name|sum_of_class_\d+)(?_reverse)?$/.match params["sort"]
+ m = /^(?
name|sum_of_class_\d+)(?_reverse)?$/.match params['sort']
if m
sort = m[:col]
sort += ' DESC' if m[:reverse]
else
- sort = "name"
+ sort = 'name'
end
@ordergroups = Ordergroup.undeleted.order(sort)
@@ -14,7 +14,7 @@ class Finance::OrdergroupsController < Finance::BaseController
@ordergroups = @ordergroups.page(params[:page]).per(@per_page)
@total_balances = FinancialTransactionClass.sorted.each_with_object({}) do |c, tmp|
- tmp[c.id] = c.financial_transactions.reduce(0) { | sum, t | sum + t.amount }
+ tmp[c.id] = c.financial_transactions.reduce(0) { |sum, t| sum + t.amount }
end
end
end
diff --git a/app/controllers/foodcoop/ordergroups_controller.rb b/app/controllers/foodcoop/ordergroups_controller.rb
index 6940a376..05dfe9cb 100644
--- a/app/controllers/foodcoop/ordergroups_controller.rb
+++ b/app/controllers/foodcoop/ordergroups_controller.rb
@@ -1,20 +1,16 @@
class Foodcoop::OrdergroupsController < ApplicationController
def index
- @ordergroups = Ordergroup.undeleted.sort_by_param(params["sort"])
+ @ordergroups = Ordergroup.undeleted.sort_by_param(params['sort'])
- unless params[:name].blank? # Search by name
- @ordergroups = @ordergroups.where('name LIKE ?', "%#{params[:name]}%")
- end
+ @ordergroups = @ordergroups.where('name LIKE ?', "%#{params[:name]}%") if params[:name].present? # Search by name
- if params[:only_active] # Select only active groups
- @ordergroups = @ordergroups.active
- end
+ @ordergroups = @ordergroups.active if params[:only_active] # Select only active groups
@ordergroups = @ordergroups.page(params[:page]).per(@per_page)
respond_to do |format|
format.html # index.html.erb
- format.js { render :layout => false }
+ format.js { render layout: false }
end
end
end
diff --git a/app/controllers/foodcoop/users_controller.rb b/app/controllers/foodcoop/users_controller.rb
index 196f1be8..5dfe0c6f 100644
--- a/app/controllers/foodcoop/users_controller.rb
+++ b/app/controllers/foodcoop/users_controller.rb
@@ -1,19 +1,22 @@
class Foodcoop::UsersController < ApplicationController
+ before_action -> { require_config_disabled :disable_members_overview }
+
def index
- @users = User.undeleted.sort_by_param(params["sort"])
+ @users = User.undeleted.sort_by_param(params['sort'])
# if somebody uses the search field:
- @users = @users.natural_search(params[:user_name]) unless params[:user_name].blank?
+ @users = @users.natural_search(params[:user_name]) if params[:user_name].present?
if params[:ordergroup_name]
- @users = @users.joins(:groups).where("groups.type = 'Ordergroup' AND groups.name LIKE ?", "%#{params[:ordergroup_name]}%")
+ @users = @users.joins(:groups).where("groups.type = 'Ordergroup' AND groups.name LIKE ?",
+ "%#{params[:ordergroup_name]}%")
end
@users = @users.page(params[:page]).per(@per_page)
respond_to do |format|
format.html # index.html.haml
- format.js { render :layout => false } # index.js.erb
+ format.js { render layout: false } # index.js.erb
end
end
end
diff --git a/app/controllers/foodcoop/workgroups_controller.rb b/app/controllers/foodcoop/workgroups_controller.rb
index e0f571be..8fd5f423 100644
--- a/app/controllers/foodcoop/workgroups_controller.rb
+++ b/app/controllers/foodcoop/workgroups_controller.rb
@@ -1,9 +1,9 @@
class Foodcoop::WorkgroupsController < ApplicationController
before_action :authenticate_membership_or_admin,
- :except => [:index]
+ except: [:index]
def index
- @workgroups = Workgroup.order("name")
+ @workgroups = Workgroup.order('name')
end
def edit
@@ -13,9 +13,9 @@ class Foodcoop::WorkgroupsController < ApplicationController
def update
@workgroup = Workgroup.find(params[:id])
if @workgroup.update(params[:workgroup])
- redirect_to foodcoop_workgroups_url, :notice => I18n.t('workgroups.update.notice')
+ redirect_to foodcoop_workgroups_url, notice: I18n.t('workgroups.update.notice')
else
- render :action => 'edit'
+ render action: 'edit'
end
end
end
diff --git a/app/controllers/group_order_articles_controller.rb b/app/controllers/group_order_articles_controller.rb
index 5aa50a87..5f58c48a 100644
--- a/app/controllers/group_order_articles_controller.rb
+++ b/app/controllers/group_order_articles_controller.rb
@@ -1,6 +1,6 @@
class GroupOrderArticlesController < ApplicationController
before_action :authenticate_finance
- before_action :find_group_order_article, except: [:new, :create]
+ before_action :find_group_order_article, except: %i[new create]
layout false # We only use this controller to server js snippets, no need for layout rendering
diff --git a/app/controllers/group_orders_controller.rb b/app/controllers/group_orders_controller.rb
index 686f0617..e5a442aa 100644
--- a/app/controllers/group_orders_controller.rb
+++ b/app/controllers/group_orders_controller.rb
@@ -3,9 +3,9 @@
class GroupOrdersController < ApplicationController
# Security
before_action :ensure_ordergroup_member
- before_action :ensure_open_order, :only => [:new, :create, :edit, :update, :order, :stock_order, :saveOrder]
- before_action :ensure_my_group_order, only: [:show, :edit, :update]
- before_action :enough_apples?, only: [:new, :create]
+ before_action :ensure_open_order, only: %i[new create edit update order stock_order saveOrder]
+ before_action :ensure_my_group_order, only: %i[show edit update]
+ before_action :enough_apples?, only: %i[new create]
# Index page.
def index
@@ -13,9 +13,17 @@ class GroupOrdersController < ApplicationController
@finished_not_closed_orders_including_group_order = Order.finished_not_closed.ordergroup_group_orders_map(@ordergroup)
end
+ def show
+ @order = @group_order.order
+ end
+
def new
ordergroup = params[:stock_order] ? nil : @ordergroup
- @group_order = @order.group_orders.build(:ordergroup => ordergroup, :updated_by => current_user)
+ @group_order = @order.group_orders.build(ordergroup: ordergroup, updated_by: current_user)
+ @ordering_data = @group_order.load_data
+ end
+
+ def edit
@ordering_data = @group_order.load_data
end
@@ -23,34 +31,26 @@ class GroupOrdersController < ApplicationController
@group_order = GroupOrder.new(params[:group_order])
begin
@group_order.save_ordering!
- redirect_to group_order_url(@group_order), :notice => I18n.t('group_orders.create.notice')
+ redirect_to group_order_url(@group_order), notice: I18n.t('group_orders.create.notice')
rescue ActiveRecord::StaleObjectError
- 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 => I18n.t('group_orders.create.error_general')
+ redirect_to group_orders_url, alert: I18n.t('group_orders.create.error_stale')
+ rescue StandardError => e
+ logger.error('Failed to update order: ' + e.message)
+ redirect_to group_orders_url, alert: I18n.t('group_orders.create.error_general')
end
end
- def show
- @order = @group_order.order
- end
-
- def edit
- @ordering_data = @group_order.load_data
- end
-
def update
@group_order.attributes = params[:group_order]
@group_order.updated_by = current_user
begin
@group_order.save_ordering!
- redirect_to group_order_url(@group_order), :notice => I18n.t('group_orders.update.notice')
+ redirect_to group_order_url(@group_order), notice: I18n.t('group_orders.update.notice')
rescue ActiveRecord::StaleObjectError
- 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 => I18n.t('group_orders.update.error_general')
+ redirect_to group_orders_url, alert: I18n.t('group_orders.update.error_stale')
+ rescue StandardError => e
+ logger.error('Failed to update order: ' + e.message)
+ redirect_to group_orders_url, alert: I18n.t('group_orders.update.error_general')
end
end
@@ -74,16 +74,16 @@ class GroupOrdersController < ApplicationController
# Used as a :before_action by OrdersController.
def ensure_ordergroup_member
@ordergroup = @current_user.ordergroup
- if @ordergroup.nil?
- redirect_to root_url, :alert => I18n.t('group_orders.errors.no_member')
- end
+ return unless @ordergroup.nil?
+
+ redirect_to root_url, alert: I18n.t('group_orders.errors.no_member')
end
def ensure_open_order
- @order = Order.includes([:supplier, :order_articles]).find(order_id_param)
+ @order = Order.includes(%i[supplier order_articles]).find(order_id_param)
unless @order.open?
flash[:notice] = I18n.t('group_orders.errors.closed')
- redirect_to :action => 'index'
+ redirect_to action: 'index'
end
rescue ActiveRecord::RecordNotFound
redirect_to group_orders_url, alert: I18n.t('group_orders.errors.notfound')
@@ -91,17 +91,17 @@ class GroupOrdersController < ApplicationController
def ensure_my_group_order
@group_order = GroupOrder.find(params[:id])
- if @group_order.ordergroup != @ordergroup && (@group_order.ordergroup || !current_user.role_orders?)
- redirect_to group_orders_url, alert: I18n.t('group_orders.errors.notfound')
- end
+ return unless @group_order.ordergroup != @ordergroup && (@group_order.ordergroup || !current_user.role_orders?)
+
+ redirect_to group_orders_url, alert: I18n.t('group_orders.errors.notfound')
end
def enough_apples?
- if @ordergroup.not_enough_apples?
- redirect_to group_orders_url,
- alert: t('not_enough_apples', scope: 'group_orders.messages', apples: @ordergroup.apples,
- stop_ordering_under: FoodsoftConfig[:stop_ordering_under])
- end
+ return unless @ordergroup.not_enough_apples?
+
+ redirect_to group_orders_url,
+ alert: t('not_enough_apples', scope: 'group_orders.messages', apples: @ordergroup.apples,
+ stop_ordering_under: FoodsoftConfig[:stop_ordering_under])
end
def order_id_param
diff --git a/app/controllers/home_controller.rb b/app/controllers/home_controller.rb
index d01a78ca..f40fb6fb 100644
--- a/app/controllers/home_controller.rb
+++ b/app/controllers/home_controller.rb
@@ -9,8 +9,7 @@ class HomeController < ApplicationController
@unassigned_tasks = Task.order(:due_date).next_unassigned_tasks_for(current_user)
end
- def profile
- end
+ def profile; end
def reference_calculator
if current_user.ordergroup
@@ -18,7 +17,7 @@ class HomeController < ApplicationController
@bank_accounts = @types.includes(:bank_account).map(&:bank_account).uniq.compact
@bank_accounts = [BankAccount.last] if @bank_accounts.empty?
else
- redirect_to root_path, alert: I18n.t('group_orders.errors.no_member')
+ redirect_to root_url, alert: I18n.t('group_orders.errors.no_member')
end
end
@@ -26,7 +25,7 @@ class HomeController < ApplicationController
if @current_user.update(user_params)
@current_user.ordergroup.update(ordergroup_params) if ordergroup_params
session[:locale] = @current_user.locale
- redirect_to my_profile_path, notice: I18n.t('home.changes_saved')
+ redirect_to my_profile_url, notice: I18n.t('home.changes_saved')
else
render :profile
end
@@ -36,40 +35,43 @@ class HomeController < ApplicationController
@user = @current_user
@ordergroup = @user.ordergroup
- unless @ordergroup.nil?
+ if @ordergroup.nil?
+ redirect_to root_path, alert: I18n.t('home.no_ordergroups')
+ else
@ordergroup = Ordergroup.include_transaction_class_sum.find(@ordergroup.id)
- if params['sort']
- sort = case params['sort']
- when "date" then "created_on"
- when "note" then "note"
- when "amount" then "amount"
- when "date_reverse" then "created_on DESC"
- when "note_reverse" then "note DESC"
- when "amount_reverse" then "amount DESC"
+ sort = if params['sort']
+ case params['sort']
+ when 'date' then 'created_on'
+ when 'note' then 'note'
+ when 'amount' then 'amount'
+ when 'date_reverse' then 'created_on DESC'
+ when 'note_reverse' then 'note DESC'
+ when 'amount_reverse' then 'amount DESC'
end
- else
- sort = "created_on DESC"
- end
+ else
+ 'created_on DESC'
+ end
@financial_transactions = @ordergroup.financial_transactions.visible.page(params[:page]).per(@per_page).order(sort)
- @financial_transactions = @financial_transactions.where('financial_transactions.note LIKE ?', "%#{params[:query]}%") if params[:query].present?
+ if params[:query].present?
+ @financial_transactions = @financial_transactions.where('financial_transactions.note LIKE ?',
+ "%#{params[:query]}%")
+ end
- else
- redirect_to root_path, alert: I18n.t('home.no_ordergroups')
end
end
# cancel personal memberships direct from the myProfile-page
def cancel_membership
- if params[:membership_id]
- membership = @current_user.memberships.find(params[:membership_id])
- else
- membership = @current_user.memberships.find_by_group_id!(params[:group_id])
- end
+ membership = if params[:membership_id]
+ @current_user.memberships.find(params[:membership_id])
+ else
+ @current_user.memberships.find_by_group_id!(params[:group_id])
+ end
membership.destroy
- redirect_to my_profile_path, notice: I18n.t('home.ordergroup_cancelled', :group => membership.group.name)
+ redirect_to my_profile_path, notice: I18n.t('home.ordergroup_cancelled', group: membership.group.name)
end
protected
@@ -82,8 +84,8 @@ class HomeController < ApplicationController
end
def ordergroup_params
- if params[:user][:ordergroup]
- params.require(:user).require(:ordergroup).permit(:contact_address)
- end
+ return unless params[:user][:ordergroup]
+
+ params.require(:user).require(:ordergroup).permit(:contact_address)
end
end
diff --git a/app/controllers/invites_controller.rb b/app/controllers/invites_controller.rb
index 37fc757b..266a1de5 100644
--- a/app/controllers/invites_controller.rb
+++ b/app/controllers/invites_controller.rb
@@ -3,7 +3,7 @@ class InvitesController < ApplicationController
before_action -> { require_config_disabled :disable_invite }
def new
- @invite = Invite.new(:user => @current_user, :group => @group)
+ @invite = Invite.new(user: @current_user, group: @group)
end
def create
@@ -27,6 +27,10 @@ class InvitesController < ApplicationController
protected
def authenticate_membership_or_admin_for_invites
- authenticate_membership_or_admin((params[:invite][:group_id] rescue params[:id]))
+ authenticate_membership_or_admin(begin
+ params[:invite][:group_id]
+ rescue StandardError
+ params[:id]
+ end)
end
end
diff --git a/app/controllers/login_controller.rb b/app/controllers/login_controller.rb
index 052231c5..4c2fd95b 100644
--- a/app/controllers/login_controller.rb
+++ b/app/controllers/login_controller.rb
@@ -1,6 +1,6 @@
class LoginController < ApplicationController
skip_before_action :authenticate # no authentication since this is the login page
- before_action :validate_token, :only => [:new_password, :update_password]
+ before_action :validate_token, only: %i[new_password update_password]
# Display the form to enter an email address requesting a token to set a new password.
def forgot_password
@@ -9,20 +9,17 @@ 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: I18n.t('errors.general_again') and return
- end
+ redirect_to forgot_password_url, alert: I18n.t('errors.general_again') and return if request.get? || params[:user].nil? # Catch for get request and give better error message.
if (user = User.undeleted.find_by_email(params[:user][:email]))
user.request_password_reset!
end
- redirect_to login_url, :notice => I18n.t('login.controller.reset_password.notice')
+ 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.
# Called with params :id => User.id and :token => User.reset_password_token to specify a new password.
- def new_password
- end
+ def new_password; end
# Sets a new password.
# Called with params :id => User.id and :token => User.reset_password_token to specify a new password.
@@ -32,7 +29,7 @@ class LoginController < ApplicationController
@user.reset_password_token = nil
@user.reset_password_expires = nil
@user.save
- redirect_to login_url, :notice => I18n.t('login.controller.update_password.notice')
+ redirect_to login_url, notice: I18n.t('login.controller.update_password.notice')
else
render :new_password
end
@@ -50,14 +47,14 @@ class LoginController < ApplicationController
@user = User.new(params[:user])
@user.email = @invite.email
if @user.save
- Membership.new(:user => @user, :group => @invite.group).save!
+ Membership.new(user: @user, group: @invite.group).save!
@invite.destroy
session[:locale] = @user.locale
redirect_to login_url, notice: I18n.t('login.controller.accept_invitation.notice')
end
end
else
- @user = User.new(:email => @invite.email)
+ @user = User.new(email: @invite.email)
end
end
@@ -65,8 +62,8 @@ 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)
- redirect_to forgot_password_url, alert: I18n.t('login.controller.error_token_invalid')
- end
+ return unless @user.nil? || @user.reset_password_expires < Time.now
+
+ redirect_to forgot_password_url, alert: I18n.t('login.controller.error_token_invalid')
end
end
diff --git a/app/controllers/order_articles_controller.rb b/app/controllers/order_articles_controller.rb
index 0552269d..43a0ea14 100644
--- a/app/controllers/order_articles_controller.rb
+++ b/app/controllers/order_articles_controller.rb
@@ -1,7 +1,7 @@
class OrderArticlesController < ApplicationController
before_action :fetch_order, except: :destroy
- before_action :authenticate_finance_or_invoices, except: [:new, :create]
- before_action :authenticate_finance_orders_or_pickup, except: [:edit, :update, :destroy]
+ before_action :authenticate_finance_or_invoices, except: %i[new create]
+ before_action :authenticate_finance_orders_or_pickup, except: %i[edit update destroy]
layout false # We only use this controller to serve js snippets, no need for layout rendering
@@ -9,28 +9,26 @@ class OrderArticlesController < ApplicationController
@order_article = @order.order_articles.build(params[:order_article])
end
+ def edit
+ @order_article = OrderArticle.find(params[:id])
+ end
+
def create
# The article may be ordered with zero units - in that case do not complain.
# If order_article is ordered and a new order_article is created, an error message will be
# given mentioning that the article already exists, which is desired.
- @order_article = @order.order_articles.where(:article_id => params[:order_article][:article_id]).first
- unless @order_article && @order_article.units_to_order == 0
- @order_article = @order.order_articles.build(params[:order_article])
- end
+ @order_article = @order.order_articles.where(article_id: params[:order_article][:article_id]).first
+ @order_article = @order.order_articles.build(params[:order_article]) unless @order_article && @order_article.units_to_order == 0
@order_article.save!
- rescue
+ rescue StandardError
render action: :new
end
- def edit
- @order_article = OrderArticle.find(params[:id])
- end
-
def update
@order_article = OrderArticle.find(params[:id])
begin
@order_article.update_article_and_price!(params[:order_article], params[:article], params[:article_price])
- rescue
+ rescue StandardError
render action: :edit
end
end
diff --git a/app/controllers/order_comments_controller.rb b/app/controllers/order_comments_controller.rb
index 39067577..3583bb0e 100644
--- a/app/controllers/order_comments_controller.rb
+++ b/app/controllers/order_comments_controller.rb
@@ -1,15 +1,15 @@
class OrderCommentsController < ApplicationController
def new
@order = Order.find(params[:order_id])
- @order_comment = @order.comments.build(:user => current_user)
+ @order_comment = @order.comments.build(user: current_user)
end
def create
@order_comment = OrderComment.new(params[:order_comment])
if @order_comment.save
- render :layout => false
+ render layout: false
else
- render :action => :new, :layout => false
+ render action: :new, layout: false
end
end
end
diff --git a/app/controllers/orders_controller.rb b/app/controllers/orders_controller.rb
index 1e041bf2..bc2d9195 100644
--- a/app/controllers/orders_controller.rb
+++ b/app/controllers/orders_controller.rb
@@ -5,25 +5,26 @@ class OrdersController < ApplicationController
include Concerns::SendOrderPdf
before_action :authenticate_pickups_or_orders
- before_action :authenticate_orders, except: [:receive, :receive_on_order_article_create, :receive_on_order_article_update, :show]
- before_action :remove_empty_article, only: [:create, :update]
+ before_action :authenticate_orders,
+ except: %i[receive receive_on_order_article_create receive_on_order_article_update show]
+ before_action :remove_empty_article, only: %i[create update]
# List orders
def index
@open_orders = Order.open.includes(:supplier)
@finished_orders = Order.finished_not_closed.includes(:supplier)
@per_page = 15
- if params['sort']
- sort = case params['sort']
- when "supplier" then "suppliers.name, ends DESC"
- when "pickup" then "pickup DESC"
- when "ends" then "ends DESC"
- when "supplier_reverse" then "suppliers.name DESC"
- when "ends_reverse" then "ends"
+ sort = if params['sort']
+ case params['sort']
+ when 'supplier' then 'suppliers.name, ends DESC'
+ when 'pickup' then 'pickup DESC'
+ when 'ends' then 'ends DESC'
+ when 'supplier_reverse' then 'suppliers.name DESC'
+ when 'ends_reverse' then 'ends'
end
- else
- sort = "ends DESC"
- end
+ else
+ 'ends DESC'
+ end
@suppliers = Supplier.having_articles.order('suppliers.name')
@orders = Order.closed.includes(:supplier).reorder(sort).page(params[:page]).per(@per_page)
end
@@ -43,13 +44,13 @@ class OrdersController < ApplicationController
respond_to do |format|
format.html
format.js do
- render :layout => false
+ render layout: false
end
format.pdf do
send_order_pdf @order, params[:document]
end
format.csv do
- send_data OrderCsv.new(@order, options= {custom_csv: params[:custom_csv]}).to_csv, filename: @order.name + '.csv', type: 'text/csv'
+ send_data OrderCsv.new(@order).to_csv, filename: @order.name + '.csv', type: 'text/csv'
end
format.text do
send_data OrderTxt.new(@order).to_txt, filename: @order.name + '.txt', type: 'text/plain'
@@ -57,19 +58,6 @@ class OrdersController < ApplicationController
end
end
- def custom_csv
- @order = Order.find(params[:id])
- @view = (params[:view] || 'default').gsub(/[^-_a-zA-Z0-9]/, '')
- @partial = case @view
- when 'default' then 'articles'
- when 'groups' then 'shared/articles_by/groups'
- when 'articles' then 'shared/articles_by/articles'
- else 'articles'
- end
-
- render :layout => false
- end
-
# Page to create a new order.
def new
if params[:order_id]
@@ -79,8 +67,14 @@ class OrdersController < ApplicationController
else
@order = Order.new(supplier_id: params[:supplier_id]).init_dates
end
- rescue => error
- redirect_to orders_url, alert: t('errors.general_msg', msg: error.message)
+ rescue StandardError => e
+ redirect_to orders_url, alert: t('errors.general_msg', msg: e.message)
+ end
+
+ # Page to edit an exsiting order.
+ # editing finished orders is done in FinanceController
+ def edit
+ @order = Order.includes(:articles).find(params[:id])
end
# Save a new order.
@@ -94,31 +88,25 @@ class OrdersController < ApplicationController
redirect_to @order
else
logger.debug "[debug] order errors: #{@order.errors.messages}"
- render :action => 'new'
+ render action: 'new'
end
end
- # Page to edit an exsiting order.
- # editing finished orders is done in FinanceController
- def edit
- @order = Order.includes(:articles).find(params[:id])
- end
-
# Update an existing order.
def update
@order = Order.find params[:id]
if @order.update(params[:order].merge(updated_by: current_user))
flash[:notice] = I18n.t('orders.update.notice')
- redirect_to :action => 'show', :id => @order
+ redirect_to action: 'show', id: @order
else
- render :action => 'edit'
+ render action: 'edit'
end
end
# Delete an order.
def destroy
Order.find(params[:id]).destroy
- redirect_to :action => 'index'
+ redirect_to action: 'index'
end
# Finish a current order.
@@ -126,8 +114,8 @@ class OrdersController < ApplicationController
order = Order.find(params[:id])
order.finish!(@current_user)
redirect_to order, notice: I18n.t('orders.finish.notice')
- rescue => error
- redirect_to orders_url, alert: I18n.t('errors.general_msg', :msg => error.message)
+ rescue StandardError => e
+ redirect_to orders_url, alert: I18n.t('errors.general_msg', msg: e.message)
end
# Send a order to the supplier.
@@ -135,20 +123,18 @@ class OrdersController < ApplicationController
order = Order.find(params[:id])
order.send_to_supplier!(@current_user)
redirect_to order, notice: I18n.t('orders.send_to_supplier.notice')
- rescue => error
- redirect_to order, alert: I18n.t('errors.general_msg', :msg => error.message)
+ rescue StandardError => e
+ redirect_to order, alert: I18n.t('errors.general_msg', msg: e.message)
end
def receive
@order = Order.find(params[:id])
- unless request.post?
- @order_articles = @order.order_articles.ordered_or_member.includes(:article).order('articles.order_number, articles.name')
- else
+ if request.post?
Order.transaction do
s = update_order_amounts
@order.update_attribute(:state, 'received') if @order.state != 'received'
- flash[:notice] = (s ? I18n.t('orders.receive.notice', :msg => s) : I18n.t('orders.receive.notice_none'))
+ flash[:notice] = (s ? I18n.t('orders.receive.notice', msg: s) : I18n.t('orders.receive.notice_none'))
end
NotifyReceivedOrderJob.perform_later(@order)
if current_user.role_orders? || current_user.role_finance?
@@ -158,23 +144,25 @@ class OrdersController < ApplicationController
else
redirect_to receive_order_path(@order)
end
+ else
+ @order_articles = @order.order_articles.ordered_or_member.includes(:article).order('articles.order_number, articles.name')
end
end
def receive_on_order_article_create # See publish/subscribe design pattern in /doc.
@order_article = OrderArticle.find(params[:order_article_id])
- render :layout => false
+ render layout: false
end
def receive_on_order_article_update # See publish/subscribe design pattern in /doc.
@order_article = OrderArticle.find(params[:order_article_id])
- render :layout => false
+ render layout: false
end
protected
def update_order_amounts
- return if not params[:order_articles]
+ return unless params[:order_articles]
# where to leave remainder during redistribution
rest_to = []
@@ -189,35 +177,42 @@ class OrdersController < ApplicationController
# "MySQL lock timeout exceeded" errors. It's ok to do
# this article-by-article anway.
params[:order_articles].each do |oa_id, oa_params|
- unless oa_params.blank?
- oa = OrderArticle.find(oa_id)
- # update attributes; don't use update_attribute because it calls save
- # which makes received_changed? not work anymore
- oa.attributes = oa_params
- if oa.units_received_changed?
- counts[0] += 1
- unless oa.units_received.blank?
- cunits[0] += oa.units_received * oa.article.unit_quantity
- oacounts = oa.redistribute oa.units_received * oa.price.unit_quantity, rest_to
- oacounts.each_with_index { |c, i| cunits[i + 1] += c; counts[i + 1] += 1 if c > 0 }
+ next if oa_params.blank?
+
+ oa = OrderArticle.find(oa_id)
+ # update attributes; don't use update_attribute because it calls save
+ # which makes received_changed? not work anymore
+ oa.attributes = oa_params
+ if oa.units_received_changed?
+ counts[0] += 1
+ if oa.units_received.present?
+ cunits[0] += oa.units_received * oa.article.unit_quantity
+ oacounts = oa.redistribute oa.units_received * oa.price.unit_quantity, rest_to
+ oacounts.each_with_index do |c, i|
+ cunits[i + 1] += c
+ counts[i + 1] += 1 if c > 0
end
end
- oa.save!
end
+ oa.save!
end
return nil if counts[0] == 0
notice = []
notice << I18n.t('orders.update_order_amounts.msg1', count: counts[0], units: cunits[0])
- notice << I18n.t('orders.update_order_amounts.msg2', count: counts[1], units: cunits[1]) if params[:rest_to_tolerance]
+ if params[:rest_to_tolerance]
+ notice << I18n.t('orders.update_order_amounts.msg2', count: counts[1],
+ units: cunits[1])
+ end
notice << I18n.t('orders.update_order_amounts.msg3', count: counts[2], units: cunits[2]) if params[:rest_to_stock]
if counts[3] > 0 || cunits[3] > 0
- notice << I18n.t('orders.update_order_amounts.msg4', count: counts[3], units: cunits[3])
+ notice << I18n.t('orders.update_order_amounts.msg4', count: counts[3],
+ units: cunits[3])
end
notice.join(', ')
end
def remove_empty_article
- params[:order][:article_ids].reject!(&:blank?) if params[:order] && params[:order][:article_ids]
+ params[:order][:article_ids].compact_blank! if params[:order] && params[:order][:article_ids]
end
end
diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb
index 5b3d0780..22750360 100644
--- a/app/controllers/sessions_controller.rb
+++ b/app/controllers/sessions_controller.rb
@@ -12,16 +12,20 @@ class SessionsController < ApplicationController
user = User.authenticate(params[:nick], params[:password])
if user
user.update_attribute(:last_login, Time.now)
- login_and_redirect_to_return_to user, :notice => I18n.t('sessions.logged_in')
+ login_and_redirect_to_return_to user, notice: I18n.t('sessions.logged_in')
else
flash.now.alert = I18n.t(FoodsoftConfig[:use_nick] ? 'sessions.login_invalid_nick' : 'sessions.login_invalid_email')
- render "new"
+ render 'new'
end
end
def destroy
logout
- redirect_to login_url, :notice => I18n.t('sessions.logged_out')
+ if FoodsoftConfig[:logout_redirect_url].present?
+ redirect_to FoodsoftConfig[:logout_redirect_url]
+ else
+ redirect_to login_url, notice: I18n.t('sessions.logged_out')
+ end
end
# redirect to root, going to default foodcoop when none given
diff --git a/app/controllers/stock_takings_controller.rb b/app/controllers/stock_takings_controller.rb
index bdf1dc77..e12af6f9 100644
--- a/app/controllers/stock_takings_controller.rb
+++ b/app/controllers/stock_takings_controller.rb
@@ -7,21 +7,21 @@ class StockTakingsController < ApplicationController
def new
@stock_taking = StockTaking.new
- StockArticle.undeleted.each { |a| @stock_taking.stock_changes.build(:stock_article => a) }
+ StockArticle.undeleted.each { |a| @stock_taking.stock_changes.build(stock_article: a) }
end
def new_on_stock_article_create # See publish/subscribe design pattern in /doc.
stock_article = StockArticle.find(params[:stock_article_id])
- @stock_change = StockChange.new(:stock_article => stock_article)
+ @stock_change = StockChange.new(stock_article: stock_article)
- render :layout => false
+ render layout: false
end
def create
- create!(:notice => I18n.t('stock_takings.create.notice'))
+ create!(notice: I18n.t('stock_takings.create.notice'))
end
def update
- update!(:notice => I18n.t('stock_takings.update.notice'))
+ update!(notice: I18n.t('stock_takings.update.notice'))
end
end
diff --git a/app/controllers/stockit_controller.rb b/app/controllers/stockit_controller.rb
index 6dd1511e..8f9b3b3d 100644
--- a/app/controllers/stockit_controller.rb
+++ b/app/controllers/stockit_controller.rb
@@ -7,57 +7,13 @@ class StockitController < ApplicationController
def index_on_stock_article_create # See publish/subscribe design pattern in /doc.
@stock_article = StockArticle.find(params[:id])
- render :layout => false
+ render layout: false
end
def index_on_stock_article_update # See publish/subscribe design pattern in /doc.
@stock_article = StockArticle.find(params[:id])
- render :layout => false
- end
-
- # three possibilites to fill a new_stock_article form
- # (1) start from blank or use params
- def new
- @stock_article = StockArticle.new(params[:stock_article])
-
- render :layout => false
- end
-
- # (2) StockArticle as template
- def copy
- @stock_article = StockArticle.find(params[:stock_article_id]).dup
-
- render :layout => false
- end
-
- # (3) non-stock Article as template
- def derive
- @stock_article = Article.find(params[:old_article_id]).becomes(StockArticle).dup
-
- render :layout => false
- end
-
- def create
- @stock_article = StockArticle.new({ quantity: 0 }.merge(params[:stock_article]))
- @stock_article.save!
- render :layout => false
- rescue ActiveRecord::RecordInvalid
- render :action => 'new', :layout => false
- end
-
- def edit
- @stock_article = StockArticle.find(params[:id])
-
- render :layout => false
- end
-
- def update
- @stock_article = StockArticle.find(params[:id])
- @stock_article.update!(params[:stock_article])
- render :layout => false
- rescue ActiveRecord::RecordInvalid
- render :action => 'edit', :layout => false
+ render layout: false
end
def show
@@ -65,24 +21,68 @@ class StockitController < ApplicationController
@stock_changes = @stock_article.stock_changes.order('stock_changes.created_at DESC')
end
+ # three possibilites to fill a new_stock_article form
+ # (1) start from blank or use params
+ def new
+ @stock_article = StockArticle.new(params[:stock_article])
+
+ render layout: false
+ end
+
+ # (2) StockArticle as template
+ def copy
+ @stock_article = StockArticle.find(params[:stock_article_id]).dup
+
+ render layout: false
+ end
+
+ # (3) non-stock Article as template
+ def derive
+ @stock_article = Article.find(params[:old_article_id]).becomes(StockArticle).dup
+
+ render layout: false
+ end
+
+ def edit
+ @stock_article = StockArticle.find(params[:id])
+
+ render layout: false
+ end
+
+ def create
+ @stock_article = StockArticle.new({ quantity: 0 }.merge(params[:stock_article]))
+ @stock_article.save!
+ render layout: false
+ rescue ActiveRecord::RecordInvalid
+ render action: 'new', layout: false
+ end
+
+ def update
+ @stock_article = StockArticle.find(params[:id])
+ @stock_article.update!(params[:stock_article])
+ render layout: false
+ rescue ActiveRecord::RecordInvalid
+ render action: 'edit', layout: false
+ end
+
def show_on_stock_article_update # See publish/subscribe design pattern in /doc.
@stock_article = StockArticle.find(params[:id])
- render :layout => false
+ render layout: false
end
def destroy
@stock_article = StockArticle.find(params[:id])
@stock_article.mark_as_deleted
- render :layout => false
- rescue => error
- render :partial => "destroy_fail", :layout => false,
- :locals => { :fail_msg => I18n.t('errors.general_msg', :msg => error.message) }
+ render layout: false
+ rescue StandardError => e
+ render partial: 'destroy_fail', layout: false,
+ locals: { fail_msg: I18n.t('errors.general_msg', msg: e.message) }
end
# TODO: Fix this!!
def articles_search
@articles = Article.not_in_stock.limit(8).where('name LIKE ?', "%#{params[:term]}%")
- render :json => @articles.map(&:name)
+ render json: @articles.map(&:name)
end
end
diff --git a/app/controllers/styles_controller.rb b/app/controllers/styles_controller.rb
index 5636ec03..6d3a9fd1 100644
--- a/app/controllers/styles_controller.rb
+++ b/app/controllers/styles_controller.rb
@@ -9,7 +9,7 @@ class StylesController < ApplicationController
def foodcoop
css = FoodsoftConfig[:custom_css]
if css.blank?
- render body: nil, content_type: 'text/css', status: 404
+ render body: nil, content_type: 'text/css', status: :not_found
else
expires_in 1.week, public: true if params[:md5].present?
render body: css, content_type: 'text/css'
diff --git a/app/controllers/suppliers_controller.rb b/app/controllers/suppliers_controller.rb
index e5188f8b..1f1e055d 100644
--- a/app/controllers/suppliers_controller.rb
+++ b/app/controllers/suppliers_controller.rb
@@ -1,5 +1,5 @@
class SuppliersController < ApplicationController
- before_action :authenticate_suppliers, :except => [:index, :list]
+ before_action :authenticate_suppliers, except: %i[index list]
helper :deliveries
def index
@@ -24,6 +24,10 @@ class SuppliersController < ApplicationController
end
end
+ def edit
+ @supplier = Supplier.find(params[:id])
+ end
+
def create
@supplier = Supplier.new(supplier_params)
@supplier.supplier_category ||= SupplierCategory.first
@@ -31,21 +35,17 @@ class SuppliersController < ApplicationController
flash[:notice] = I18n.t('suppliers.create.notice')
redirect_to suppliers_path
else
- render :action => 'new'
+ render action: 'new'
end
end
- def edit
- @supplier = Supplier.find(params[:id])
- end
-
def update
@supplier = Supplier.find(params[:id])
if @supplier.update(supplier_params)
flash[:notice] = I18n.t('suppliers.update.notice')
redirect_to @supplier
else
- render :action => 'edit'
+ render action: 'edit'
end
end
@@ -54,8 +54,8 @@ class SuppliersController < ApplicationController
@supplier.mark_as_deleted
flash[:notice] = I18n.t('suppliers.destroy.notice')
redirect_to suppliers_path
- rescue => e
- flash[:error] = I18n.t('errors.general_msg', :msg => e.message)
+ rescue StandardError => e
+ flash[:error] = I18n.t('errors.general_msg', msg: e.message)
redirect_to @supplier
end
diff --git a/app/controllers/tasks_controller.rb b/app/controllers/tasks_controller.rb
index db4ca1ab..352c71ae 100644
--- a/app/controllers/tasks_controller.rb
+++ b/app/controllers/tasks_controller.rb
@@ -11,35 +11,33 @@ class TasksController < ApplicationController
@accepted_tasks = Task.accepted_tasks_for(current_user)
end
- def new
- @task = Task.new(current_user_id: current_user.id)
- end
-
- def create
- @task = Task.new(current_user_id: current_user.id)
- @task.created_by = current_user
- @task.attributes = (task_params)
- if params[:periodic]
- @task.periodic_task_group = PeriodicTaskGroup.new
- end
- if @task.save
- @task.periodic_task_group.create_tasks_for_upfront_days if params[:periodic]
- redirect_to tasks_url, :notice => I18n.t('tasks.create.notice')
- else
- render :template => "tasks/new"
- end
- end
-
def show
@task = Task.find(params[:id])
end
+ def new
+ @task = Task.new(current_user_id: current_user.id)
+ end
+
def edit
@task = Task.find(params[:id])
@periodic = !!params[:periodic]
@task.current_user_id = current_user.id
end
+ def create
+ @task = Task.new(current_user_id: current_user.id)
+ @task.created_by = current_user
+ @task.attributes = (task_params)
+ @task.periodic_task_group = PeriodicTaskGroup.new if params[:periodic]
+ if @task.save
+ @task.periodic_task_group.create_tasks_for_upfront_days if params[:periodic]
+ redirect_to tasks_url, notice: I18n.t('tasks.create.notice')
+ else
+ render template: 'tasks/new'
+ end
+ end
+
def update
@task = Task.find(params[:id])
task_group = @task.periodic_task_group
@@ -50,16 +48,14 @@ class TasksController < ApplicationController
if @task.errors.empty? && @task.save
task_group.update_tasks_including(@task, prev_due_date) if params[:periodic]
flash[:notice] = I18n.t('tasks.update.notice')
- if was_periodic && !@task.periodic?
- flash[:notice] = I18n.t('tasks.update.notice_converted')
- end
+ flash[:notice] = I18n.t('tasks.update.notice_converted') if was_periodic && !@task.periodic?
if @task.workgroup
redirect_to workgroup_tasks_url(workgroup_id: @task.workgroup_id)
else
redirect_to tasks_url
end
else
- render :template => "tasks/edit"
+ render template: 'tasks/edit'
end
end
@@ -75,7 +71,7 @@ class TasksController < ApplicationController
end
task.update_ordergroup_stats(user_ids)
- redirect_to tasks_url, :notice => I18n.t('tasks.destroy.notice')
+ redirect_to tasks_url, notice: I18n.t('tasks.destroy.notice')
end
# assign current_user to the task and set the assignment to "accepted"
@@ -85,20 +81,20 @@ class TasksController < ApplicationController
if ass = task.is_assigned?(current_user)
ass.update_attribute(:accepted, true)
else
- task.assignments.create(:user => current_user, :accepted => true)
+ task.assignments.create(user: current_user, accepted: true)
end
- redirect_to user_tasks_path, :notice => I18n.t('tasks.accept.notice')
+ redirect_to user_tasks_path, notice: I18n.t('tasks.accept.notice')
end
# deletes assignment between current_user and given taskcurrent_user_id: current_user.id
def reject
Task.find(params[:id]).users.delete(current_user)
- redirect_to :action => "index"
+ redirect_to action: 'index'
end
def set_done
Task.find(params[:id]).update_attribute :done, true
- redirect_to tasks_url, :notice => I18n.t('tasks.set_done.notice')
+ redirect_to tasks_url, notice: I18n.t('tasks.set_done.notice')
end
# Shows all tasks, which are already done
@@ -109,9 +105,9 @@ class TasksController < ApplicationController
# shows workgroup (normal group) to edit weekly_tasks_template
def workgroup
@group = Group.find(params[:workgroup_id])
- if @group.is_a? Ordergroup
- redirect_to tasks_url, :alert => I18n.t('tasks.error_not_found')
- end
+ return unless @group.is_a? Ordergroup
+
+ redirect_to tasks_url, alert: I18n.t('tasks.error_not_found')
end
private
diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb
index 503bc79b..df56ade0 100644
--- a/app/controllers/users_controller.rb
+++ b/app/controllers/users_controller.rb
@@ -3,7 +3,7 @@ class UsersController < ApplicationController
def index
@users = User.undeleted.natural_search(params[:q])
respond_to do |format|
- format.json { render :json => @users.map(&:token_attributes).to_json }
+ format.json { render json: @users.map(&:token_attributes).to_json }
end
end
end
diff --git a/app/documents/order_by_articles.rb b/app/documents/order_by_articles.rb
index 84fb5c00..b1a68a11 100644
--- a/app/documents/order_by_articles.rb
+++ b/app/documents/order_by_articles.rb
@@ -1,11 +1,11 @@
class OrderByArticles < OrderPdf
def filename
- I18n.t('documents.order_by_articles.filename', :name => order.name, :date => order.ends.to_date) + '.pdf'
+ I18n.t('documents.order_by_articles.filename', name: order.name, date: order.ends.to_date) + '.pdf'
end
def title
- I18n.t('documents.order_by_articles.title', :name => order.name,
- :date => order.ends.strftime(I18n.t('date.formats.default')))
+ I18n.t('documents.order_by_articles.title', name: order.name,
+ date: order.ends.strftime(I18n.t('date.formats.default')))
end
def body
diff --git a/app/documents/order_by_groups.rb b/app/documents/order_by_groups.rb
index d6711731..e5a72c35 100644
--- a/app/documents/order_by_groups.rb
+++ b/app/documents/order_by_groups.rb
@@ -1,11 +1,11 @@
class OrderByGroups < OrderPdf
def filename
- I18n.t('documents.order_by_groups.filename', :name => order.name, :date => order.ends.to_date) + '.pdf'
+ I18n.t('documents.order_by_groups.filename', name: order.name, date: order.ends.to_date) + '.pdf'
end
def title
- I18n.t('documents.order_by_groups.title', :name => order.name,
- :date => order.ends.strftime(I18n.t('date.formats.default')))
+ I18n.t('documents.order_by_groups.title', name: order.name,
+ date: order.ends.strftime(I18n.t('date.formats.default')))
end
def body
diff --git a/app/documents/order_fax.rb b/app/documents/order_fax.rb
index b4b50577..e881c93f 100644
--- a/app/documents/order_fax.rb
+++ b/app/documents/order_fax.rb
@@ -2,7 +2,7 @@ class OrderFax < OrderPdf
BATCH_SIZE = 250
def filename
- I18n.t('documents.order_fax.filename', :name => order.name, :date => order.ends.to_date) + '.pdf'
+ I18n.t('documents.order_fax.filename', name: order.name, date: order.ends.to_date) + '.pdf'
end
def title
@@ -20,16 +20,18 @@ class OrderFax < OrderPdf
move_down 5
text "#{contact[:zip_code]} #{contact[:city]}", size: fontsize(9), align: :right
move_down 5
- unless order.supplier.try(:customer_number).blank?
- text "#{Supplier.human_attribute_name :customer_number}: #{order.supplier[:customer_number]}", size: fontsize(9), align: :right
+ if order.supplier.try(:customer_number).present?
+ text "#{Supplier.human_attribute_name :customer_number}: #{order.supplier[:customer_number]}",
+ size: fontsize(9), align: :right
move_down 5
end
- unless contact[:phone].blank?
+ if contact[:phone].present?
text "#{Supplier.human_attribute_name :phone}: #{contact[:phone]}", size: fontsize(9), align: :right
move_down 5
end
- unless contact[:email].blank?
- text "#{Supplier.human_attribute_name :email}: #{contact[:email]}", size: fontsize(9), align: :right
+ if contact[:email].present?
+ text "#{Supplier.human_attribute_name :email}: #{contact[:email]}", size: fontsize(9),
+ align: :right
end
end
@@ -38,7 +40,7 @@ class OrderFax < OrderPdf
text order.name
move_down 5
text order.supplier.try(:address).to_s
- unless order.supplier.try(:fax).blank?
+ if order.supplier.try(:fax).present?
move_down 5
text "#{Supplier.human_attribute_name :fax}: #{order.supplier[:fax]}"
end
@@ -50,7 +52,7 @@ class OrderFax < OrderPdf
move_down 10
text "#{Delivery.human_attribute_name :date}:"
move_down 10
- unless order.supplier.try(:contact_person).blank?
+ if order.supplier.try(:contact_person).present?
text "#{Supplier.human_attribute_name :contact_person}: #{order.supplier[:contact_person]}"
move_down 10
end
@@ -78,8 +80,8 @@ class OrderFax < OrderPdf
table.row(0).border_bottom_width = 2
table.columns(1).align = :right
table.columns(3..6).align = :right
- table.row(data.length - 1).columns(0..5).borders = [:top, :bottom]
- table.row(data.length - 1).columns(0).borders = [:top, :bottom, :left]
+ table.row(data.length - 1).columns(0..5).borders = %i[top bottom]
+ table.row(data.length - 1).columns(0).borders = %i[top bottom left]
table.row(data.length - 1).border_top_width = 2
end
# font_size: fontsize(8),
@@ -98,7 +100,7 @@ class OrderFax < OrderPdf
.preload(:article, :article_price)
end
- def each_order_article
- order_articles.find_each_with_order(batch_size: BATCH_SIZE) { |oa| yield oa }
+ def each_order_article(&block)
+ order_articles.find_each_with_order(batch_size: BATCH_SIZE, &block)
end
end
diff --git a/app/documents/order_matrix.rb b/app/documents/order_matrix.rb
index 7269feaf..c45ca5fd 100644
--- a/app/documents/order_matrix.rb
+++ b/app/documents/order_matrix.rb
@@ -3,12 +3,12 @@ class OrderMatrix < OrderPdf
PLACEHOLDER_CHAR = 'X'
def filename
- I18n.t('documents.order_matrix.filename', :name => @order.name, :date => @order.ends.to_date) + '.pdf'
+ I18n.t('documents.order_matrix.filename', name: @order.name, date: @order.ends.to_date) + '.pdf'
end
def title
- I18n.t('documents.order_matrix.title', :name => @order.name,
- :date => @order.ends.strftime(I18n.t('date.formats.default')))
+ I18n.t('documents.order_matrix.title', name: @order.name,
+ date: @order.ends.strftime(I18n.t('date.formats.default')))
end
def body
@@ -87,7 +87,7 @@ class OrderMatrix < OrderPdf
table.cells.border_width = 0.5
table.cells.border_color = '666666'
- table.row(0).borders = [:bottom, :left]
+ table.row(0).borders = %i[bottom left]
table.row(0).padding = [2, 0, 2, 0]
table.row(1..-1).height = row_height_1
table.column(0..1).borders = []
@@ -106,7 +106,7 @@ class OrderMatrix < OrderPdf
table.column(2 + idx).border_width = 2
end
- table.row_colors = ['dddddd', 'ffffff']
+ table.row_colors = %w[dddddd ffffff]
end
first_page = false
diff --git a/app/helpers/admin/configs_helper.rb b/app/helpers/admin/configs_helper.rb
index 0185a0df..3c1da9f0 100644
--- a/app/helpers/admin/configs_helper.rb
+++ b/app/helpers/admin/configs_helper.rb
@@ -28,7 +28,11 @@ module Admin::ConfigsHelper
options[:default] = options[:input_html].delete(:value)
return form.input key, options, &block
end
- block ||= proc { config_input_field form, key, options.merge(options[:input_html]) } if options[:as] == :select_recurring
+ if options[:as] == :select_recurring
+ block ||= proc {
+ config_input_field form, key, options.merge(options[:input_html])
+ }
+ end
form.input key, options, &block
end
@@ -57,11 +61,12 @@ module Admin::ConfigsHelper
unchecked_value = options.delete(:unchecked_value) || 'false'
options[:checked] = 'checked' if v = options.delete(:value) && v != 'false'
# different key for hidden field so that allow clocking on label focuses the control
- form.hidden_field(key, id: "#{key}_", value: unchecked_value, as: :hidden) + form.check_box(key, options, checked_value, false)
+ form.hidden_field(key, id: "#{key}_", value: unchecked_value,
+ as: :hidden) + form.check_box(key, options, checked_value, false)
elsif options[:as] == :select_recurring
options[:value] = FoodsoftDateUtil.rule_from(options[:value])
options[:rules] ||= []
- options[:rules].unshift options[:value] unless options[:value].blank?
+ options[:rules].unshift options[:value] if options[:value].present?
options[:rules].push [I18n.t('recurring_select.not_recurring'), '{}'] if options.delete(:allow_blank) # blank after current value
form.select_recurring key, options.delete(:rules).uniq, options
else
@@ -73,7 +78,7 @@ module Admin::ConfigsHelper
# @param form [ActionView::Helpers::FormBuilder] Form object.
# @param key [Symbol, String] Configuration key of a boolean (e.g. +use_messages+).
# @option options [String] :label Label to show
- def config_use_heading(form, key, options = {})
+ def config_use_heading(form, key, options = {}, &block)
head = content_tag :label do
lbl = options[:label] || config_input_label(form, key)
field = config_input_field(form, key, as: :boolean, boolean_style: :inline,
@@ -83,9 +88,7 @@ module Admin::ConfigsHelper
content_tag :span, (lbl + field).html_safe, config_input_tooltip_options(form, key, {})
end
end
- fields = content_tag(:fieldset, id: "#{key}-fields", class: "collapse#{' in' if @cfg[key]}") do
- yield
- end
+ fields = content_tag(:fieldset, id: "#{key}-fields", class: "collapse#{' in' if @cfg[key]}", &block)
head + fields
end
@@ -127,7 +130,7 @@ module Admin::ConfigsHelper
# tooltip with help info to the right
cfg_path = form.lookup_model_names[1..-1] + [key]
tooltip = I18n.t("config.hints.#{cfg_path.map(&:to_s).join('.')}", default: '')
- unless tooltip.blank?
+ if tooltip.present?
options[:data] ||= {}
options[:data][:toggle] ||= 'tooltip'
options[:data][:placement] ||= 'right'
diff --git a/app/helpers/admin/ordergroups_helper.rb b/app/helpers/admin/ordergroups_helper.rb
index e74fdde5..ecb4bd39 100644
--- a/app/helpers/admin/ordergroups_helper.rb
+++ b/app/helpers/admin/ordergroups_helper.rb
@@ -2,9 +2,7 @@ module Admin::OrdergroupsHelper
def ordergroup_members_title(ordergroup)
s = ''
s += ordergroup.users.map(&:name).join(', ') if ordergroup.users.any?
- if ordergroup.contact_person.present?
- s += "\n" + Ordergroup.human_attribute_name(:contact) + ": " + ordergroup.contact_person
- end
+ s += "\n" + Ordergroup.human_attribute_name(:contact) + ': ' + ordergroup.contact_person if ordergroup.contact_person.present?
s
end
end
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index de207901..8b8a5f95 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -4,7 +4,7 @@ module ApplicationHelper
include PathHelper
def format_time(time = Time.now)
- I18n.l(time, :format => "%d.%m.%Y %H:%M") unless time.nil?
+ I18n.l(time, format: :foodsoft_datetime) unless time.nil?
end
def format_date(time = Time.now)
@@ -16,7 +16,7 @@ module ApplicationHelper
end
def format_datetime_timespec(time, format)
- I18n.l(time, :format => format) unless (time.nil? || format.nil?)
+ I18n.l(time, format: format) unless time.nil? || format.nil?
end
def format_currency(amount)
@@ -26,28 +26,28 @@ module ApplicationHelper
# Splits an IBAN into groups of 4 digits displayed with margins in between
def format_iban(iban)
- iban && iban.scan(/..?.?.?/).map { |item| content_tag(:span, item, style: "margin-right: 0.5em;") }.join.html_safe
+ iban && iban.scan(/..?.?.?/).map { |item| content_tag(:span, item, style: 'margin-right: 0.5em;') }.join.html_safe
end
# Creates ajax-controlled-links for pagination
def pagination_links_remote(collection, options = {})
per_page = options[:per_page] || @per_page
params = options[:params] || {}
- params = params.merge({ :per_page => per_page })
- paginate collection, :params => params, :remote => true
+ params = params.merge({ per_page: per_page })
+ paginate collection, params: params, remote: true
end
# Link-collection for per_page-options when using the pagination-plugin
def items_per_page(options = {})
per_page_options = options[:per_page_options] || [20, 50, 100, 500]
current = options[:current] || @per_page
- params = params || {}
+ params ||= {}
links = per_page_options.map do |per_page|
- params.merge!({ :per_page => per_page })
+ params.merge!({ per_page: per_page })
link_class = 'btn'
link_class << ' disabled' if per_page == current
- link_to(per_page, params, :remote => true, class: link_class)
+ link_to(per_page, params, remote: true, class: link_class)
end
if options[:wrap] == false
@@ -63,21 +63,19 @@ module ApplicationHelper
# Hmtl options
remote = options[:remote].nil? ? true : options[:remote]
class_name = case params[:sort]
- when key then
+ when key
'sortup'
- when key + '_reverse' then
+ when key + '_reverse'
'sortdown'
- else
- nil
end
html_options = {
- :title => I18n.t('helpers.application.sort_by', text: text),
- :remote => remote,
- :class => class_name
+ title: I18n.t('helpers.application.sort_by', text: text),
+ remote: remote,
+ class: class_name
}
# Url options
- key += "_reverse" if params[:sort] == key
+ key += '_reverse' if params[:sort] == key
per_page = options[:per_page] || @per_page
url_options = params.merge(per_page: per_page, sort: key)
url_options.merge!({ page: params[:page] }) if params[:page]
@@ -95,14 +93,16 @@ module ApplicationHelper
# be overridden by the option 'desc'.
# Other options are passed through to I18n.
def heading_helper(model, attribute, options = {})
- i18nopts = { count: 2 }.merge(options.select { |a| !['short', 'desc'].include?(a) })
+ i18nopts = { count: 2 }.merge(options.select { |a| !%w[short desc].include?(a) })
s = model.human_attribute_name(attribute, i18nopts)
if options[:short]
desc = options[:desc]
- desc ||= model.human_attribute_name("#{attribute}_desc".to_sym, options.merge({ fallback: true, default: '', count: 2 }))
+ desc ||= model.human_attribute_name("#{attribute}_desc".to_sym,
+ options.merge({ fallback: true, default: '', count: 2 }))
desc.blank? && desc = s
- sshort = model.human_attribute_name("#{attribute}_short".to_sym, options.merge({ fallback: true, default: '', count: 2 }))
- s = raw "#{sshort}" unless sshort.blank?
+ sshort = model.human_attribute_name("#{attribute}_short".to_sym,
+ options.merge({ fallback: true, default: '', count: 2 }))
+ s = raw "#{sshort}" if sshort.present?
end
s
end
@@ -117,7 +117,7 @@ module ApplicationHelper
# Returns the weekday. 0 is sunday, 1 is monday and so on
def weekday(dayNumber)
weekdays = I18n.t('date.day_names')
- return weekdays[dayNumber]
+ weekdays[dayNumber]
end
# to set a title for both the h1-tag and the title in the header
@@ -136,13 +136,13 @@ module ApplicationHelper
def icon(name, options = {})
icons = {
- :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') }
+ 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]
- options.merge!({ :size => '16x16', :border => "0" })
+ options.merge!({ size: '16x16', border: '0' })
image_tag icons[name][:file], options
end
@@ -150,27 +150,29 @@ module ApplicationHelper
# Remote links with default 'loader'.gif during request
def remote_link_to(text, options = {})
remote_options = {
- :before => "Element.show('loader')",
- :success => "Element.hide('loader')",
- :method => :get
+ before: "Element.show('loader')",
+ success: "Element.hide('loader')",
+ method: :get
}
link_to(text, options[:url], remote_options.merge(options))
end
def format_roles(record, icon = false)
- roles = %w(suppliers article_meta orders pickups finance invoices admin)
+ roles = %w[suppliers article_meta orders pickups finance invoices admin]
roles.select! { |role| record.send "role_#{role}?" }
- names = Hash[roles.map { |r| [r, I18n.t("helpers.application.role_#{r}")] }]
+ names = roles.index_with { |r| I18n.t("helpers.application.role_#{r}") }
if icon
- roles.map { |r| image_tag("role-#{r}.png", size: '22x22', border: 0, alt: names[r], title: names[r]) }.join(' ').html_safe
+ roles.map do |r|
+ image_tag("role-#{r}.png", size: '22x22', border: 0, alt: names[r], title: names[r])
+ end.join(' ').html_safe
else
roles.map { |r| names[r] }.join(', ')
end
end
def link_to_gmaps(address)
- link_to h(address), "http://maps.google.com/?q=#{h(address)}", :title => I18n.t('helpers.application.show_google_maps'),
- :target => "_blank"
+ link_to h(address), "http://maps.google.com/?q=#{h(address)}", title: I18n.t('helpers.application.show_google_maps'),
+ target: '_blank', rel: 'noopener'
end
# Returns flash messages html.
@@ -186,8 +188,8 @@ module ApplicationHelper
type = :success if type == 'notice'
type = :error if type == 'alert'
text = content_tag(:div,
- content_tag(:button, I18n.t('ui.marks.close').html_safe, :class => "close", "data-dismiss" => "alert") +
- message, :class => "alert fade in alert-#{type}")
+ 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
flash_messages.join("\n").html_safe
@@ -195,17 +197,17 @@ module ApplicationHelper
# render base errors in a form after failed validation
# http://railsapps.github.io/twitter-bootstrap-rails.html
- def base_errors resource
+ def base_errors(resource)
return '' if resource.errors.empty? || resource.errors[:base].empty?
messages = resource.errors[:base].map { |msg| content_tag(:li, msg) }.join
- render :partial => 'shared/base_errors', :locals => { :error_messages => messages }
+ render partial: 'shared/base_errors', locals: { error_messages: messages }
end
# show a user, depending on settings
def show_user(user = @current_user, options = {})
if user.nil?
- "?"
+ '?'
elsif FoodsoftConfig[:use_nick]
if options[:full] && options[:markup]
raw "#{h user.nick} (#{h user.first_name} #{h user.last_name})"
@@ -216,7 +218,7 @@ module ApplicationHelper
user.nick.nil? ? I18n.t('helpers.application.nick_fallback') : user.nick
end
else
- "#{user.first_name} #{user.last_name}" + (options[:unique] ? " (\##{user.id})" : '')
+ "#{user.first_name} #{user.last_name}" + (options[:unique] ? " (##{user.id})" : '')
end
end
@@ -258,9 +260,9 @@ module ApplicationHelper
# @return [String] stylesheet tag for foodcoop CSS style (+custom_css+ foodcoop config)
# @see #foodcoop_css_path
- def foodcoop_css_tag(options = {})
- unless FoodsoftConfig[:custom_css].blank?
- stylesheet_link_tag foodcoop_css_path, media: 'all'
- end
+ def foodcoop_css_tag(_options = {})
+ return if FoodsoftConfig[:custom_css].blank?
+
+ stylesheet_link_tag foodcoop_css_path, media: 'all'
end
end
diff --git a/app/helpers/articles_helper.rb b/app/helpers/articles_helper.rb
index add1c6ba..ebad29a4 100644
--- a/app/helpers/articles_helper.rb
+++ b/app/helpers/articles_helper.rb
@@ -3,13 +3,13 @@ module ArticlesHelper
def highlight_new(unequal_attributes, attribute)
return unless unequal_attributes
- unequal_attributes.has_key?(attribute) ? "background-color: yellow" : ""
+ unequal_attributes.has_key?(attribute) ? 'background-color: yellow' : ''
end
def row_classes(article)
classes = []
- classes << "unavailable" if !article.availability
- classes << "just-updated" if article.recently_updated && article.availability
- classes.join(" ")
+ classes << 'unavailable' unless article.availability
+ classes << 'just-updated' if article.recently_updated && article.availability
+ classes.join(' ')
end
end
diff --git a/app/helpers/deliveries_helper.rb b/app/helpers/deliveries_helper.rb
index a97a7df7..ac6e4b35 100644
--- a/app/helpers/deliveries_helper.rb
+++ b/app/helpers/deliveries_helper.rb
@@ -11,11 +11,11 @@ module DeliveriesHelper
def articles_for_select2(articles, except = [], &block)
articles = articles.reorder('articles.name ASC')
- articles = articles.reject { |a| not except.index(a.id).nil? } if except
- block_given? or block = Proc.new { |a| "#{a.name} (#{number_to_currency a.price}/#{a.unit})" }
+ articles = articles.reject { |a| !except.index(a.id).nil? } if except
+ block_given? or block = proc { |a| "#{a.name} (#{number_to_currency a.price}/#{a.unit})" }
articles.map do |a|
- { :id => a.id, :text => block.call(a) }
- end.unshift({ :id => '', :text => '' })
+ { id: a.id, text: block.call(a) }
+ end.unshift({ id: '', text: '' })
end
def articles_for_table(articles)
@@ -23,10 +23,14 @@ module DeliveriesHelper
end
def stock_change_remove_link(stock_change_form)
- return link_to t('deliveries.stock_change_fields.remove_article'), "#", :class => 'remove_new_stock_change btn btn-small' if stock_change_form.object.new_record?
+ if stock_change_form.object.new_record?
+ return link_to t('deliveries.stock_change_fields.remove_article'), '#',
+ class: 'remove_new_stock_change btn btn-small'
+ end
output = stock_change_form.hidden_field :_destroy
- output += link_to t('deliveries.stock_change_fields.remove_article'), "#", :class => 'destroy_stock_change btn btn-small'
- return output.html_safe
+ output += link_to t('deliveries.stock_change_fields.remove_article'), '#',
+ class: 'destroy_stock_change btn btn-small'
+ output.html_safe
end
end
diff --git a/app/helpers/finance/balancing_helper.rb b/app/helpers/finance/balancing_helper.rb
index bc528f04..a123b161 100644
--- a/app/helpers/finance/balancing_helper.rb
+++ b/app/helpers/finance/balancing_helper.rb
@@ -2,11 +2,11 @@ module Finance::BalancingHelper
def balancing_view_partial
view = params[:view] || 'edit_results'
case view
- when 'edit_results' then
+ when 'edit_results'
'edit_results_by_articles'
- when 'groups_overview' then
+ when 'groups_overview'
'shared/articles_by/groups'
- when 'articles_overview' then
+ when 'articles_overview'
'shared/articles_by/articles'
end
end
diff --git a/app/helpers/finance/invoices_helper.rb b/app/helpers/finance/invoices_helper.rb
index ef01a275..0644b501 100644
--- a/app/helpers/finance/invoices_helper.rb
+++ b/app/helpers/finance/invoices_helper.rb
@@ -1,9 +1,9 @@
module Finance::InvoicesHelper
- def format_delivery_item delivery
+ def format_delivery_item(delivery)
format_date(delivery.date)
end
- def format_order_item order
+ def format_order_item(order)
"#{format_date(order.ends)} (#{number_to_currency(order.sum)})"
end
end
diff --git a/app/helpers/group_order_articles_helper.rb b/app/helpers/group_order_articles_helper.rb
index ff003731..3a7efc33 100644
--- a/app/helpers/group_order_articles_helper.rb
+++ b/app/helpers/group_order_articles_helper.rb
@@ -2,12 +2,12 @@ module GroupOrderArticlesHelper
# return an edit field for a GroupOrderArticle result
def group_order_article_edit_result(goa)
result = number_with_precision goa.result, strip_insignificant_zeros: true
- unless goa.group_order.order.finished? && current_user.role_finance?
- result
- else
+ if goa.group_order.order.finished? && current_user.role_finance?
simple_form_for goa, remote: true, html: { 'data-submit-onchange' => 'changed', class: 'delta-input' } do |f|
f.input_field :result, as: :delta, class: 'input-nano', data: { min: 0 }, id: "r_#{goa.id}", value: result
end
+ else
+ result
end
end
end
diff --git a/app/helpers/group_orders_helper.rb b/app/helpers/group_orders_helper.rb
index 4f1d352f..a09a066c 100644
--- a/app/helpers/group_orders_helper.rb
+++ b/app/helpers/group_orders_helper.rb
@@ -1,10 +1,11 @@
module GroupOrdersHelper
def data_to_js(ordering_data)
- ordering_data[:order_articles].map { |id, data|
- [id, data[:price], data[:unit], data[:total_price], data[:others_quantity], data[:others_tolerance], data[:used_quantity], data[:quantity_available]]
- }.map { |row|
+ ordering_data[:order_articles].map do |id, data|
+ [id, data[:price], data[:unit], data[:total_price], data[:others_quantity], data[:others_tolerance],
+ data[:used_quantity], data[:quantity_available]]
+ end.map do |row|
"addData(#{row.join(', ')});"
- }.join("\n")
+ end.join("\n")
end
# Returns a link to the page where a group_order can be edited.
@@ -14,9 +15,9 @@ module GroupOrdersHelper
path = if options[:show] && group_order
group_order_path(group_order)
elsif group_order
- edit_group_order_path(group_order, :order_id => order.id)
+ edit_group_order_path(group_order, order_id: order.id)
else
- new_group_order_path(:order_id => order.id)
+ new_group_order_path(order_id: order.id)
end
options.delete(:show)
name = block_given? ? capture(&block) : order.name
@@ -26,7 +27,7 @@ module GroupOrdersHelper
# Return css class names for order result table
def order_article_class_name(quantity, tolerance, result)
- if (quantity + tolerance > 0)
+ if quantity + tolerance > 0
result > 0 ? 'success' : 'failed'
else
'ignored'
@@ -45,20 +46,12 @@ module GroupOrdersHelper
end
def get_missing_units_css_class(quantity_missing)
- if (quantity_missing == 1)
- return 'missing-few';
- elsif (quantity_missing == 0)
- return ''
+ if quantity_missing == 1
+ 'missing-few'
+ elsif quantity_missing == 0
+ ''
else
- return 'missing-many'
+ 'missing-many'
end
end
-
- def price_per_base_unit(article:, price:)
- quantity_unit = QuantityUnit.parse(article.unit)
- return nil unless quantity_unit.present?
-
- scaled_price, base_unit = quantity_unit.scale_price_to_base_unit(price)
- "#{number_to_currency(scaled_price)}/#{base_unit}"
- end
end
diff --git a/app/helpers/order_articles_helper.rb b/app/helpers/order_articles_helper.rb
index b4290e84..7af4b409 100644
--- a/app/helpers/order_articles_helper.rb
+++ b/app/helpers/order_articles_helper.rb
@@ -1,6 +1,6 @@
module OrderArticlesHelper
def article_label_with_unit(article)
pkg_info = pkg_helper(article, plain: true)
- "#{article.name} (#{[article.unit, pkg_info].reject(&:blank?).join(' ')})"
+ "#{article.name} (#{[article.unit, pkg_info].compact_blank.join(' ')})"
end
end
diff --git a/app/helpers/orders_helper.rb b/app/helpers/orders_helper.rb
index 5f7fb904..d629ccb1 100644
--- a/app/helpers/orders_helper.rb
+++ b/app/helpers/orders_helper.rb
@@ -18,7 +18,7 @@ module OrdersHelper
def options_for_suppliers_to_select
options = [[I18n.t('helpers.orders.option_choose')]]
- options += Supplier.map { |s| [s.name, url_for(action: "new", supplier_id: s.id)] }
+ options += Supplier.map { |s| [s.name, url_for(action: 'new', supplier_id: s.id)] }
options += [[I18n.t('helpers.orders.option_stock'), url_for(action: 'new', supplier_id: nil)]]
options_for_select(options)
end
@@ -29,13 +29,13 @@ module OrdersHelper
nil
else
units_info = []
- [:units_to_order, :units_billed, :units_received].map do |unit|
- if n = order_article.send(unit)
- line = n.to_s + ' '
- line += pkg_helper(order_article.price, options) + ' ' unless n == 0
- line += OrderArticle.human_attribute_name("#{unit}_short", count: n)
- units_info << line
- end
+ %i[units_to_order units_billed units_received].map do |unit|
+ next unless n = order_article.send(unit)
+
+ line = n.to_s + ' '
+ line += pkg_helper(order_article.price, options) + ' ' unless n == 0
+ line += OrderArticle.human_attribute_name("#{unit}_short", count: n)
+ units_info << line
end
units_info.join(', ').html_safe
end
@@ -67,8 +67,8 @@ module OrdersHelper
def pkg_helper_icon(c = nil, options = {})
options = { tag: 'i', class: '' }.merge(options)
if c.nil?
- c = " ".html_safe
- options[:class] += " icon-only"
+ c = ' '.html_safe
+ options[:class] += ' icon-only'
end
content_tag(options[:tag], c, class: "package #{options[:class]}").html_safe
end
@@ -94,11 +94,12 @@ module OrdersHelper
autocomplete: 'off'
if order_article.result_manually_changed?
- input_html = content_tag(:span, class: 'input-prepend intable', title: t('orders.edit_amount.field_locked_title', default: '')) {
+ input_html = content_tag(:span, class: 'input-prepend intable',
+ title: t('orders.edit_amount.field_locked_title', default: '')) do
button_tag(nil, type: :button, class: 'btn unlocker') {
content_tag(:i, nil, class: 'icon icon-unlock')
} + input_html
- }
+ end
end
input_html.html_safe
@@ -109,18 +110,16 @@ module OrdersHelper
def ordergroup_count(order)
group_orders = order.group_orders.includes(:ordergroup)
txt = "#{group_orders.count} #{Ordergroup.model_name.human count: group_orders.count}"
- if group_orders.count == 0
- return txt
- else
- desc = group_orders.includes(:ordergroup).map { |g| g.ordergroup_name }.join(', ')
- content_tag(:abbr, txt, title: desc).html_safe
- end
+ return txt if group_orders.count == 0
+
+ desc = group_orders.includes(:ordergroup).map { |g| g.ordergroup_name }.join(', ')
+ content_tag(:abbr, txt, title: desc).html_safe
end
# @param order_or_supplier [Order, Supplier] Order or supplier to link to
# @return [String] Link to order or supplier, showing its name.
def supplier_link(order_or_supplier)
- if order_or_supplier.kind_of?(Order) && order_or_supplier.stockit?
+ if order_or_supplier.is_a?(Order) && order_or_supplier.stockit?
link_to(order_or_supplier.name, stock_articles_path).html_safe
else
link_to(@order.supplier.name, supplier_path(@order.supplier)).html_safe
@@ -152,19 +151,8 @@ module OrdersHelper
if order.stockit?
content_tag :div, t('orders.index.action_receive'), class: "btn disabled #{options[:class]}"
else
- link_to t('orders.index.action_receive'), receive_order_path(order), class: "btn#{' btn-success' unless order.received?} #{options[:class]}"
+ link_to t('orders.index.action_receive'), receive_order_path(order),
+ class: "btn#{' btn-success' unless order.received?} #{options[:class]}"
end
end
-
- def custom_csv_collection
- [
- OrderArticle.human_attribute_name(:units_to_order),
- Article.human_attribute_name(:order_number),
- Article.human_attribute_name(:name),
- Article.human_attribute_name(:unit),
- Article.human_attribute_name(:unit_quantity_short),
- ArticlePrice.human_attribute_name(:price),
- OrderArticle.human_attribute_name(:total_price)
- ]
- end
end
diff --git a/app/helpers/stockit_helper.rb b/app/helpers/stockit_helper.rb
index a08e8335..9848198d 100644
--- a/app/helpers/stockit_helper.rb
+++ b/app/helpers/stockit_helper.rb
@@ -1,8 +1,8 @@
module StockitHelper
def stock_article_classes(article)
class_names = []
- class_names << "unavailable" if article.quantity_available <= 0
- class_names.join(" ")
+ class_names << 'unavailable' if article.quantity_available <= 0
+ class_names.join(' ')
end
def link_to_stock_change_reason(stock_change)
@@ -17,8 +17,8 @@ module StockitHelper
def stock_article_price_hint(stock_article)
t('simple_form.hints.stock_article.edit_stock_article.price',
- :stock_article_copy_link => link_to(t('stockit.form.copy_stock_article'),
- stock_article_copy_path(stock_article),
- :remote => true))
+ stock_article_copy_link: link_to(t('stockit.form.copy_stock_article'),
+ stock_article_copy_path(stock_article),
+ remote: true))
end
end
diff --git a/app/helpers/tasks_helper.rb b/app/helpers/tasks_helper.rb
index f6f1fa14..4b12f7a8 100644
--- a/app/helpers/tasks_helper.rb
+++ b/app/helpers/tasks_helper.rb
@@ -1,16 +1,16 @@
module TasksHelper
def task_assignments(task)
task.assignments.map do |ass|
- content_tag :span, show_user(ass.user), :class => (ass.accepted? ? 'accepted' : 'unaccepted')
- end.join(", ").html_safe
+ content_tag :span, show_user(ass.user), class: (ass.accepted? ? 'accepted' : 'unaccepted')
+ end.join(', ').html_safe
end
# generate colored number of still required users
def highlighted_required_users(task)
- unless task.enough_users_assigned?
- content_tag :span, task.still_required_users, class: 'badge badge-important',
- title: I18n.t('helpers.tasks.required_users', :count => task.still_required_users)
- end
+ return if task.enough_users_assigned?
+
+ content_tag :span, task.still_required_users, class: 'badge badge-important',
+ title: I18n.t('helpers.tasks.required_users', count: task.still_required_users)
end
def task_title(task)
diff --git a/app/inputs/delta_input.rb b/app/inputs/delta_input.rb
index adc08960..f4ce1a2b 100644
--- a/app/inputs/delta_input.rb
+++ b/app/inputs/delta_input.rb
@@ -6,7 +6,7 @@ class DeltaInput < SimpleForm::Inputs::StringInput
options[:data] ||= {}
options[:data][:delta] ||= 1
options[:autocomplete] ||= 'off'
- # TODO get generated id, don't know how yet - `add_default_name_and_id_for_value` might be an option
+ # TODO: get generated id, don't know how yet - `add_default_name_and_id_for_value` might be an option
template.content_tag :div, class: 'delta-input input-prepend input-append' do
delta_button(content_tag(:i, nil, class: 'icon icon-minus'), -1, options) +
diff --git a/app/javascript/application.js b/app/javascript/application.js
index ed5cae66..141d3cae 100644
--- a/app/javascript/application.js
+++ b/app/javascript/application.js
@@ -1,3 +1,4 @@
// Configure your import map in config/importmap.rb. Read more: https://github.com/rails/importmap-rails
import "trix"
import "@rails/actiontext"
+import "trix-editor-overrides"
diff --git a/app/javascript/trix-editor-overrides.js b/app/javascript/trix-editor-overrides.js
new file mode 100644
index 00000000..64cecbef
--- /dev/null
+++ b/app/javascript/trix-editor-overrides.js
@@ -0,0 +1,7 @@
+// app/javascript/trix-editor-overrides.js
+window.addEventListener("trix-file-accept", function(event) {
+ if (event.file.size > 1024 * 1024 * 512) {
+ event.preventDefault()
+ alert(I18n.t('js.trix_editor.file_size_alert'))
+ }
+})
\ No newline at end of file
diff --git a/app/lib/apple_bar.rb b/app/lib/apple_bar.rb
index 236417c6..fb6fcef7 100644
--- a/app/lib/apple_bar.rb
+++ b/app/lib/apple_bar.rb
@@ -29,7 +29,7 @@ class AppleBar
def mean_order_amount_per_job
(1 / @global_avg).round
- rescue
+ rescue StandardError
0
end
diff --git a/app/lib/articles_csv.rb b/app/lib/articles_csv.rb
index 55bc7fc5..61f5743f 100644
--- a/app/lib/articles_csv.rb
+++ b/app/lib/articles_csv.rb
@@ -23,7 +23,7 @@ class ArticlesCsv < RenderCsv
def data
@object.each do |o|
yield [
- '',
+ o.availability ? I18n.t('simple_form.yes') : I18n.t('simple_form.no'),
o.order_number,
o.name,
o.note,
diff --git a/app/lib/bank_account_connector.rb b/app/lib/bank_account_connector.rb
index b728ebb9..5e18a816 100644
--- a/app/lib/bank_account_connector.rb
+++ b/app/lib/bank_account_connector.rb
@@ -41,14 +41,14 @@ class BankAccountConnector
end
end
- @@registered_classes = Set.new
+ @registered_classes = Set.new
def self.register(klass)
- @@registered_classes.add klass
+ @registered_classes.add klass
end
def self.find(iban)
- @@registered_classes.each do |klass|
+ @registered_classes.each do |klass|
return klass if klass.handles(iban)
end
nil
diff --git a/app/lib/bank_account_information_importer.rb b/app/lib/bank_account_information_importer.rb
index bebc1ff4..a83c53f7 100644
--- a/app/lib/bank_account_information_importer.rb
+++ b/app/lib/bank_account_information_importer.rb
@@ -17,16 +17,16 @@ class BankAccountInformationImporter
ret = 0
booked.each do |t|
amount = parse_account_information_amount t[:transactionAmount]
- entityName = amount < 0 ? t[:creditorName] : t[:debtorName]
- entityAccount = amount < 0 ? t[:creditorAccount] : t[:debtorAccount]
+ entity_name = amount < 0 ? t[:creditorName] : t[:debtorName]
+ entity_account = amount < 0 ? t[:creditorAccount] : t[:debtorAccount]
reference = [t[:endToEndId], t[:remittanceInformationUnstructured]].join("\n").strip
@bank_account.bank_transactions.where(external_id: t[:transactionId]).first_or_create.update({
date: t[:bookingDate],
amount: amount,
- iban: entityAccount && entityAccount[:iban],
+ iban: entity_account && entity_account[:iban],
reference: reference,
- text: entityName,
+ text: entity_name,
receipt: t[:additionalInformation]
})
ret += 1
@@ -34,7 +34,7 @@ class BankAccountInformationImporter
balances = (data[:balances] ? data[:balances].map { |b| [b[:balanceType], b[:balanceAmount]] } : []).to_h
balance = balances.values.first
- %w(closingBooked expected authorised openingBooked interimAvailable forwardAvailable nonInvoiced).each do |type|
+ %w[closingBooked expected authorised openingBooked interimAvailable forwardAvailable nonInvoiced].each do |type|
value = balances[type]
if value
balance = value
diff --git a/app/lib/date_time_attribute_validate.rb b/app/lib/date_time_attribute_validate.rb
index 23127898..fa53c361 100644
--- a/app/lib/date_time_attribute_validate.rb
+++ b/app/lib/date_time_attribute_validate.rb
@@ -10,66 +10,68 @@ module DateTimeAttributeValidate
super
attributes.each do |attribute|
- validate -> { self.send("#{attribute}_datetime_value_valid") }
+ validate -> { send("#{attribute}_datetime_value_valid") }
# allow resetting the field to nil
before_validation do
- if self.instance_variable_get("@#{attribute}_is_set")
- date = self.instance_variable_get("@#{attribute}_date_value")
- time = self.instance_variable_get("@#{attribute}_time_value")
- if date.blank? && time.blank?
- self.send("#{attribute}=", nil)
- end
+ if instance_variable_get("@#{attribute}_is_set")
+ date = instance_variable_get("@#{attribute}_date_value")
+ time = instance_variable_get("@#{attribute}_time_value")
+ send("#{attribute}=", nil) if date.blank? && time.blank?
end
end
# remember old date and time values
define_method("#{attribute}_date_value=") do |val|
- self.instance_variable_set("@#{attribute}_is_set", true)
- self.instance_variable_set("@#{attribute}_date_value", val)
+ instance_variable_set("@#{attribute}_is_set", true)
+ instance_variable_set("@#{attribute}_date_value", val)
begin
- self.send("#{attribute}_date=", val)
- rescue
+ send("#{attribute}_date=", val)
+ rescue StandardError
nil
end
end
define_method("#{attribute}_time_value=") do |val|
- self.instance_variable_set("@#{attribute}_is_set", true)
- self.instance_variable_set("@#{attribute}_time_value", val)
+ instance_variable_set("@#{attribute}_is_set", true)
+ instance_variable_set("@#{attribute}_time_value", val)
begin
- self.send("#{attribute}_time=", val)
- rescue
+ send("#{attribute}_time=", val)
+ rescue StandardError
nil
end
end
# fallback to field when values are not set
define_method("#{attribute}_date_value") do
- self.instance_variable_get("@#{attribute}_date_value") || self.send("#{attribute}_date").try { |e| e.strftime('%Y-%m-%d') }
+ instance_variable_get("@#{attribute}_date_value") || send("#{attribute}_date").try do |e|
+ e.strftime('%Y-%m-%d')
+ end
end
define_method("#{attribute}_time_value") do
- self.instance_variable_get("@#{attribute}_time_value") || self.send("#{attribute}_time").try { |e| e.strftime('%H:%M') }
+ instance_variable_get("@#{attribute}_time_value") || send("#{attribute}_time").try do |e|
+ e.strftime('%H:%M')
+ end
end
private
# validate date and time
define_method("#{attribute}_datetime_value_valid") do
- date = self.instance_variable_get("@#{attribute}_date_value")
+ date = instance_variable_get("@#{attribute}_date_value")
unless date.blank? || begin
Date.parse(date)
- rescue
+ rescue StandardError
nil
end
- errors.add(attribute, "is not a valid date") # @todo I18n
+ errors.add(attribute, 'is not a valid date') # @todo I18n
end
- time = self.instance_variable_get("@#{attribute}_time_value")
+ time = instance_variable_get("@#{attribute}_time_value")
unless time.blank? || begin
Time.parse(time)
- rescue
+ rescue StandardError
nil
end
- errors.add(attribute, "is not a valid time") # @todo I18n
+ errors.add(attribute, 'is not a valid time') # @todo I18n
end
end
end
diff --git a/app/lib/foodsoft/expansion_variables.rb b/app/lib/foodsoft/expansion_variables.rb
index 97f7b6bb..a4a8153e 100644
--- a/app/lib/foodsoft/expansion_variables.rb
+++ b/app/lib/foodsoft/expansion_variables.rb
@@ -14,7 +14,7 @@ module Foodsoft
cattr_accessor :variables
# Hash of variables. Note that keys are Strings.
- @@variables = {
+ @variables = {
'scope' => -> { FoodsoftConfig.scope },
'name' => -> { FoodsoftConfig[:name] },
'contact.street' => -> { FoodsoftConfig[:contact][:street] },
@@ -39,13 +39,13 @@ module Foodsoft
'supplier_count' => -> { Supplier.undeleted.count },
'active_supplier_count' => -> { active_supplier_count },
'active_suppliers' => -> { active_suppliers },
- 'first_order_date' => -> { I18n.l Order.first.try { |o| o.starts.to_date } }
+ 'first_order_date' => -> { I18n.l(Order.first.try { |o| o.starts.to_date }) }
}
# Return expanded variable
# @return [String] Expanded variable
def self.get(var)
- s = @@variables[var.to_s]
+ s = @variables[var.to_s]
s.respond_to?(:call) ? s.call : s.to_s
end
@@ -55,7 +55,7 @@ module Foodsoft
# @return [String] Expanded string
def self.expand(str, options = {})
str.gsub(/{{([._a-zA-Z0-9]+)}}/) do
- options[::Regexp.last_match(1)] || self.get(::Regexp.last_match(1))
+ options[::Regexp.last_match(1)] || get(::Regexp.last_match(1))
end
end
diff --git a/app/lib/foodsoft_config.rb b/app/lib/foodsoft_config.rb
index 6ea166d3..c7dda590 100644
--- a/app/lib/foodsoft_config.rb
+++ b/app/lib/foodsoft_config.rb
@@ -70,7 +70,7 @@ class FoodsoftConfig
# Load initial config from development or production
set_config Rails.env
# Overwrite scope to have a better namescope than 'production'
- self.scope = config[:default_scope] or raise "No default_scope is set"
+ self.scope = config[:default_scope] or raise 'No default_scope is set'
# Set defaults for backward-compatibility
set_missing
# Make sure relevant configuration is applied, also in single coops mode,
@@ -79,7 +79,7 @@ class FoodsoftConfig
end
def init_mailing
- [:protocol, :host, :port, :script_name].each do |k|
+ %i[protocol host port script_name].each do |k|
ActionMailer::Base.default_url_options[k] = self[k] if self[k]
end
end
@@ -117,7 +117,7 @@ class FoodsoftConfig
# @return [Object] Value of the key.
def [](key)
if RailsSettings::CachedSettings.table_exists? && allowed_key?(key)
- value = RailsSettings::CachedSettings["foodcoop.#{self.scope}.#{key}"]
+ value = RailsSettings::CachedSettings["foodcoop.#{scope}.#{key}"]
value = config[key] if value.nil?
value
else
@@ -139,20 +139,20 @@ class FoodsoftConfig
if config[key] == value || (config[key].nil? && value == false)
# delete (ok if it was already deleted)
begin
- RailsSettings::CachedSettings.destroy "foodcoop.#{self.scope}.#{key}"
+ RailsSettings::CachedSettings.destroy "foodcoop.#{scope}.#{key}"
rescue RailsSettings::Settings::SettingNotFound
end
else
# or store
- RailsSettings::CachedSettings["foodcoop.#{self.scope}.#{key}"] = value
+ RailsSettings::CachedSettings["foodcoop.#{scope}.#{key}"] = value
end
true
end
# @return [Array] Configuration keys that are set (either in +app_config.yml+ or database).
def keys
- keys = RailsSettings::CachedSettings.get_all("foodcoop.#{self.scope}.").try(:keys) || []
- keys.map! { |k| k.gsub(/^foodcoop\.#{self.scope}\./, '') }
+ keys = RailsSettings::CachedSettings.get_all("foodcoop.#{scope}.").try(:keys) || []
+ keys.map! { |k| k.gsub(/^foodcoop\.#{scope}\./, '') }
keys += config.keys
keys.map(&:to_s).uniq
end
@@ -181,10 +181,10 @@ class FoodsoftConfig
# @return [Boolean] Whether this key may be set in the database
def allowed_key?(key)
# fast check for keys without nesting
- if self.config[:protected].include? key
- !self.config[:protected][key]
+ if config[:protected].include? key
+ !config[:protected][key]
else
- !self.config[:protected][:all]
+ !config[:protected][:all]
end
# @todo allow to check nested keys as well
end
@@ -287,7 +287,9 @@ class FoodsoftConfig
def normalize_value(value)
value = value.map { |v| normalize_value(v) } if value.is_a? Array
if value.is_a? Hash
- value = ActiveSupport::HashWithIndifferentAccess[value.to_a.map { |a| [a[0], normalize_value(a[1])] }]
+ value = ActiveSupport::HashWithIndifferentAccess[value.to_a.map do |a|
+ [a[0], normalize_value(a[1])]
+ end]
end
case value
when 'true' then true
diff --git a/app/lib/foodsoft_date_util.rb b/app/lib/foodsoft_date_util.rb
index a14ad453..38dbc6be 100644
--- a/app/lib/foodsoft_date_util.rb
+++ b/app/lib/foodsoft_date_util.rb
@@ -8,26 +8,24 @@ module FoodsoftDateUtil
# @todo handle ical parse errors
occ = begin
schedule.next_occurrence(from).to_time
- rescue
+ rescue StandardError
nil
end
end
- if options && options[:time] && occ
- occ = occ.beginning_of_day.advance(seconds: Time.parse(options[:time]).seconds_since_midnight)
- end
+ occ = occ.beginning_of_day.advance(seconds: Time.parse(options[:time]).seconds_since_midnight) if options && options[:time] && occ
occ
end
- # @param p [String, Symbol, Hash, IceCube::Rule] What to return a rule from.
+ # @param rule [String, Symbol, Hash, IceCube::Rule] What to return a rule from.
# @return [IceCube::Rule] Recurring rule
- def self.rule_from(p)
- case p
+ def self.rule_from(rule)
+ case rule
when String
- IceCube::Rule.from_ical(p)
+ IceCube::Rule.from_ical(rule)
when Hash
- IceCube::Rule.from_hash(p)
+ IceCube::Rule.from_hash(rule)
else
- p
+ rule
end
end
end
diff --git a/app/lib/foodsoft_file.rb b/app/lib/foodsoft_file.rb
new file mode 100644
index 00000000..0a7128ed
--- /dev/null
+++ b/app/lib/foodsoft_file.rb
@@ -0,0 +1,25 @@
+# Foodsoft-file import
+class FoodsoftFile
+ # parses a string from a foodsoft-file
+ # returns two arrays with articles and outlisted_articles
+ # the parsed article is a simple hash
+ def self.parse(file, options = {})
+ SpreadsheetFile.parse file, options do |row, row_index|
+ next if row[2].blank?
+
+ article = { order_number: row[1],
+ name: row[2],
+ note: row[3],
+ manufacturer: row[4],
+ origin: row[5],
+ unit: row[6],
+ price: row[7],
+ tax: row[8],
+ deposit: (row[9].nil? ? '0' : row[9]),
+ unit_quantity: row[10],
+ article_category: row[13] }
+ status = row[0] && row[0].strip.downcase == 'x' ? :outlisted : nil
+ yield status, article, row_index
+ end
+ end
+end
diff --git a/app/lib/foodsoft_mail_receiver.rb b/app/lib/foodsoft_mail_receiver.rb
index 18e93be3..c5ec2edb 100644
--- a/app/lib/foodsoft_mail_receiver.rb
+++ b/app/lib/foodsoft_mail_receiver.rb
@@ -23,8 +23,8 @@ class FoodsoftMailReceiver < MidiSmtpServer::Smtpd
recipient = rcpt_to.gsub(/^\s*<\s*(.*)\s*>\s*$/, '\1')
@handlers << self.class.find_handler(recipient)
rcpt_to
- rescue => error
- logger.info("Can not accept mail for '#{rcpt_to}': #{error}")
+ rescue StandardError => e
+ logger.info("Can not accept mail for '#{rcpt_to}': #{e}")
raise MidiSmtpServer::Smtpd550Exception
end
@@ -32,16 +32,16 @@ class FoodsoftMailReceiver < MidiSmtpServer::Smtpd
@handlers.each do |handler|
handler.call(ctx[:message][:data])
end
- rescue => error
- ExceptionNotifier.notify_exception(error, data: ctx)
- raise error
+ rescue StandardError => e
+ ExceptionNotifier.notify_exception(e, data: ctx)
+ raise e
ensure
@handlers.clear
end
def self.find_handler(recipient)
m = /(?[^@.]+)\.(?[^@]+)(@(?[^@]+))?/.match recipient
- raise "recipient is missing or has an invalid format" if m.nil?
+ raise 'recipient is missing or has an invalid format' if m.nil?
raise "Foodcoop '#{m[:foodcoop]}' could not be found" unless FoodsoftConfig.allowed_foodcoop? m[:foodcoop]
FoodsoftConfig.select_multifoodcoop m[:foodcoop]
@@ -53,6 +53,6 @@ class FoodsoftMailReceiver < MidiSmtpServer::Smtpd
end
end
- raise "invalid format for recipient"
+ raise 'invalid format for recipient'
end
end
diff --git a/app/lib/order_csv.rb b/app/lib/order_csv.rb
index 653edf90..e2449596 100644
--- a/app/lib/order_csv.rb
+++ b/app/lib/order_csv.rb
@@ -2,60 +2,28 @@ require 'csv'
class OrderCsv < RenderCsv
def header
- params = @options[:custom_csv]
- arr = if params.nil?
- [
- OrderArticle.human_attribute_name(:units_to_order),
- Article.human_attribute_name(:order_number),
- Article.human_attribute_name(:name),
- Article.human_attribute_name(:unit),
- Article.human_attribute_name(:unit_quantity_short),
- ArticlePrice.human_attribute_name(:price),
- OrderArticle.human_attribute_name(:total_price)
- ]
- else
- [
- params[:first],
- params[:second],
- params[:third],
- params[:fourth],
- params[:fifth],
- params[:sixth],
- params[:seventh]
- ]
- end
+ [
+ OrderArticle.human_attribute_name(:units_to_order),
+ Article.human_attribute_name(:order_number),
+ Article.human_attribute_name(:name),
+ Article.human_attribute_name(:unit),
+ Article.human_attribute_name(:unit_quantity_short),
+ ArticlePrice.human_attribute_name(:price),
+ OrderArticle.human_attribute_name(:total_price)
+ ]
end
def data
- @object.order_articles.ordered.includes([:article, :article_price]).all.map do |oa|
+ @object.order_articles.ordered.includes(%i[article article_price]).all.map do |oa|
yield [
- match_params(oa, header[0]),
- match_params(oa, header[1]),
- match_params(oa, header[2]),
- match_params(oa, header[3]),
- match_params(oa, header[4]),
- match_params(oa, header[5]),
- match_params(oa, header[6])
+ oa.units_to_order,
+ oa.article.order_number,
+ oa.article.name,
+ oa.article.unit,
+ oa.price.unit_quantity > 1 ? oa.price.unit_quantity : nil,
+ number_to_currency(oa.price.price * oa.price.unit_quantity),
+ number_to_currency(oa.total_price)
]
end
end
-
- def match_params(object, attribute)
- case attribute
- when OrderArticle.human_attribute_name(:units_to_order)
- object.units_to_order
- when Article.human_attribute_name(:order_number)
- object.article.order_number
- when Article.human_attribute_name(:name)
- object.article.name
- when Article.human_attribute_name(:unit)
- object.article.unit
- when Article.human_attribute_name(:unit_quantity_short)
- object.price.unit_quantity > 1 ? object.price.unit_quantity : nil
- when ArticlePrice.human_attribute_name(:price)
- number_to_currency(object.price.price * object.price.unit_quantity)
- when OrderArticle.human_attribute_name(:total_price)
- number_to_currency(object.total_price)
- end
- end
end
diff --git a/app/lib/order_pdf.rb b/app/lib/order_pdf.rb
index 164be66b..869cb0e8 100644
--- a/app/lib/order_pdf.rb
+++ b/app/lib/order_pdf.rb
@@ -55,7 +55,7 @@ class OrderPdf < RenderPdf
end
def group_order_article_quantity_with_tolerance(goa)
- goa.tolerance > 0 ? "#{goa.quantity} + #{goa.tolerance}" : "#{goa.quantity}"
+ goa.tolerance > 0 ? "#{goa.quantity} + #{goa.tolerance}" : goa.quantity.to_s
end
def group_order_article_result(goa)
@@ -88,7 +88,7 @@ class OrderPdf < RenderPdf
.pluck('groups.name', 'SUM(group_orders.price)', 'ordergroup_id', 'SUM(group_orders.transport)')
result.map do |item|
- [item.first || stock_ordergroup_name] + item[1..-1]
+ [item.first || stock_ordergroup_name] + item[1..]
end
end
@@ -103,7 +103,7 @@ class OrderPdf < RenderPdf
def each_ordergroup_batch(batch_size)
offset = 0
- while true
+ loop do
go_records = ordergroups(offset, batch_size)
break unless go_records.any?
@@ -113,7 +113,7 @@ class OrderPdf < RenderPdf
# get quantity for each article and ordergroup
goa_records = group_order_articles(group_ids)
.group('group_order_articles.order_article_id, group_orders.ordergroup_id')
- .pluck('group_order_articles.order_article_id', 'group_orders.ordergroup_id', 'SUM(COALESCE(group_order_articles.result, group_order_articles.quantity))')
+ .pluck('group_order_articles.order_article_id', 'group_orders.ordergroup_id', Arel.sql('SUM(COALESCE(group_order_articles.result, group_order_articles.quantity))'))
# transform the flat list of results in a hash (with the article as key), which contains an array for all ordergroups
results = goa_records.group_by(&:first).transform_values do |value|
@@ -136,7 +136,7 @@ class OrderPdf < RenderPdf
group_order_articles(ordergroup)
.includes(order_article: { article: [:supplier] })
.order('suppliers.name, articles.name')
- .preload(order_article: [:article_price, :order])
+ .preload(order_article: %i[article_price order])
.each(&block)
end
diff --git a/app/lib/order_txt.rb b/app/lib/order_txt.rb
index 7f23e705..320e429f 100644
--- a/app/lib/order_txt.rb
+++ b/app/lib/order_txt.rb
@@ -8,23 +8,19 @@ class OrderTxt
def to_txt
supplier = @order.supplier
contact = FoodsoftConfig[:contact].symbolize_keys
- text = I18n.t('orders.fax.heading', :name => FoodsoftConfig[:name])
- text += "\n#{Supplier.human_attribute_name(:customer_number)}: #{supplier.customer_number}" unless supplier.customer_number.blank?
+ text = I18n.t('orders.fax.heading', name: FoodsoftConfig[:name])
+ text += "\n#{Supplier.human_attribute_name(:customer_number)}: #{supplier.customer_number}" if supplier.customer_number.present?
text += "\n" + I18n.t('orders.fax.delivery_day')
text += "\n\n#{supplier.name}\n#{supplier.address}\n#{Supplier.human_attribute_name(:fax)}: #{supplier.fax}\n\n"
- text += "****** " + I18n.t('orders.fax.to_address') + "\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 += "****** " + I18n.t('orders.fax.articles') + "\n\n"
- text += format("%8s %8s %s\n", I18n.t('orders.fax.number'), I18n.t('orders.fax.amount'), I18n.t('orders.fax.name'))
+ text += '****** ' + I18n.t('orders.fax.articles') + "\n\n"
+ text += format("%8s %8s %s\n", I18n.t('orders.fax.number'), I18n.t('orders.fax.amount'),
+ I18n.t('orders.fax.name'))
# now display all ordered articles
- @order.order_articles.ordered.includes([:article, :article_price]).each do |oa|
+ @order.order_articles.ordered.includes(%i[article article_price]).each do |oa|
text += format("%8s %8d %s\n", oa.article.order_number, oa.units_to_order.to_i, oa.article.name)
end
text
end
-
- # Helper method to test pdf via rails console: OrderTxt.new(order).save_tmp
- def save_tmp
- File.write("#{Rails.root}/tmp/#{self.class.to_s.underscore}.txt", to_csv.force_encoding("UTF-8"))
- end
end
diff --git a/app/lib/quantity_unit.rb b/app/lib/quantity_unit.rb
deleted file mode 100644
index 0a910f87..00000000
--- a/app/lib/quantity_unit.rb
+++ /dev/null
@@ -1,59 +0,0 @@
-class QuantityUnit
- def initialize(quantity, unit)
- @quantity = quantity
- @unit = unit
- end
-
- def self.parse(number_with_unit)
- # remove whitespace
- number_with_unit = number_with_unit.gsub(/\s+/, '')
- # to lowercase
- number_with_unit = number_with_unit.downcase
- # remove numerical part
- number = number_with_unit.gsub(/[^0-9.,]/, '')
- # remove unit part
- unit = number_with_unit.gsub(/[^a-zA-Z]/, '')
- # convert comma to dot
- number = number.gsub(',', '.')
- # convert to float
- number = number.to_f
-
- return nil unless unit.in?(%w[g kg l ml])
-
- QuantityUnit.new(number, unit)
- end
-
- def scale_price_to_base_unit(price)
- return nil unless price.is_a?(Numeric)
-
- factor = if @unit == 'kg' || @unit == 'l'
- 1
- elsif @unit == 'g' || @unit == 'ml'
- 1000
- end
-
- scaled_price = price / @quantity * factor
- scaled_price.round(2)
-
- base_unit = if @unit == 'kg' || @unit == 'g'
- 'kg'
- elsif @unit == 'l' || @unit == 'ml'
- 'L'
- end
-
- [scaled_price, base_unit]
- end
-
-
- def to_s
- "#{@quantity} #{@unit}"
- end
-
- def quantity
- @quantity
- end
-
- def unit
- @unit
- end
-end
\ No newline at end of file
diff --git a/app/lib/render_csv.rb b/app/lib/render_csv.rb
index c1fd24db..76d77f11 100644
--- a/app/lib/render_csv.rb
+++ b/app/lib/render_csv.rb
@@ -13,14 +13,13 @@ class RenderCsv
end
def to_csv
- options = @options.select { |k| %w(col_sep row_sep).include? k.to_s }
+ options = @options.select { |k| %w[col_sep row_sep].include? k.to_s }
ret = CSV.generate options do |csv|
if h = header
csv << h
end
data { |d| csv << d }
end
- ret << I18n.t('.orders.articles.prices_sum') << ";" << "#{number_to_currency(@object.sum(:gross))}/#{number_to_currency(@object.sum(:net))}" if @options[:custom_csv]
ret.encode(@options[:encoding], invalid: :replace, undef: :replace)
end
@@ -32,12 +31,6 @@ class RenderCsv
yield []
end
- # Helper method to test pdf via rails console: OrderCsv.new(order).save_tmp
- def save_tmp
- encoding = @options[:encoding] || 'UTF-8'
- File.write("#{Rails.root}/tmp/#{self.class.to_s.underscore}.csv", to_csv.force_encoding(encoding))
- end
-
# XXX disable unit to avoid encoding problems, both in unit and whitespace. Also allows computations in spreadsheet.
def number_to_currency(number, options = {})
super(number, options.merge({ unit: '' }))
diff --git a/app/lib/render_pdf.rb b/app/lib/render_pdf.rb
index 479dc4a3..2311e646 100644
--- a/app/lib/render_pdf.rb
+++ b/app/lib/render_pdf.rb
@@ -28,9 +28,9 @@ class RotatedCell < Prawn::Table::Cell::Text
with_font { (@pdf.width_of(@content, options) + padding_top + padding_bottom) * tan_rotation }
end
- def draw_borders(pt)
+ def draw_borders(point)
@pdf.mask(:line_width, :stroke_color) do
- x, y = pt
+ x, y = point
from = [[x - skew, y + (border_top_width / 2.0)],
to = [x, y - height - (border_bottom_width / 2.0)]]
@@ -118,11 +118,6 @@ class RenderPdf < Prawn::Document
render # Render pdf
end
- # Helper method to test pdf via rails console: OrderByGroups.new(order).save_tmp
- def save_tmp
- File.write("#{Rails.root}/tmp/#{self.class.to_s.underscore}.pdf", to_pdf.force_encoding("UTF-8"))
- end
-
# @todo avoid underscore instead of unicode whitespace in pdf :/
def number_to_currency(number, options = {})
super(number, options).gsub("\u202f", ' ') if number
@@ -148,8 +143,8 @@ class RenderPdf < Prawn::Document
protected
- def fontsize(n)
- n
+ def fontsize(size)
+ size
end
# return whether pagebreak or vertical whitespace is used for breaks
diff --git a/app/lib/spreadsheet_file.rb b/app/lib/spreadsheet_file.rb
new file mode 100644
index 00000000..dbca9c90
--- /dev/null
+++ b/app/lib/spreadsheet_file.rb
@@ -0,0 +1,22 @@
+require 'roo'
+
+class SpreadsheetFile
+ def self.parse(file, options = {})
+ filepath = file.is_a?(String) ? file : file.to_path
+ filename = options.delete(:filename) || filepath
+ fileext = File.extname(filename)
+ options[:csv_options] = { col_sep: ';', encoding: 'utf-8' }.merge(options[:csv_options] || {})
+ s = Roo::Spreadsheet.open(filepath, options.merge({ extension: fileext }))
+
+ row_index = 1
+ s.each do |row|
+ if row_index == 1
+ # @todo try to detect headers; for now using the index is ok
+ else
+ yield row, row_index
+ end
+ row_index += 1
+ end
+ row_index
+ end
+end
diff --git a/app/lib/token_verifier.rb b/app/lib/token_verifier.rb
index b481d60f..5f389943 100644
--- a/app/lib/token_verifier.rb
+++ b/app/lib/token_verifier.rb
@@ -19,9 +19,9 @@ class TokenVerifier < ActiveSupport::MessageVerifier
raise InvalidPrefix unless r[1] == @_prefix
# return original message
- if r.length > 2
- r[2]
- end
+ return unless r.length > 2
+
+ r[2]
end
class InvalidMessage < ActiveSupport::MessageVerifier::InvalidSignature; end
diff --git a/app/mailers/mailer.rb b/app/mailers/mailer.rb
index 52e1354f..90c8a062 100644
--- a/app/mailers/mailer.rb
+++ b/app/mailers/mailer.rb
@@ -81,7 +81,7 @@ class Mailer < ActionMailer::Base
add_order_result_attachments order, options
- subject = I18n.t('mailer.order_result_supplier.subject', :name => order.supplier.name)
+ subject = I18n.t('mailer.order_result_supplier.subject', name: order.supplier.name)
subject += " (#{I18n.t('activerecord.attributes.order.pickup')}: #{format_date(order.pickup)})" if order.pickup
mail to: order.supplier.email,
@@ -122,10 +122,11 @@ class Mailer < ActionMailer::Base
if args[:from].is_a? User
args[:reply_to] ||= args[:from]
- args[:from] = format_address(FoodsoftConfig[:email_sender], I18n.t('mailer.from_via_foodsoft', name: show_user(args[:from])))
+ args[:from] =
+ format_address(FoodsoftConfig[:email_sender], I18n.t('mailer.from_via_foodsoft', name: show_user(args[:from])))
end
- [:bcc, :cc, :reply_to, :sender, :to].each do |k|
+ %i[bcc cc reply_to sender to].each do |k|
user = args[k]
args[k] = format_address(user.email, show_user(user)) if user.is_a? User
end
@@ -145,21 +146,21 @@ class Mailer < ActionMailer::Base
def self.deliver_now_with_user_locale(user, &block)
I18n.with_locale(user.settings['profile']['language']) do
- self.deliver_now(&block)
+ deliver_now(&block)
end
end
def self.deliver_now_with_default_locale(&block)
I18n.with_locale(FoodsoftConfig[:default_locale]) do
- self.deliver_now(&block)
+ deliver_now(&block)
end
end
def self.deliver_now
message = yield
message.deliver_now
- rescue => error
- MailDeliveryStatus.create email: message.to[0], message: error.message
+ rescue StandardError => e
+ MailDeliveryStatus.create email: message.to[0], message: e.message
end
# separate method to allow plugins to mess with the attachments
@@ -169,8 +170,7 @@ class Mailer < ActionMailer::Base
end
# separate method to allow plugins to mess with the text
- def additonal_welcome_text(user)
- end
+ def additonal_welcome_text(user); end
private
diff --git a/app/models/article.rb b/app/models/article.rb
index 1eca49cd..561deaf8 100644
--- a/app/models/article.rb
+++ b/app/models/article.rb
@@ -42,7 +42,7 @@ class Article < ApplicationRecord
belongs_to :supplier
# @!attribute article_prices
# @return [Array] Price history (current price first).
- has_many :article_prices, -> { order("created_at DESC") }
+ has_many :article_prices, -> { order('created_at DESC') }
# @!attribute order_articles
# @return [Array] Order articles for this article.
has_many :order_articles
@@ -60,16 +60,16 @@ class Article < ApplicationRecord
scope :not_in_stock, -> { where(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 => 1..15
- validates_length_of :note, :maximum => 255
- validates_length_of :origin, :maximum => 255
- validates_length_of :manufacturer, :maximum => 255
- validates_length_of :order_number, :maximum => 255
- validates_numericality_of :price, :greater_than_or_equal_to => 0
- validates_numericality_of :unit_quantity, :greater_than => 0
- validates_numericality_of :deposit, :tax
+ validates :name, :unit, :price, :tax, :deposit, :unit_quantity, :supplier_id, :article_category, presence: true
+ validates :name, length: { in: 4..60 }
+ validates :unit, length: { in: 1..15 }
+ validates :note, length: { maximum: 255 }
+ validates :origin, length: { maximum: 255 }
+ validates :manufacturer, length: { maximum: 255 }
+ validates :order_number, length: { maximum: 255 }
+ validates :price, numericality: { greater_than_or_equal_to: 0 }
+ validates :unit_quantity, numericality: { greater_than: 0 }
+ validates :deposit, :tax, numericality: true
# validates_uniqueness_of :name, :scope => [:supplier_id, :deleted_at, :type], if: Proc.new {|a| a.supplier.shared_sync_method.blank? or a.supplier.shared_sync_method == 'import' }
# validates_uniqueness_of :name, :scope => [:supplier_id, :deleted_at, :type, :unit, :unit_quantity]
validate :uniqueness_of_name
@@ -78,12 +78,12 @@ class Article < ApplicationRecord
before_save :update_price_history
before_destroy :check_article_in_use
- def self.ransackable_attributes(auth_object = nil)
- %w(id name supplier_id article_category_id unit note manufacturer origin unit_quantity order_number)
+ def self.ransackable_attributes(_auth_object = nil)
+ %w[id name supplier_id article_category_id unit note manufacturer origin unit_quantity order_number]
end
- def self.ransackable_associations(auth_object = nil)
- %w(article_category supplier order_articles orders)
+ def self.ransackable_associations(_auth_object = nil)
+ %w[article_category supplier order_articles orders]
end
# Returns true if article has been updated at least 2 days ago
@@ -96,7 +96,7 @@ class Article < ApplicationRecord
@in_open_order ||= begin
order_articles = OrderArticle.where(order_id: Order.open.collect(&:id))
order_article = order_articles.detect { |oa| oa.article_id == id }
- order_article ? order_article.order : nil
+ order_article&.order
end
end
@@ -112,15 +112,15 @@ class Article < ApplicationRecord
def shared_article_changed?(supplier = self.supplier)
# skip early if the timestamp hasn't changed
shared_article = self.shared_article(supplier)
- unless shared_article.nil? || self.shared_updated_on == shared_article.updated_on
- attrs = unequal_attributes(shared_article)
- if attrs.empty?
- # when attributes not changed, update timestamp of article
- self.update_attribute(:shared_updated_on, shared_article.updated_on)
- false
- else
- attrs
- end
+ return if shared_article.nil? || shared_updated_on == shared_article.updated_on
+
+ attrs = unequal_attributes(shared_article)
+ if attrs.empty?
+ # when attributes not changed, update timestamp of article
+ update_attribute(:shared_updated_on, shared_article.updated_on)
+ false
+ else
+ attrs
end
end
@@ -131,36 +131,33 @@ class Article < ApplicationRecord
def unequal_attributes(new_article, options = {})
# try to convert different units when desired
if options[:convert_units] == false
- new_price, new_unit_quantity = nil, nil
+ new_price = nil
+ new_unit_quantity = nil
else
new_price, new_unit_quantity = convert_units(new_article)
end
if new_price && new_unit_quantity
- new_unit = self.unit
+ new_unit = unit
else
new_price = new_article.price
new_unit_quantity = new_article.unit_quantity
new_unit = new_article.unit
end
- attribute_hash = {
- :name => [self.name, new_article.name],
- :manufacturer => [self.manufacturer, new_article.manufacturer.to_s],
- :origin => [self.origin, new_article.origin],
- :unit => [self.unit, new_unit],
- :price => [self.price.to_f.round(2), new_price.to_f.round(2)],
- :tax => [self.tax, new_article.tax],
- :deposit => [self.deposit.to_f.round(2), new_article.deposit.to_f.round(2)],
- # take care of different num-objects.
- :unit_quantity => [self.unit_quantity.to_s.to_f, new_unit_quantity.to_s.to_f],
- :note => [self.note.to_s, new_article.note.to_s]
- }
- if options[:update_category] == true
- new_article_category = new_article.article_category
- attribute_hash[:article_category] = [self.article_category, new_article_category] unless new_article_category.blank?
- end
-
- Article.compare_attributes(attribute_hash)
+ Article.compare_attributes(
+ {
+ name: [name, new_article.name],
+ manufacturer: [manufacturer, new_article.manufacturer.to_s],
+ origin: [origin, new_article.origin],
+ unit: [unit, new_unit],
+ price: [price.to_f.round(2), new_price.to_f.round(2)],
+ tax: [tax, new_article.tax],
+ deposit: [deposit.to_f.round(2), new_article.deposit.to_f.round(2)],
+ # take care of different num-objects.
+ unit_quantity: [unit_quantity.to_s.to_f, new_unit_quantity.to_s.to_f],
+ note: [note.to_s, new_article.note.to_s]
+ }
+ )
end
# Compare attributes from two different articles.
@@ -169,14 +166,20 @@ class Article < ApplicationRecord
# @param attributes [Hash] Attributes with old and new values
# @return [Hash] Changed attributes with new values
def self.compare_attributes(attributes)
- unequal_attributes = attributes.select { |name, values| values[0] != values[1] && !(values[0].blank? && values[1].blank?) }
- Hash[unequal_attributes.to_a.map { |a| [a[0], a[1].last] }]
+ unequal_attributes = attributes.select do |_name, values|
+ values[0] != values[1] && !(values[0].blank? && values[1].blank?)
+ end
+ unequal_attributes.to_a.map { |a| [a[0], a[1].last] }.to_h
end
# to get the correspondent shared article
def shared_article(supplier = self.supplier)
- self.order_number.blank? and return nil
- @shared_article ||= supplier.shared_supplier.find_article_by_number(self.order_number) rescue nil
+ order_number.blank? and return nil
+ @shared_article ||= begin
+ supplier.shared_supplier.find_article_by_number(order_number)
+ rescue StandardError
+ nil
+ end
end
# convert units in foodcoop-size
@@ -185,31 +188,37 @@ class Article < ApplicationRecord
# returns false if units aren't foodsoft-compatible
# returns nil if units are eqal
def convert_units(new_article = shared_article)
- if unit != new_article.unit
- # legacy, used by foodcoops in Germany
- if new_article.unit == "KI" && unit == "ST" # 'KI' means a box, with a different amount of items in it
- # try to match the size out of its name, e.g. "banana 10-12 St" => 10
- new_unit_quantity = /[0-9\-\s]+(St)/.match(new_article.name).to_s.to_i
- if new_unit_quantity && new_unit_quantity > 0
- new_price = (new_article.price / new_unit_quantity.to_f).round(2)
- [new_price, new_unit_quantity]
- else
- false
- end
- else # use ruby-units to convert
- fc_unit = (::Unit.new(unit) rescue nil)
- supplier_unit = (::Unit.new(new_article.unit) rescue nil)
- if fc_unit && supplier_unit && fc_unit =~ supplier_unit
- conversion_factor = (supplier_unit / fc_unit).to_base.to_r
- new_price = new_article.price / conversion_factor
- new_unit_quantity = new_article.unit_quantity * conversion_factor
- [new_price, new_unit_quantity]
- else
- false
- end
+ return unless unit != new_article.unit
+
+ # legacy, used by foodcoops in Germany
+ if new_article.unit == 'KI' && unit == 'ST' # 'KI' means a box, with a different amount of items in it
+ # try to match the size out of its name, e.g. "banana 10-12 St" => 10
+ new_unit_quantity = /[0-9\-\s]+(St)/.match(new_article.name).to_s.to_i
+ if new_unit_quantity && new_unit_quantity > 0
+ new_price = (new_article.price / new_unit_quantity.to_f).round(2)
+ [new_price, new_unit_quantity]
+ else
+ false
+ end
+ else # use ruby-units to convert
+ fc_unit = begin
+ ::Unit.new(unit)
+ rescue StandardError
+ nil
+ end
+ supplier_unit = begin
+ ::Unit.new(new_article.unit)
+ rescue StandardError
+ nil
+ end
+ if fc_unit != 0 && supplier_unit != 0 && fc_unit && supplier_unit && fc_unit =~ supplier_unit
+ conversion_factor = (supplier_unit / fc_unit).to_base.to_r
+ new_price = new_article.price / conversion_factor
+ new_unit_quantity = new_article.unit_quantity * conversion_factor
+ [new_price, new_unit_quantity]
+ else
+ false
end
- else
- nil
end
end
@@ -226,19 +235,19 @@ class Article < ApplicationRecord
# Checks if the article is in use before it will deleted
def check_article_in_use
- raise I18n.t('articles.model.error_in_use', :article => self.name.to_s) if self.in_open_order
+ raise I18n.t('articles.model.error_in_use', article: name.to_s) if in_open_order
end
# Create an ArticlePrice, when the price-attr are changed.
def update_price_history
- if price_changed?
- article_prices.build(
- :price => price,
- :tax => tax,
- :deposit => deposit,
- :unit_quantity => unit_quantity
- )
- end
+ return unless price_changed?
+
+ article_prices.build(
+ price: price,
+ tax: tax,
+ deposit: deposit,
+ unit_quantity: unit_quantity
+ )
end
def price_changed?
@@ -254,8 +263,8 @@ class Article < ApplicationRecord
# supplier should always be there - except, perhaps, on initialization (on seeding)
if supplier && (supplier.shared_sync_method.blank? || supplier.shared_sync_method == 'import')
errors.add :name, :taken if matches.any?
- else
- errors.add :name, :taken_with_unit if matches.where(unit: unit, unit_quantity: unit_quantity).any?
+ elsif matches.where(unit: unit, unit_quantity: unit_quantity).any?
+ errors.add :name, :taken_with_unit
end
end
end
diff --git a/app/models/article_category.rb b/app/models/article_category.rb
index 28597a59..1574b5d5 100644
--- a/app/models/article_category.rb
+++ b/app/models/article_category.rb
@@ -17,16 +17,16 @@ class ArticleCategory < ApplicationRecord
normalize_attributes :name, :description
- validates :name, :presence => true, :uniqueness => true, :length => { :minimum => 2 }
+ validates :name, presence: true, uniqueness: true, length: { minimum: 2 }
before_destroy :check_for_associated_articles
- def self.ransackable_attributes(auth_object = nil)
- %w(id name)
+ def self.ransackable_attributes(_auth_object = nil)
+ %w[id name]
end
- def self.ransackable_associations(auth_object = nil)
- %w(articles order_articles orders)
+ def self.ransackable_associations(_auth_object = nil)
+ %w[articles order_articles orders]
end
# Find a category that matches a category name; may return nil.
@@ -40,7 +40,11 @@ class ArticleCategory < ApplicationRecord
# case-insensitive substring match (take the closest match = shortest)
c = ArticleCategory.where('name LIKE ?', "%#{category}%") unless c && c.any?
# case-insensitive phrase present in category description
- c = ArticleCategory.where('description LIKE ?', "%#{category}%").select { |s| s.description.match /(^|,)\s*#{category}\s*(,|$)/i } unless c && c.any?
+ unless c && c.any?
+ c = ArticleCategory.where('description LIKE ?', "%#{category}%").select do |s|
+ s.description.match(/(^|,)\s*#{category}\s*(,|$)/i)
+ end
+ end
# return closest match if there are multiple
c = c.sort_by { |s| s.name.length }.first if c.respond_to? :sort_by
c
@@ -50,6 +54,9 @@ class ArticleCategory < ApplicationRecord
# Deny deleting the category when there are associated articles.
def check_for_associated_articles
- raise I18n.t('activerecord.errors.has_many_left', collection: Article.model_name.human) if articles.undeleted.exists?
+ return unless articles.undeleted.exists?
+
+ raise I18n.t('activerecord.errors.has_many_left',
+ collection: Article.model_name.human)
end
end
diff --git a/app/models/article_price.rb b/app/models/article_price.rb
index f6879eac..ac3b2b4c 100644
--- a/app/models/article_price.rb
+++ b/app/models/article_price.rb
@@ -24,8 +24,8 @@ class ArticlePrice < ApplicationRecord
localize_input_of :price, :tax, :deposit
- validates_presence_of :price, :tax, :deposit, :unit_quantity
- validates_numericality_of :price, :greater_than_or_equal_to => 0
- validates_numericality_of :unit_quantity, :greater_than => 0
- validates_numericality_of :deposit, :tax
+ validates :price, :tax, :deposit, :unit_quantity, presence: true
+ validates :price, numericality: { greater_than_or_equal_to: 0 }
+ validates :unit_quantity, numericality: { greater_than: 0 }
+ validates :deposit, :tax, numericality: true
end
diff --git a/app/models/bank_account.rb b/app/models/bank_account.rb
index de15ee4b..f433b48a 100644
--- a/app/models/bank_account.rb
+++ b/app/models/bank_account.rb
@@ -5,10 +5,10 @@ class BankAccount < ApplicationRecord
normalize_attributes :name, :iban, :description
- validates :name, :presence => true, :uniqueness => true, :length => { :minimum => 2 }
- validates :iban, :presence => true, :uniqueness => true
- validates_format_of :iban, :with => /\A[A-Z]{2}[0-9]{2}[0-9A-Z]{,30}\z/
- validates_numericality_of :balance, :message => I18n.t('bank_account.model.invalid_balance')
+ validates :name, presence: true, uniqueness: true, length: { minimum: 2 }
+ validates :iban, presence: true, uniqueness: true
+ validates :iban, format: { with: /\A[A-Z]{2}[0-9]{2}[0-9A-Z]{,30}\z/ }
+ validates :balance, numericality: { message: I18n.t('bank_account.model.invalid_balance') }
# @return [Function] Method wich can be called to import transaction from a bank or nil if unsupported
def find_connector
@@ -18,10 +18,8 @@ class BankAccount < ApplicationRecord
def assign_unlinked_transactions
count = 0
- bank_transactions.without_financial_link.includes(:supplier, :user).each do |t|
- if t.assign_to_ordergroup || t.assign_to_invoice
- count += 1
- end
+ bank_transactions.without_financial_link.includes(:supplier, :user).find_each do |t|
+ count += 1 if t.assign_to_ordergroup || t.assign_to_invoice
end
count
end
diff --git a/app/models/bank_gateway.rb b/app/models/bank_gateway.rb
index 3811f128..f8043755 100644
--- a/app/models/bank_gateway.rb
+++ b/app/models/bank_gateway.rb
@@ -4,5 +4,5 @@ class BankGateway < ApplicationRecord
scope :with_unattended_support, -> { where.not(unattended_user: nil) }
- validates_presence_of :name, :url
+ validates :name, :url, presence: true
end
diff --git a/app/models/bank_transaction.rb b/app/models/bank_transaction.rb
index 5d9d6c04..0f74d1e0 100644
--- a/app/models/bank_transaction.rb
+++ b/app/models/bank_transaction.rb
@@ -22,8 +22,8 @@ class BankTransaction < ApplicationRecord
belongs_to :supplier, optional: true, foreign_key: 'iban', primary_key: 'iban'
belongs_to :user, optional: true, foreign_key: 'iban', primary_key: 'iban'
- validates_presence_of :date, :amount, :bank_account_id
- validates_numericality_of :amount
+ validates :date, :amount, :bank_account_id, presence: true
+ validates :amount, numericality: true
scope :without_financial_link, -> { where(financial_link: nil) }
@@ -31,13 +31,13 @@ class BankTransaction < ApplicationRecord
localize_input_of :amount
def image_url
- 'data:image/png;base64,' + Base64.encode64(self.image)
+ 'data:image/png;base64,' + Base64.encode64(image)
end
def assign_to_invoice
return false unless supplier
- content = text || ""
+ content = text || ''
content += "\n" + reference if reference.present?
invoices = supplier.invoices.unpaid.select { |i| content.include? i.number }
invoices_sum = invoices.map(&:amount).sum
@@ -49,7 +49,7 @@ class BankTransaction < ApplicationRecord
update_attribute :financial_link, link
end
- return true
+ true
end
def assign_to_ordergroup
@@ -78,6 +78,6 @@ class BankTransaction < ApplicationRecord
update_attribute :financial_link, link
end
- return true
+ true
end
end
diff --git a/app/models/concerns/custom_fields.rb b/app/models/concerns/custom_fields.rb
index d54cebe5..aafec389 100644
--- a/app/models/concerns/custom_fields.rb
+++ b/app/models/concerns/custom_fields.rb
@@ -10,7 +10,7 @@ module CustomFields
end
after_save do
- self.settings.custom_fields = custom_fields if custom_fields
+ settings.custom_fields = custom_fields if custom_fields
end
end
end
diff --git a/app/models/concerns/find_each_with_order.rb b/app/models/concerns/find_each_with_order.rb
index 0e7cd5cd..faf545b2 100644
--- a/app/models/concerns/find_each_with_order.rb
+++ b/app/models/concerns/find_each_with_order.rb
@@ -3,9 +3,9 @@ module FindEachWithOrder
extend ActiveSupport::Concern
class_methods do
- def find_each_with_order(options = {})
+ def find_each_with_order(options = {}, &block)
find_in_batches_with_order(options) do |records|
- records.each { |record| yield record }
+ records.each(&block)
end
end
diff --git a/app/models/concerns/localize_input.rb b/app/models/concerns/localize_input.rb
index b6330fcc..7cd26acd 100644
--- a/app/models/concerns/localize_input.rb
+++ b/app/models/concerns/localize_input.rb
@@ -10,7 +10,7 @@ module LocalizeInput
input.gsub!(delimiter, "") if input.match(/\d+#{Regexp.escape(delimiter)}+\d+#{Regexp.escape(separator)}+\d+/) # Remove delimiter
input.gsub!(separator, ".") or input.gsub!(",", ".") # Replace separator with db compatible character
input
- rescue
+ rescue StandardError
Rails.logger.warn "Can't localize input: #{input}"
input
end
diff --git a/app/models/concerns/mark_as_deleted_with_name.rb b/app/models/concerns/mark_as_deleted_with_name.rb
index 4b888438..fb0aa590 100644
--- a/app/models/concerns/mark_as_deleted_with_name.rb
+++ b/app/models/concerns/mark_as_deleted_with_name.rb
@@ -3,7 +3,7 @@ module MarkAsDeletedWithName
def mark_as_deleted
# get maximum length of name
- max_length = 100000
+ max_length = 100_000
if lenval = self.class.validators_on(:name).detect { |v| v.is_a?(ActiveModel::Validations::LengthValidator) }
max_length = lenval.options[:maximum]
end
diff --git a/app/models/concerns/price_calculation.rb b/app/models/concerns/price_calculation.rb
index 03b9a7ad..8d56d671 100644
--- a/app/models/concerns/price_calculation.rb
+++ b/app/models/concerns/price_calculation.rb
@@ -9,12 +9,12 @@ module PriceCalculation
# @return [Number] Price for the foodcoop-member.
def fc_price
- add_percent(gross_price, FoodsoftConfig[:price_markup])
+ add_percent(gross_price, FoodsoftConfig[:price_markup].to_i)
end
private
def add_percent(value, percent)
- (value * (percent * 0.01 + 1)).round(2)
+ (value * ((percent * 0.01) + 1)).round(2)
end
end
diff --git a/app/models/delivery.rb b/app/models/delivery.rb
index ab5ca5ec..bb2aed45 100644
--- a/app/models/delivery.rb
+++ b/app/models/delivery.rb
@@ -4,10 +4,10 @@ class Delivery < StockEvent
scope :recent, -> { order('created_at DESC').limit(10) }
- validates_presence_of :supplier_id
+ validates :supplier_id, presence: true
validate :stock_articles_must_be_unique
- accepts_nested_attributes_for :stock_changes, :allow_destroy => :true
+ accepts_nested_attributes_for :stock_changes, allow_destroy: :true
def new_stock_changes=(stock_change_attributes)
for attributes in stock_change_attributes
@@ -16,7 +16,7 @@ class Delivery < StockEvent
end
def includes_article?(article)
- self.stock_changes.map { |stock_change| stock_change.stock_article.id }.include? article.id
+ stock_changes.map { |stock_change| stock_change.stock_article.id }.include? article.id
end
def sum(type = :gross)
@@ -39,8 +39,8 @@ class Delivery < StockEvent
protected
def stock_articles_must_be_unique
- unless stock_changes.reject { |sc| sc.marked_for_destruction? }.map { |sc| sc.stock_article.id }.uniq!.nil?
- errors.add(:base, I18n.t('model.delivery.each_stock_article_must_be_unique'))
- end
+ return if stock_changes.reject { |sc| sc.marked_for_destruction? }.map { |sc| sc.stock_article.id }.uniq!.nil?
+
+ errors.add(:base, I18n.t('model.delivery.each_stock_article_must_be_unique'))
end
end
diff --git a/app/models/financial_link.rb b/app/models/financial_link.rb
index 30a1955c..51108cd2 100644
--- a/app/models/financial_link.rb
+++ b/app/models/financial_link.rb
@@ -4,13 +4,13 @@ class FinancialLink < ApplicationRecord
has_many :invoices
scope :incomplete, -> { with_full_sum.where.not('full_sums.full_sum' => 0) }
- scope :unused, -> {
+ scope :unused, lambda {
includes(:bank_transactions, :financial_transactions, :invoices)
.where(bank_transactions: { financial_link_id: nil })
.where(financial_transactions: { financial_link_id: nil })
.where(invoices: { financial_link_id: nil })
}
- scope :with_full_sum, -> {
+ scope :with_full_sum, lambda {
select(:id, :note, :full_sum).joins(<<-SQL)
LEFT JOIN (
SELECT id, COALESCE(bt_sum, 0) - COALESCE(ft_sum, 0) + COALESCE(i_sum, 0) AS full_sum
diff --git a/app/models/financial_transaction.rb b/app/models/financial_transaction.rb
index bd2c4e58..1556ecbe 100644
--- a/app/models/financial_transaction.rb
+++ b/app/models/financial_transaction.rb
@@ -8,14 +8,16 @@ class FinancialTransaction < ApplicationRecord
belongs_to :financial_link, optional: true
belongs_to :financial_transaction_type
belongs_to :group_order, optional: true
- belongs_to :reverts, optional: true, class_name: 'FinancialTransaction', foreign_key: 'reverts_id'
+ belongs_to :reverts, optional: true, class_name: 'FinancialTransaction'
has_one :reverted_by, class_name: 'FinancialTransaction', foreign_key: 'reverts_id'
- validates_presence_of :amount, :note, :user_id
- validates_numericality_of :amount, greater_then: -100_000,
- less_than: 100_000
+ validates :amount, :note, :user_id, presence: true
+ validates :amount, numericality: { greater_then: -100_000,
+ less_than: 100_000 }
- scope :visible, -> { joins('LEFT JOIN financial_transactions r ON financial_transactions.id = r.reverts_id').where('r.id IS NULL').where(reverts: nil) }
+ scope :visible, lambda {
+ joins('LEFT JOIN financial_transactions r ON financial_transactions.id = r.reverts_id').where('r.id IS NULL').where(reverts: nil)
+ }
scope :without_financial_link, -> { where(financial_link: nil) }
scope :with_ordergroup, -> { where.not(ordergroup: nil) }
@@ -28,12 +30,12 @@ class FinancialTransaction < ApplicationRecord
# @todo remove alias (and rename created_on to created_at below) after #575
ransack_alias :created_at, :created_on
- def self.ransackable_attributes(auth_object = nil)
- %w(id amount note created_on user_id)
+ def self.ransackable_attributes(_auth_object = nil)
+ %w[id amount note created_on user_id]
end
- def self.ransackable_associations(auth_object = nil)
- %w() # none, and certainly not user until we've secured that more
+ def self.ransackable_associations(_auth_object = nil)
+ %w[] # none, and certainly not user until we've secured that more
end
# Use this save method instead of simple save and after callback
diff --git a/app/models/financial_transaction_class.rb b/app/models/financial_transaction_class.rb
index 43ded5fd..0c924993 100644
--- a/app/models/financial_transaction_class.rb
+++ b/app/models/financial_transaction_class.rb
@@ -5,7 +5,7 @@ class FinancialTransactionClass < ApplicationRecord
has_many :ordergroups, -> { distinct }, through: :financial_transactions
validates :name, presence: true
- validates_uniqueness_of :name
+ validates :name, uniqueness: true
after_save :update_balance_of_ordergroups
diff --git a/app/models/financial_transaction_type.rb b/app/models/financial_transaction_type.rb
index 392a1a95..97ed7979 100644
--- a/app/models/financial_transaction_type.rb
+++ b/app/models/financial_transaction_type.rb
@@ -5,13 +5,13 @@ class FinancialTransactionType < ApplicationRecord
has_many :ordergroups, -> { distinct }, through: :financial_transactions
validates :name, presence: true
- validates_uniqueness_of :name
- validates_uniqueness_of :name_short, allow_blank: true, allow_nil: true
- validates_format_of :name_short, :with => /\A[A-Za-z]*\z/
+ validates :name, uniqueness: true
+ validates :name_short, uniqueness: { allow_blank: true }
+ validates :name_short, format: { with: /\A[A-Za-z]*\z/ }
validates :financial_transaction_class, presence: true
- after_save :update_balance_of_ordergroups
before_destroy :restrict_deleting_last_financial_transaction_type
+ after_save :update_balance_of_ordergroups
scope :with_name_short, -> { where.not(name_short: [nil, '']) }
@@ -20,7 +20,7 @@ class FinancialTransactionType < ApplicationRecord
end
def self.has_multiple_types
- self.count > 1
+ count > 1
end
protected
diff --git a/app/models/group.rb b/app/models/group.rb
index a667ea5a..a4a770eb 100644
--- a/app/models/group.rb
+++ b/app/models/group.rb
@@ -7,8 +7,8 @@ class Group < ApplicationRecord
has_many :memberships, dependent: :destroy
has_many :users, -> { where(deleted_at: nil) }, through: :memberships
- validates :name, :presence => true, :length => { :in => 1..25 }
- validates_uniqueness_of :name
+ validates :name, presence: true, length: { in: 1..25 }
+ validates :name, uniqueness: true
attr_reader :user_tokens
@@ -25,7 +25,7 @@ class Group < ApplicationRecord
end
def user_tokens=(ids)
- self.user_ids = ids.split(",")
+ self.user_ids = ids.split(',')
end
def deleted?
diff --git a/app/models/group_order.rb b/app/models/group_order.rb
index f3153c44..183b663a 100644
--- a/app/models/group_order.rb
+++ b/app/models/group_order.rb
@@ -6,14 +6,14 @@ class GroupOrder < ApplicationRecord
belongs_to :order
belongs_to :ordergroup, optional: true
- has_many :group_order_articles, :dependent => :destroy
- has_many :order_articles, :through => :group_order_articles
+ has_many :group_order_articles, dependent: :destroy
+ has_many :order_articles, through: :group_order_articles
has_one :financial_transaction
belongs_to :updated_by, optional: true, class_name: 'User', foreign_key: 'updated_by_user_id'
- validates_presence_of :order_id
- validates_numericality_of :price
- validates_uniqueness_of :ordergroup_id, :scope => :order_id # order groups can only order once per order
+ validates :order_id, presence: true
+ validates :price, numericality: true
+ validates :ordergroup_id, uniqueness: { scope: :order_id } # order groups can only order once per order
scope :in_open_orders, -> { joins(:order).merge(Order.open) }
scope :in_finished_orders, -> { joins(:order).merge(Order.finished_not_closed) }
@@ -21,12 +21,12 @@ class GroupOrder < ApplicationRecord
scope :ordered, -> { includes(:ordergroup).order('groups.name') }
- def self.ransackable_attributes(auth_object = nil)
- %w(id price)
+ def self.ransackable_attributes(_auth_object = nil)
+ %w[id price]
end
- def self.ransackable_associations(auth_object = nil)
- %w(order group_order_articles)
+ def self.ransackable_associations(_auth_object = nil)
+ %w[order group_order_articles]
end
# Generate some data for the javascript methods in ordering view
@@ -37,24 +37,24 @@ class GroupOrder < ApplicationRecord
# load prices and other stuff....
data[:order_articles] = {}
- order.articles_grouped_by_category.each do |article_category, order_articles|
+ order.articles_grouped_by_category.each do |_article_category, order_articles|
order_articles.each do |order_article|
# Get the result of last time ordering, if possible
goa = group_order_articles.detect { |goa| goa.order_article_id == order_article.id }
# Build hash with relevant data
data[:order_articles][order_article.id] = {
- :price => order_article.article.fc_price,
- :unit => order_article.article.unit_quantity,
- :quantity => (goa ? goa.quantity : 0),
- :others_quantity => order_article.quantity - (goa ? goa.quantity : 0),
- :used_quantity => (goa ? goa.result(:quantity) : 0),
- :tolerance => (goa ? goa.tolerance : 0),
- :others_tolerance => order_article.tolerance - (goa ? goa.tolerance : 0),
- :used_tolerance => (goa ? goa.result(:tolerance) : 0),
- :total_price => (goa ? goa.total_price : 0),
- :missing_units => order_article.missing_units,
- :quantity_available => (order.stockit? ? order_article.article.quantity_available : 0)
+ price: order_article.article.fc_price,
+ unit: order_article.article.unit_quantity,
+ quantity: (goa ? goa.quantity : 0),
+ others_quantity: order_article.quantity - (goa ? goa.quantity : 0),
+ used_quantity: (goa ? goa.result(:quantity) : 0),
+ tolerance: (goa ? goa.tolerance : 0),
+ others_tolerance: order_article.tolerance - (goa ? goa.tolerance : 0),
+ used_tolerance: (goa ? goa.result(:tolerance) : 0),
+ total_price: (goa ? goa.total_price : 0),
+ missing_units: order_article.missing_units,
+ quantity_available: (order.stockit? ? order_article.article.quantity_available : 0)
}
end
end
@@ -69,12 +69,12 @@ class GroupOrder < ApplicationRecord
# Get ordered quantities and update group_order_articles/_quantities...
if group_order_articles_attributes
- quantities = group_order_articles_attributes.fetch(order_article.id.to_s, { :quantity => 0, :tolerance => 0 })
+ quantities = group_order_articles_attributes.fetch(order_article.id.to_s, { quantity: 0, tolerance: 0 })
group_order_article.update_quantities(quantities[:quantity].to_i, quantities[:tolerance].to_i)
end
# Also update results for the order_article
- logger.debug "[save_group_order_articles] update order_article.results!"
+ logger.debug '[save_group_order_articles] update order_article.results!'
order_article.update_results!
end
@@ -83,7 +83,7 @@ class GroupOrder < ApplicationRecord
# Updates the "price" attribute.
def update_price!
- total = group_order_articles.includes(:order_article => [:article, :article_price]).to_a.sum(&:total_price)
+ total = group_order_articles.includes(order_article: %i[article article_price]).to_a.sum(&:total_price)
update_attribute(:price, total)
end
@@ -97,7 +97,12 @@ class GroupOrder < ApplicationRecord
end
def ordergroup_name
- ordergroup ? ordergroup.name : I18n.t('model.group_order.stock_ordergroup_name', :user => updated_by.try(:name) || '?')
+ if ordergroup
+ ordergroup.name
+ else
+ I18n.t('model.group_order.stock_ordergroup_name',
+ user: updated_by.try(:name) || '?')
+ end
end
def total
diff --git a/app/models/group_order_article.rb b/app/models/group_order_article.rb
index 5a02734d..7b95d462 100644
--- a/app/models/group_order_article.rb
+++ b/app/models/group_order_article.rb
@@ -8,21 +8,21 @@ class GroupOrderArticle < ApplicationRecord
belongs_to :order_article
has_many :group_order_article_quantities, dependent: :destroy
- validates_presence_of :group_order, :order_article
- validates_uniqueness_of :order_article_id, :scope => :group_order_id # just once an article per group order
+ validates :group_order, :order_article, presence: true
+ validates :order_article_id, uniqueness: { scope: :group_order_id } # just once an article per group order
validate :check_order_not_closed # don't allow changes to closed (aka settled) orders
validates :quantity, :tolerance, numericality: { only_integer: true, greater_than_or_equal_to: 0 }
- scope :ordered, -> { includes(:group_order => :ordergroup).order('groups.name') }
+ scope :ordered, -> { includes(group_order: :ordergroup).order('groups.name') }
localize_input_of :result
- def self.ransackable_attributes(auth_object = nil)
- %w(id quantity tolerance result)
+ def self.ransackable_attributes(_auth_object = nil)
+ %w[id quantity tolerance result]
end
- def self.ransackable_associations(auth_object = nil)
- %w(order_article group_order)
+ def self.ransackable_associations(_auth_object = nil)
+ %w[order_article group_order]
end
# Setter used in group_order_article#new
@@ -32,7 +32,7 @@ class GroupOrderArticle < ApplicationRecord
end
def ordergroup_id
- group_order.try!(:ordergroup_id)
+ group_order&.ordergroup_id
end
# Updates the quantity/tolerance for this GroupOrderArticle by updating both GroupOrderArticle properties
@@ -45,7 +45,7 @@ class GroupOrderArticle < ApplicationRecord
# When quantity and tolerance are zero, we don't serve any purpose
if quantity == 0 && tolerance == 0
- logger.debug("Self-destructing since requested quantity and tolerance are zero")
+ logger.debug('Self-destructing since requested quantity and tolerance are zero')
destroy!
return
end
@@ -54,26 +54,28 @@ class GroupOrderArticle < ApplicationRecord
quantities = group_order_article_quantities.order('created_on DESC').to_a
logger.debug("GroupOrderArticleQuantity items found: #{quantities.size}")
- if (quantities.size == 0)
+ if quantities.size == 0
# There is no GroupOrderArticleQuantity item yet, just insert with desired quantities...
- logger.debug("No quantities entry at all, inserting a new one with the desired quantities")
- quantities.push(GroupOrderArticleQuantity.new(:group_order_article => self, :quantity => quantity, :tolerance => tolerance))
- self.quantity, self.tolerance = quantity, tolerance
+ logger.debug('No quantities entry at all, inserting a new one with the desired quantities')
+ quantities.push(GroupOrderArticleQuantity.new(group_order_article: self, quantity: quantity,
+ tolerance: tolerance))
+ self.quantity = quantity
+ self.tolerance = tolerance
else
# Decrease quantity/tolerance if necessary by going through the existing items and decreasing their values...
i = 0
- while (i < quantities.size && (quantity < self.quantity || tolerance < self.tolerance))
+ while i < quantities.size && (quantity < self.quantity || tolerance < self.tolerance)
logger.debug("Need to decrease quantities for GroupOrderArticleQuantity[#{quantities[i].id}]")
- if (quantity < self.quantity && quantities[i].quantity > 0)
+ if quantity < self.quantity && quantities[i].quantity > 0
delta = self.quantity - quantity
- delta = (delta > quantities[i].quantity ? quantities[i].quantity : delta)
+ delta = [delta, quantities[i].quantity].min
logger.debug("Decreasing quantity by #{delta}")
quantities[i].quantity -= delta
self.quantity -= delta
end
- if (tolerance < self.tolerance && quantities[i].tolerance > 0)
+ if tolerance < self.tolerance && quantities[i].tolerance > 0
delta = self.tolerance - tolerance
- delta = (delta > quantities[i].tolerance ? quantities[i].tolerance : delta)
+ delta = [delta, quantities[i].tolerance].min
logger.debug("Decreasing tolerance by #{delta}")
quantities[i].tolerance -= delta
self.tolerance -= delta
@@ -81,12 +83,12 @@ class GroupOrderArticle < ApplicationRecord
i += 1
end
# If there is at least one increased value: insert a new GroupOrderArticleQuantity object
- if (quantity > self.quantity || tolerance > self.tolerance)
- logger.debug("Inserting a new GroupOrderArticleQuantity")
+ if quantity > self.quantity || tolerance > self.tolerance
+ logger.debug('Inserting a new GroupOrderArticleQuantity')
quantities.insert(0, GroupOrderArticleQuantity.new(
- :group_order_article => self,
- :quantity => (quantity > self.quantity ? quantity - self.quantity : 0),
- :tolerance => (tolerance > self.tolerance ? tolerance - self.tolerance : 0)
+ group_order_article: self,
+ quantity: (quantity > self.quantity ? quantity - self.quantity : 0),
+ tolerance: (tolerance > self.tolerance ? tolerance - self.tolerance : 0)
))
# Recalc totals:
self.quantity += quantities[0].quantity
@@ -95,8 +97,9 @@ class GroupOrderArticle < ApplicationRecord
end
# Check if something went terribly wrong and quantites have not been adjusted as desired.
- if (self.quantity != quantity || self.tolerance != tolerance)
- raise ActiveRecord::RecordNotSaved.new('Unable to update GroupOrderArticle/-Quantities to desired quantities!', self)
+ if self.quantity != quantity || self.tolerance != tolerance
+ raise ActiveRecord::RecordNotSaved.new('Unable to update GroupOrderArticle/-Quantities to desired quantities!',
+ self)
end
# Remove zero-only items.
@@ -121,7 +124,7 @@ class GroupOrderArticle < ApplicationRecord
quantity = tolerance = total_quantity = 0
# Get total
- if not total.nil?
+ if !total.nil?
logger.debug "<#{order_article.article.name}> => #{total} (given)"
elsif order_article.article.is_a?(StockArticle)
total = order_article.article.quantity
@@ -145,7 +148,7 @@ class GroupOrderArticle < ApplicationRecord
q = goaq.quantity
q = [q, total - total_quantity].min if first_order_first_serve
total_quantity += q
- if goaq.group_order_article_id == self.id
+ if goaq.group_order_article_id == id
logger.debug "increasing quantity by #{q}"
quantity += q
end
@@ -154,11 +157,11 @@ class GroupOrderArticle < ApplicationRecord
# Determine tolerance to be ordered...
if total_quantity < total
- logger.debug "determining additional items to be ordered from tolerance"
+ logger.debug 'determining additional items to be ordered from tolerance'
order_quantities.each do |goaq|
q = [goaq.tolerance, total - total_quantity].min
total_quantity += q
- if goaq.group_order_article_id == self.id
+ if goaq.group_order_article_id == id
logger.debug "increasing tolerance by #{q}"
tolerance += q
end
@@ -170,7 +173,7 @@ class GroupOrderArticle < ApplicationRecord
end
# memoize result unless a total is given
- r = { :quantity => quantity, :tolerance => tolerance, :total => quantity + tolerance }
+ r = { quantity: quantity, tolerance: tolerance, total: quantity + tolerance }
@calculate_result = r if total.nil?
r
end
@@ -185,8 +188,8 @@ class GroupOrderArticle < ApplicationRecord
# This is used for automatic distribution, e.g., in order.finish! or when receiving orders
def save_results!(article_total = nil)
new_result = calculate_result(article_total)[:total]
- self.update_attribute(:result_computed, new_result)
- self.update_attribute(:result, new_result)
+ update_attribute(:result_computed, new_result)
+ update_attribute(:result, new_result)
end
# Returns total price for this individual article
@@ -213,8 +216,8 @@ class GroupOrderArticle < ApplicationRecord
private
def check_order_not_closed
- if order_article.order.closed?
- errors.add(:order_article, I18n.t('model.group_order_article.order_closed'))
- end
+ return unless order_article.order.closed?
+
+ errors.add(:order_article, I18n.t('model.group_order_article.order_closed'))
end
end
diff --git a/app/models/group_order_article_quantity.rb b/app/models/group_order_article_quantity.rb
index 1e29985f..12832b2c 100644
--- a/app/models/group_order_article_quantity.rb
+++ b/app/models/group_order_article_quantity.rb
@@ -4,5 +4,5 @@
class GroupOrderArticleQuantity < ApplicationRecord
belongs_to :group_order_article
- validates_presence_of :group_order_article_id
+ validates :group_order_article_id, presence: true
end
diff --git a/app/models/invite.rb b/app/models/invite.rb
index e37a8a18..d471aa50 100644
--- a/app/models/invite.rb
+++ b/app/models/invite.rb
@@ -5,12 +5,12 @@ class Invite < ApplicationRecord
belongs_to :user
belongs_to :group
- validates_format_of :email, :with => /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i
- validates_presence_of :user
- validates_presence_of :group
- validates_presence_of :token
- validates_presence_of :expires_at
- validate :email_not_already_registered, :on => :create
+ validates :email, format: { with: /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i }
+ validates :user, presence: true
+ validates :group, presence: true
+ validates :token, presence: true
+ validates :expires_at, presence: true
+ validate :email_not_already_registered, on: :create
before_validation :set_token_and_expires_at
@@ -19,15 +19,15 @@ class Invite < ApplicationRecord
# Before validation, set token and expires_at.
def set_token_and_expires_at
self.token = Digest::SHA1.hexdigest(Time.now.to_s + rand(100).to_s)
- self.expires_at = Time.now.advance(:days => 7)
+ self.expires_at = Time.now.advance(days: 7)
end
private
# 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, I18n.t('invites.errors.already_member'))
- end
+ return if User.find_by_email(email).nil?
+
+ errors.add(:email, I18n.t('invites.errors.already_member'))
end
end
diff --git a/app/models/invoice.rb b/app/models/invoice.rb
index f2a8866f..2bf3aaee 100644
--- a/app/models/invoice.rb
+++ b/app/models/invoice.rb
@@ -3,13 +3,13 @@ class Invoice < ApplicationRecord
include LocalizeInput
belongs_to :supplier
- belongs_to :created_by, :class_name => 'User', :foreign_key => 'created_by_user_id'
+ belongs_to :created_by, class_name: 'User', foreign_key: 'created_by_user_id'
belongs_to :financial_link, optional: true
has_many :deliveries, dependent: :nullify
has_many :orders, dependent: :nullify
- validates_presence_of :supplier_id
- validates_numericality_of :amount, :deposit, :deposit_credit
+ validates :supplier_id, presence: true
+ validates :amount, :deposit, :deposit_credit, numericality: true
validate :valid_attachment
scope :unpaid, -> { where(paid_on: nil) }
@@ -23,18 +23,18 @@ class Invoice < ApplicationRecord
def attachment=(incoming_file)
self.attachment_data = incoming_file.read
# allow to soft-fail when FileMagic isn't present and removed from Gemfile (e.g. Heroku)
- self.attachment_mime = defined?(FileMagic) ? FileMagic.new(FileMagic::MAGIC_MIME).buffer(self.attachment_data) : 'application/octet-stream'
+ self.attachment_mime = defined?(FileMagic) ? FileMagic.new(FileMagic::MAGIC_MIME).buffer(attachment_data) : 'application/octet-stream'
end
def delete_attachment=(value)
- if value == '1'
- self.attachment_data = nil
- self.attachment_mime = nil
- end
+ return unless value == '1'
+
+ self.attachment_data = nil
+ self.attachment_mime = nil
end
def user_can_edit?(user)
- user.role_finance? || (user.role_invoices? && !self.paid_on && self.created_by.try(:id) == user.id)
+ user.role_finance? || (user.role_invoices? && !paid_on && created_by.try(:id) == user.id)
end
# Amount without deposit
@@ -45,9 +45,9 @@ class Invoice < ApplicationRecord
def orders_sum
orders
.joins(order_articles: [:article_price])
- .sum("COALESCE(order_articles.units_received, order_articles.units_billed, order_articles.units_to_order)" \
- + "* article_prices.unit_quantity" \
- + "* ROUND((article_prices.price + article_prices.deposit) * (100 + article_prices.tax) / 100, 2)")
+ .sum('COALESCE(order_articles.units_received, order_articles.units_billed, order_articles.units_to_order)' \
+ + '* article_prices.unit_quantity' \
+ + '* ROUND((article_prices.price + article_prices.deposit) * (100 + article_prices.tax) / 100, 2)')
end
def orders_transport_sum
@@ -63,11 +63,11 @@ class Invoice < ApplicationRecord
protected
def valid_attachment
- if attachment_data
- mime = MIME::Type.simplified(attachment_mime)
- unless ['application/pdf', 'image/jpeg'].include? mime
- errors.add :attachment, I18n.t('model.invoice.invalid_mime', :mime => mime)
- end
- end
+ return unless attachment_data
+
+ mime = MIME::Type.simplified(attachment_mime)
+ return if ['application/pdf', 'image/jpeg'].include? mime
+
+ errors.add :attachment, I18n.t('model.invoice.invalid_mime', mime: mime)
end
end
diff --git a/app/models/membership.rb b/app/models/membership.rb
index bebf00e2..4ebc061c 100644
--- a/app/models/membership.rb
+++ b/app/models/membership.rb
@@ -8,6 +8,6 @@ class Membership < ApplicationRecord
# check if this is the last admin-membership and deny
def check_last_admin
- raise I18n.t('model.membership.no_admin_delete') if self.group.role_admin? && self.group.memberships.size == 1 && Group.where(role_admin: true).count == 1
+ raise I18n.t('model.membership.no_admin_delete') if group.role_admin? && group.memberships.size == 1 && Group.where(role_admin: true).count == 1
end
end
diff --git a/app/models/order.rb b/app/models/order.rb
index e83307f3..ada62e59 100644
--- a/app/models/order.rb
+++ b/app/models/order.rb
@@ -2,29 +2,29 @@ class Order < ApplicationRecord
attr_accessor :ignore_warnings, :transport_distribution
# Associations
- has_many :order_articles, :dependent => :destroy
- has_many :articles, :through => :order_articles
- has_many :group_orders, :dependent => :destroy
- has_many :ordergroups, :through => :group_orders
- has_many :users_ordered, :through => :ordergroups, :source => :users
- has_many :comments, -> { order('created_at') }, :class_name => "OrderComment"
+ has_many :order_articles, dependent: :destroy
+ has_many :articles, through: :order_articles
+ has_many :group_orders, dependent: :destroy
+ has_many :ordergroups, through: :group_orders
+ has_many :users_ordered, through: :ordergroups, source: :users
+ has_many :comments, -> { order('created_at') }, class_name: 'OrderComment'
has_many :stock_changes
belongs_to :invoice, optional: true
belongs_to :supplier, optional: true
- 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'
+ 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'
enum end_action: { no_end_action: 0, auto_close: 1, auto_close_and_send: 2, auto_close_and_send_min_quantity: 3 }
- enum transport_distribution: [:skip, :ordergroup, :price, :articles]
+ enum transport_distribution: { skip: 0, ordergroup: 1, price: 2, articles: 3 }
# Validations
- validates_presence_of :starts
+ validates :starts, presence: true
validate :starts_before_ends, :include_articles
validate :keep_ordered_articles
+ before_validation :distribute_transport
# Callbacks
after_save :save_order_articles, :update_price_of_group_orders!
- before_validation :distribute_transport
# Finders
scope :started, -> { where('starts <= ?', Time.now) }
@@ -49,12 +49,12 @@ class Order < ApplicationRecord
include DateTimeAttributeValidate
date_time_attribute :starts, :boxfill, :ends
- def self.ransackable_attributes(auth_object = nil)
- %w(id state supplier_id starts boxfill ends pickup)
+ def self.ransackable_attributes(_auth_object = nil)
+ %w[id state supplier_id starts boxfill ends pickup]
end
- def self.ransackable_associations(auth_object = nil)
- %w(supplier articles order_articles)
+ def self.ransackable_associations(_auth_object = nil)
+ %w[supplier articles order_articles]
end
def stockit?
@@ -70,9 +70,9 @@ class Order < ApplicationRecord
# make sure to include those articles which are no longer available
# but which have already been ordered in this stock order
StockArticle.available.includes(:article_category)
- .order('article_categories.name', 'articles.name').reject { |a|
+ .order('article_categories.name', 'articles.name').reject do |a|
a.quantity_available <= 0 && !a.ordered_in_order?(self)
- }.group_by { |a| a.article_category.name }
+ end.group_by { |a| a.article_category.name }
else
supplier.articles.available.group_by { |a| a.article_category.name }
end
@@ -87,9 +87,7 @@ class Order < ApplicationRecord
end
# Save ids, and create/delete order_articles after successfully saved the order
- def article_ids=(ids)
- @article_ids = ids
- end
+ attr_writer :article_ids
def article_ids
@article_ids ||= order_articles.map { |a| a.article_id.to_s }
@@ -101,19 +99,19 @@ class Order < ApplicationRecord
end
def open?
- state == "open"
+ state == 'open'
end
def finished?
- state == "finished" || state == "received"
+ state == 'finished' || state == 'received'
end
def received?
- state == "received"
+ state == 'received'
end
def closed?
- state == "closed"
+ state == 'closed'
end
def boxfill?
@@ -134,11 +132,18 @@ class Order < ApplicationRecord
self.starts ||= Time.now
if FoodsoftConfig[:order_schedule]
# try to be smart when picking a reference day
- last = (DateTime.parse(FoodsoftConfig[:order_schedule][:initial]) rescue nil)
+ last = begin
+ DateTime.parse(FoodsoftConfig[:order_schedule][:initial])
+ rescue StandardError
+ nil
+ end
last ||= Order.finished.reorder(:starts).first.try(:starts)
last ||= self.starts
# adjust boxfill and end date
- self.boxfill ||= FoodsoftDateUtil.next_occurrence last, self.starts, FoodsoftConfig[:order_schedule][:boxfill] if is_boxfill_useful?
+ if is_boxfill_useful?
+ self.boxfill ||= FoodsoftDateUtil.next_occurrence last, self.starts,
+ FoodsoftConfig[:order_schedule][:boxfill]
+ end
self.ends ||= FoodsoftDateUtil.next_occurrence last, self.starts, FoodsoftConfig[:order_schedule][:ends]
end
self
@@ -149,7 +154,7 @@ class Order < ApplicationRecord
def self.ordergroup_group_orders_map(ordergroup)
orders = includes(:supplier)
group_orders = GroupOrder.where(ordergroup_id: ordergroup.id, order_id: orders.map(&:id))
- group_orders_hash = Hash[group_orders.collect { |go| [go.order_id, go] }]
+ group_orders_hash = group_orders.index_by { |go| go.order_id }
orders.map do |order|
{
order: order,
@@ -160,11 +165,11 @@ class Order < ApplicationRecord
# search GroupOrder of given Ordergroup
def group_order(ordergroup)
- group_orders.where(:ordergroup_id => ordergroup.id).first
+ group_orders.where(ordergroup_id: ordergroup.id).first
end
def stock_group_order
- group_orders.where(:ordergroup_id => nil).first
+ group_orders.where(ordergroup_id: nil).first
end
# Returns OrderArticles in a nested Array, grouped by category and ordered by article name.
@@ -172,7 +177,7 @@ class Order < ApplicationRecord
# e.g: [["drugs",[teethpaste, toiletpaper]], ["fruits" => [apple, banana, lemon]]]
def articles_grouped_by_category
@articles_grouped_by_category ||= order_articles
- .includes([:article_price, :group_order_articles, :article => :article_category])
+ .includes([:article_price, :group_order_articles, { article: :article_category }])
.order('articles.name')
.group_by { |a| a.article.article_category.name }
.sort { |a, b| a[0] <=> b[0] }
@@ -189,10 +194,10 @@ class Order < ApplicationRecord
# FIXME: Consider order.foodcoop_result
def profit(options = {})
markup = options[:without_markup] || false
- if invoice
- groups_sum = markup ? sum(:groups_without_markup) : sum(:groups)
- groups_sum - invoice.net_amount
- end
+ return unless invoice
+
+ groups_sum = markup ? sum(:groups_without_markup) : sum(:groups)
+ groups_sum - invoice.net_amount
end
# Returns the all round price of a finished order
@@ -202,7 +207,7 @@ class Order < ApplicationRecord
# :fc, guess what...
def sum(type = :gross)
total = 0
- if type == :net || type == :gross || type == :fc
+ if %i[net gross fc].include?(type)
for oa in order_articles.ordered.includes(:article, :article_price)
quantity = oa.units * oa.price.unit_quantity
case type
@@ -214,8 +219,8 @@ class Order < ApplicationRecord
total += quantity * oa.price.fc_price
end
end
- elsif type == :groups || type == :groups_without_markup
- for go in group_orders.includes(group_order_articles: { order_article: [:article, :article_price] })
+ elsif %i[groups groups_without_markup].include?(type)
+ for go in group_orders.includes(group_order_articles: { order_article: %i[article article_price] })
for goa in go.group_order_articles
case type
when :groups
@@ -232,36 +237,36 @@ class Order < ApplicationRecord
# Finishes this order. This will set the order state to "finish" and the end property to the current time.
# Ignored if the order is already finished.
def finish!(user)
- unless finished?
- Order.transaction do
- # set new order state (needed by notify_order_finished)
- update!(state: 'finished', ends: Time.now, updated_by: user)
+ return if finished?
- # Update order_articles. Save the current article_price to keep price consistency
- # Also save results for each group_order_result
- # Clean up
- order_articles.includes(:article).each do |oa|
- oa.update_attribute(:article_price, oa.article.article_prices.first)
- oa.group_order_articles.each do |goa|
- 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 ?)
- # A: Yes, we do - for redistributing articles when the number of articles
- # delivered changes, and for statistics on popular articles. Records
- # with both tolerance and quantity zero can be deleted.
- # goa.group_order_article_quantities.clear
- end
+ Order.transaction do
+ # set new order state (needed by notify_order_finished)
+ update!(state: 'finished', ends: Time.now, updated_by: user)
+
+ # Update order_articles. Save the current article_price to keep price consistency
+ # Also save results for each group_order_result
+ # Clean up
+ order_articles.includes(:article).find_each do |oa|
+ oa.update_attribute(:article_price, oa.article.article_prices.first)
+ oa.group_order_articles.each do |goa|
+ 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 ?)
+ # A: Yes, we do - for redistributing articles when the number of articles
+ # delivered changes, and for statistics on popular articles. Records
+ # with both tolerance and quantity zero can be deleted.
+ # goa.group_order_article_quantities.clear
end
-
- # Update GroupOrder prices
- group_orders.each(&:update_price!)
-
- # Stats
- ordergroups.each(&:update_stats!)
-
- # Notifications
- NotifyFinishedOrderJob.perform_later(self)
end
+
+ # Update GroupOrder prices
+ group_orders.each(&:update_price!)
+
+ # Stats
+ ordergroups.each(&:update_stats!)
+
+ # Notifications
+ NotifyFinishedOrderJob.perform_later(self)
end
end
@@ -277,11 +282,11 @@ class Order < ApplicationRecord
if stockit? # Decreases the quantity of stock_articles
for oa in order_articles.includes(:article)
oa.update_results! # Update units_to_order of order_article
- stock_changes.create! :stock_article => oa.article, :quantity => oa.units_to_order * -1
+ stock_changes.create! stock_article: oa.article, quantity: oa.units_to_order * -1
end
end
- self.update!(state: 'closed', updated_by: user, foodcoop_result: profit)
+ update!(state: 'closed', updated_by: user, foodcoop_result: profit)
end
end
@@ -289,7 +294,10 @@ class Order < ApplicationRecord
def close_direct!(user)
raise I18n.t('orders.model.error_closed') if closed?
- comments.create(user: user, text: I18n.t('orders.model.close_direct_message')) unless FoodsoftConfig[:charge_members_manually]
+ unless FoodsoftConfig[:charge_members_manually]
+ comments.create(user: user,
+ text: I18n.t('orders.model.close_direct_message'))
+ end
update!(state: 'closed', updated_by: user)
end
@@ -313,13 +321,12 @@ class Order < ApplicationRecord
end
def self.finish_ended!
- orders = Order.where.not(end_action: Order.end_actions[:no_end_action]).where(state: 'open').where('ends <= ?', DateTime.now)
+ orders = Order.where.not(end_action: Order.end_actions[:no_end_action]).where(state: 'open').where('ends <= ?',
+ DateTime.now)
orders.each do |order|
- begin
- order.do_end_action!
- rescue => error
- ExceptionNotifier.notify_exception(error, data: { foodcoop: FoodsoftConfig.scope, order_id: order.id })
- end
+ order.do_end_action!
+ rescue StandardError => e
+ ExceptionNotifier.notify_exception(e, data: { foodcoop: FoodsoftConfig.scope, order_id: order.id })
end
end
@@ -329,7 +336,10 @@ class Order < ApplicationRecord
delta = Rails.env.test? ? 1 : 0 # since Rails 4.2 tests appear to have time differences, with this validation failing
errors.add(:ends, I18n.t('orders.model.error_starts_before_ends')) if ends && starts && ends <= (starts - delta)
errors.add(:ends, I18n.t('orders.model.error_boxfill_before_ends')) if ends && boxfill && ends <= (boxfill - delta)
- errors.add(:boxfill, I18n.t('orders.model.error_starts_before_boxfill')) if boxfill && starts && boxfill <= (starts - delta)
+ return unless boxfill && starts && boxfill <= (starts - delta)
+
+ errors.add(:boxfill,
+ I18n.t('orders.model.error_starts_before_boxfill'))
end
def include_articles
@@ -340,17 +350,17 @@ class Order < ApplicationRecord
chosen_order_articles = order_articles.where(article_id: article_ids)
to_be_removed = order_articles - chosen_order_articles
to_be_removed_but_ordered = to_be_removed.select { |a| a.quantity > 0 || a.tolerance > 0 }
- unless to_be_removed_but_ordered.empty? || ignore_warnings
- errors.add(:articles, I18n.t(stockit? ? 'orders.model.warning_ordered_stock' : 'orders.model.warning_ordered'))
- @erroneous_article_ids = to_be_removed_but_ordered.map { |a| a.article_id }
- end
+ return if to_be_removed_but_ordered.empty? || ignore_warnings
+
+ errors.add(:articles, I18n.t(stockit? ? 'orders.model.warning_ordered_stock' : 'orders.model.warning_ordered'))
+ @erroneous_article_ids = to_be_removed_but_ordered.map { |a| a.article_id }
end
def save_order_articles
# fetch selected articles
articles_list = Article.find(article_ids)
# create new order_articles
- (articles_list - articles).each { |article| order_articles.create(:article => article) }
+ (articles_list - articles).each { |article| order_articles.create(article: article) }
# delete old order_articles
articles.reject { |article| articles_list.include?(article) }.each do |article|
order_articles.detect { |order_article| order_article.article_id == article.id }.destroy
@@ -363,17 +373,17 @@ class Order < ApplicationRecord
return unless group_orders.any?
case transport_distribution.try(&:to_i)
- when Order.transport_distributions[:ordergroup] then
+ when Order.transport_distributions[:ordergroup]
amount = transport / group_orders.size
group_orders.each do |go|
go.transport = amount.ceil(2)
end
- when Order.transport_distributions[:price] then
+ when Order.transport_distributions[:price]
amount = transport / group_orders.sum(:price)
group_orders.each do |go|
go.transport = (amount * go.price).ceil(2)
end
- when Order.transport_distributions[:articles] then
+ when Order.transport_distributions[:articles]
amount = transport / group_orders.includes(:group_order_articles).sum(:result)
group_orders.each do |go|
go.transport = (amount * go.group_order_articles.sum(:result)).ceil(2)
@@ -389,7 +399,7 @@ class Order < ApplicationRecord
def charge_group_orders!(user, transaction_type = nil)
note = transaction_note
- group_orders.includes(:ordergroup).each do |group_order|
+ group_orders.includes(:ordergroup).find_each do |group_order|
if group_order.ordergroup
price = group_order.total * -1 # decrease! account balance
group_order.ordergroup.add_financial_transaction!(price, note, user, transaction_type, nil, group_order)
diff --git a/app/models/order_article.rb b/app/models/order_article.rb
index cda24ae2..14193d15 100644
--- a/app/models/order_article.rb
+++ b/app/models/order_article.rb
@@ -7,25 +7,27 @@ class OrderArticle < ApplicationRecord
belongs_to :order
belongs_to :article
belongs_to :article_price, optional: true
- has_many :group_order_articles, :dependent => :destroy
+ has_many :group_order_articles, dependent: :destroy
- validates_presence_of :order_id, :article_id
+ validates :order_id, :article_id, presence: true
validate :article_and_price_exist
- validates_uniqueness_of :article_id, scope: :order_id
+ validates :article_id, uniqueness: { scope: :order_id }
- _ordered_sql = "order_articles.units_to_order > 0 OR order_articles.units_billed > 0 OR order_articles.units_received > 0"
+ _ordered_sql = 'order_articles.units_to_order > 0 OR order_articles.units_billed > 0 OR order_articles.units_received > 0'
scope :ordered, -> { where(_ordered_sql) }
- scope :ordered_or_member, -> { includes(:group_order_articles).where("#{_ordered_sql} OR order_articles.quantity > 0 OR group_order_articles.result > 0") }
+ scope :ordered_or_member, lambda {
+ includes(:group_order_articles).where("#{_ordered_sql} OR order_articles.quantity > 0 OR group_order_articles.result > 0")
+ }
before_create :init_from_balancing
after_destroy :update_ordergroup_prices
- def self.ransackable_attributes(auth_object = nil)
- %w(id order_id article_id quantity tolerance units_to_order)
+ def self.ransackable_attributes(_auth_object = nil)
+ %w[id order_id article_id quantity tolerance units_to_order]
end
- def self.ransackable_associations(auth_object = nil)
- %w(order article)
+ def self.ransackable_associations(_auth_object = nil)
+ %w[order article]
end
# This method returns either the ArticlePrice or the Article
@@ -46,7 +48,7 @@ class OrderArticle < ApplicationRecord
# In balancing this can differ from ordered (by supplier) quantity for this article.
def group_orders_sum
quantity = group_order_articles.collect(&:result).sum
- { :quantity => quantity, :price => quantity * price.fc_price }
+ { quantity: quantity, price: quantity * price.fc_price }
end
# Update quantity/tolerance/units_to_order from group_order_articles
@@ -97,15 +99,13 @@ class OrderArticle < ApplicationRecord
units * price.unit_quantity * price.gross_price
end
- def ordered_quantities_different_from_group_orders?(ordered_mark = "!", billed_mark = "?", received_mark = "?")
- if not units_received.nil?
- ((units_received * price.unit_quantity) == group_orders_sum[:quantity]) ? false : received_mark
- elsif not units_billed.nil?
- ((units_billed * price.unit_quantity) == group_orders_sum[:quantity]) ? false : billed_mark
- elsif not units_to_order.nil?
- ((units_to_order * price.unit_quantity) == group_orders_sum[:quantity]) ? false : ordered_mark
- else
- nil # can happen in integration tests
+ def ordered_quantities_different_from_group_orders?(ordered_mark = '!', billed_mark = '?', received_mark = '?')
+ if !units_received.nil?
+ (units_received * price.unit_quantity) == group_orders_sum[:quantity] ? false : received_mark
+ elsif !units_billed.nil?
+ (units_billed * price.unit_quantity) == group_orders_sum[:quantity] ? false : billed_mark
+ elsif !units_to_order.nil?
+ (units_to_order * price.unit_quantity) == group_orders_sum[:quantity] ? false : ordered_mark
end
end
@@ -124,7 +124,7 @@ class OrderArticle < ApplicationRecord
if surplus.index(:tolerance).nil?
qty_for_members = [qty_left, self.quantity].min
else
- qty_for_members = [qty_left, self.quantity + self.tolerance].min
+ qty_for_members = [qty_left, self.quantity + tolerance].min
counts[surplus.index(:tolerance)] = [0, qty_for_members - self.quantity].max
end
@@ -139,9 +139,7 @@ class OrderArticle < ApplicationRecord
# 2) if not found, create new stock article
# avoiding duplicate stock article names
end
- if qty_left > 0 && surplus.index(nil)
- counts[surplus.index(nil)] = qty_left
- end
+ counts[surplus.index(nil)] = qty_left if qty_left > 0 && surplus.index(nil)
# Update GroupOrder prices & Ordergroup stats
# TODO only affected group_orders, and once after redistributing all articles
@@ -150,7 +148,7 @@ class OrderArticle < ApplicationRecord
order.ordergroups.each(&:update_stats!)
end
- # TODO notifications
+ # TODO: notifications
counts
end
@@ -159,7 +157,7 @@ class OrderArticle < ApplicationRecord
def update_article_and_price!(order_article_attributes, article_attributes, price_attributes = nil)
OrderArticle.transaction do
# Updates self
- self.update!(order_article_attributes)
+ update!(order_article_attributes)
# Updates article
article.update!(article_attributes)
@@ -186,7 +184,7 @@ class OrderArticle < ApplicationRecord
end
def update_global_price=(value)
- @update_global_price = (value == true || value == '1') ? true : false
+ @update_global_price = [true, '1'].include?(value) ? true : false
end
# @return [Number] Units missing for the last +unit_quantity+ of the article.
@@ -210,16 +208,19 @@ class OrderArticle < ApplicationRecord
private
def article_and_price_exist
- errors.add(:article, I18n.t('model.order_article.error_price')) if !(article = Article.find(article_id)) || article.fc_price.nil?
- rescue
+ if !(article = Article.find(article_id)) || article.fc_price.nil?
+ errors.add(:article,
+ I18n.t('model.order_article.error_price'))
+ end
+ rescue StandardError
errors.add(:article, I18n.t('model.order_article.error_price'))
end
# Associate with current article price if created in a finished order
def init_from_balancing
- if order.present? && order.finished?
- self.article_price = article.article_prices.first
- end
+ return unless order.present? && order.finished?
+
+ self.article_price = article.article_prices.first
end
def update_ordergroup_prices
@@ -241,7 +242,8 @@ class OrderArticle < ApplicationRecord
unless (delta_q == 0 && delta_t >= 0) ||
(delta_mis < 0 && delta_box >= 0 && delta_t >= 0) ||
(delta_q > 0 && delta_q == -delta_t)
- raise ActiveRecord::RecordNotSaved.new("Change not acceptable in boxfill phase for '#{article.name}', sorry.", self)
+ raise ActiveRecord::RecordNotSaved.new("Change not acceptable in boxfill phase for '#{article.name}', sorry.",
+ self)
end
end
diff --git a/app/models/order_comment.rb b/app/models/order_comment.rb
index 5f35d98c..b11388b0 100644
--- a/app/models/order_comment.rb
+++ b/app/models/order_comment.rb
@@ -2,6 +2,6 @@ class OrderComment < ApplicationRecord
belongs_to :order
belongs_to :user
- validates_presence_of :order_id, :user_id, :text
- validates_length_of :text, :minimum => 3
+ validates :order_id, :user_id, :text, presence: true
+ validates :text, length: { minimum: 3 }
end
diff --git a/app/models/ordergroup.rb b/app/models/ordergroup.rb
index c29ec762..6770fc55 100644
--- a/app/models/ordergroup.rb
+++ b/app/models/ordergroup.rb
@@ -15,7 +15,7 @@ class Ordergroup < Group
has_many :orders, through: :group_orders
has_many :group_order_articles, through: :group_orders
- validates_numericality_of :account_balance, :message => I18n.t('ordergroups.model.invalid_balance')
+ validates :account_balance, numericality: { message: I18n.t('ordergroups.model.invalid_balance') }
validate :uniqueness_of_name, :uniqueness_of_members
after_create :update_stats!
@@ -32,7 +32,7 @@ class Ordergroup < Group
def self.include_transaction_class_sum
columns = ['groups.*']
- FinancialTransactionClass.all.each do |c|
+ FinancialTransactionClass.all.find_each do |c|
columns << "sum(CASE financial_transaction_types.financial_transaction_class_id WHEN #{c.id} THEN financial_transactions.amount ELSE 0 END) AS sum_of_class_#{c.id}"
end
@@ -51,9 +51,9 @@ class Ordergroup < Group
def last_user_activity
last_active_user = users.order('users.last_activity DESC').first
- if last_active_user
- last_active_user.last_activity
- end
+ return unless last_active_user
+
+ last_active_user.last_activity
end
# the most recent order this ordergroup was participating in
@@ -86,12 +86,14 @@ class Ordergroup < Group
# Throws an exception if it fails.
def add_financial_transaction!(amount, note, user, transaction_type, link = nil, group_order = nil)
transaction do
- t = FinancialTransaction.new(ordergroup: self, amount: amount, note: note, user: user, financial_transaction_type: transaction_type, financial_link: link, group_order: group_order)
+ t = FinancialTransaction.new(ordergroup: self, amount: amount, note: note, user: user,
+ financial_transaction_type: transaction_type, financial_link: link, group_order: group_order)
t.save!
update_balance!
# Notify only when order group had a positive balance before the last transaction:
- if t.amount < 0 && self.account_balance < 0 && self.account_balance - t.amount >= 0
- NotifyNegativeBalanceJob.perform_later(self, t)
+ if t.amount < 0 && account_balance < 0 && account_balance - t.amount >= 0
+ NotifyNegativeBalanceJob.perform_later(self,
+ t)
end
t
end
@@ -101,10 +103,11 @@ class Ordergroup < Group
# Get hours for every job of each user in period
jobs = users.to_a.sum { |u| u.tasks.done.where('updated_on > ?', APPLE_MONTH_AGO.month.ago).sum(:duration) }
# Get group_order.price for every finished order in this period
- orders_sum = group_orders.includes(:order).merge(Order.finished).where('orders.ends >= ?', APPLE_MONTH_AGO.month.ago).references(:orders).sum(:price)
+ orders_sum = group_orders.includes(:order).merge(Order.finished).where('orders.ends >= ?',
+ APPLE_MONTH_AGO.month.ago).references(:orders).sum(:price)
@readonly = false # Dirty hack, avoid getting RecordReadOnly exception when called in task after_save callback. A rails bug?
- update_attribute(:stats, { :jobs_size => jobs, :orders_sum => orders_sum })
+ update_attribute(:stats, { jobs_size: jobs, orders_sum: orders_sum })
end
def update_balance!
@@ -116,13 +119,17 @@ class Ordergroup < Group
end
def avg_jobs_per_euro
- stats[:jobs_size].to_f / stats[:orders_sum].to_f rescue 0
+ stats[:jobs_size].to_f / stats[:orders_sum].to_f
+ rescue StandardError
+ 0
end
# This is the ordergroup job per euro performance
# in comparison to the hole foodcoop average
def apples
- ((avg_jobs_per_euro / Ordergroup.avg_jobs_per_euro) * 100).to_i rescue 0
+ ((avg_jobs_per_euro / Ordergroup.avg_jobs_per_euro) * 100).to_i
+ rescue StandardError
+ 0
end
# If the the option stop_ordering_under is set, the ordergroup is only allowed to participate in an order,
@@ -141,7 +148,11 @@ class Ordergroup < Group
# Global average
def self.avg_jobs_per_euro
stats = Ordergroup.pluck(:stats)
- stats.sum { |s| s[:jobs_size].to_f } / stats.sum { |s| s[:orders_sum].to_f } rescue 0
+ begin
+ stats.sum { |s| s[:jobs_size].to_f } / stats.sum { |s| s[:orders_sum].to_f }
+ rescue StandardError
+ 0
+ end
end
def account_updated
@@ -149,22 +160,22 @@ class Ordergroup < Group
end
def self.sort_by_param(param)
- param ||= "name"
+ param ||= 'name'
sort_param_map = {
- "name" => "name",
- "name_reverse" => "name DESC",
- "members_count" => "count(users.id)",
- "members_count_reverse" => "count(users.id) DESC",
- "last_user_activity" => "max(users.last_activity)",
- "last_user_activity_reverse" => "max(users.last_activity) DESC",
- "last_order" => "max(orders.starts)",
- "last_order_reverse" => "max(orders.starts) DESC"
+ 'name' => 'name',
+ 'name_reverse' => 'name DESC',
+ 'members_count' => 'count(users.id)',
+ 'members_count_reverse' => 'count(users.id) DESC',
+ 'last_user_activity' => 'max(users.last_activity)',
+ 'last_user_activity_reverse' => 'max(users.last_activity) DESC',
+ 'last_order' => 'max(orders.starts)',
+ 'last_order_reverse' => 'max(orders.starts) DESC'
}
result = self
- result = result.left_joins(:users).group("groups.id") if param.starts_with?("members_count", "last_user_activity")
- result = result.left_joins(:orders).group("groups.id") if param.starts_with?("last_order")
+ result = result.left_joins(:users).group('groups.id') if param.starts_with?('members_count', 'last_user_activity')
+ result = result.left_joins(:orders).group('groups.id') if param.starts_with?('last_order')
# Never pass user input data to Arel.sql() because of SQL Injection vulnerabilities.
# This case here is okay, as param is mapped to the actual order string.
@@ -176,17 +187,21 @@ 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, I18n.t('ordergroups.model.error_single_group', :user => user.display) if user.groups.where(:type => 'Ordergroup').size > 1
+ next unless user.groups.where(type: 'Ordergroup').size > 1
+
+ errors.add :user_tokens,
+ I18n.t('ordergroups.model.error_single_group',
+ user: user.display)
end
end
# Make sure, the name is uniq, add usefull message if uniq group is already deleted
def uniqueness_of_name
group = Ordergroup.where(name: name)
- group = group.where.not(id: self.id) unless new_record?
- if group.exists?
- message = group.first.deleted? ? :taken_with_deleted : :taken
- errors.add :name, message
- end
+ group = group.where.not(id: id) unless new_record?
+ return unless group.exists?
+
+ message = group.first.deleted? ? :taken_with_deleted : :taken
+ errors.add :name, message
end
end
diff --git a/app/models/periodic_task_group.rb b/app/models/periodic_task_group.rb
index c0a2b10f..f9e9f249 100644
--- a/app/models/periodic_task_group.rb
+++ b/app/models/periodic_task_group.rb
@@ -5,7 +5,7 @@ class PeriodicTaskGroup < ApplicationRecord
return false if tasks.empty?
return false if tasks.first.due_date.nil?
- return true
+ true
end
def create_next_task
@@ -18,15 +18,13 @@ class PeriodicTaskGroup < ApplicationRecord
next_task.save
self.next_task_date += period_days
- self.save
+ save
end
def create_tasks_until(create_until)
- if has_next_task?
- while next_task_date.nil? || next_task_date < create_until
- create_next_task
- end
- end
+ return unless has_next_task?
+
+ create_next_task while next_task_date.nil? || next_task_date < create_until
end
def create_tasks_for_upfront_days
@@ -36,7 +34,7 @@ class PeriodicTaskGroup < ApplicationRecord
end
def exclude_tasks_before(task)
- tasks.where("due_date < '#{task.due_date}'").each do |t|
+ tasks.where("due_date < '#{task.due_date}'").find_each do |t|
t.update_attribute(:periodic_task_group, nil)
end
end
@@ -53,7 +51,7 @@ class PeriodicTaskGroup < ApplicationRecord
due_date: task.due_date + due_date_delta)
end
group_tasks.each do |task|
- task.update_columns(periodic_task_group_id: self.id)
+ task.update_columns(periodic_task_group_id: id)
end
end
diff --git a/app/models/shared_article.rb b/app/models/shared_article.rb
index 238b48f0..c390a021 100644
--- a/app/models/shared_article.rb
+++ b/app/models/shared_article.rb
@@ -4,23 +4,23 @@ class SharedArticle < ApplicationRecord
# set correct table_name in external DB
self.table_name = 'articles'
- belongs_to :shared_supplier, :foreign_key => :supplier_id
+ belongs_to :shared_supplier, foreign_key: :supplier_id
def build_new_article(supplier)
supplier.articles.build(
- :name => name,
- :unit => unit,
- :note => note,
- :manufacturer => manufacturer,
- :origin => origin,
- :price => price,
- :tax => tax,
- :deposit => deposit,
- :unit_quantity => unit_quantity,
- :order_number => number,
- :article_category => ArticleCategory.find_match(category),
+ name: name,
+ unit: unit,
+ note: note,
+ manufacturer: manufacturer,
+ origin: origin,
+ price: price,
+ tax: tax,
+ deposit: deposit,
+ unit_quantity: unit_quantity,
+ order_number: number,
+ article_category: ArticleCategory.find_match(category),
# convert to db-compatible-string
- :shared_updated_on => updated_on.to_formatted_s(:db)
+ shared_updated_on: updated_on.to_fs(:db)
)
end
end
diff --git a/app/models/shared_supplier.rb b/app/models/shared_supplier.rb
index 29c9c1ab..e2b23805 100644
--- a/app/models/shared_supplier.rb
+++ b/app/models/shared_supplier.rb
@@ -5,10 +5,10 @@ class SharedSupplier < ApplicationRecord
self.table_name = 'suppliers'
has_many :suppliers, -> { undeleted }
- has_many :shared_articles, :foreign_key => :supplier_id
+ has_many :shared_articles, foreign_key: :supplier_id
def find_article_by_number(order_number)
- # note that `shared_articles` uses number instead order_number
+ # NOTE: that `shared_articles` uses number instead order_number
cached_articles.detect { |a| a.number == order_number }
end
@@ -19,15 +19,18 @@ class SharedSupplier < ApplicationRecord
# 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)
+ whitelist = %w[name address phone fax email url delivery_days note]
attributes.select { |k, _v| whitelist.include?(k) }
end
# return list of synchronisation methods available for this supplier
def shared_sync_methods
methods = []
- methods += %w(all_available all_unavailable) if shared_articles.count < FoodsoftConfig[:shared_supplier_article_sync_limit]
- methods += %w(import)
+ if shared_articles.count < FoodsoftConfig[:shared_supplier_article_sync_limit]
+ methods += %w[all_available
+ all_unavailable]
+ end
+ methods += %w[import]
methods
end
end
diff --git a/app/models/stock_article.rb b/app/models/stock_article.rb
index 42a06d49..14b8d5ef 100644
--- a/app/models/stock_article.rb
+++ b/app/models/stock_article.rb
@@ -10,11 +10,11 @@ class StockArticle < Article
ransack_alias :quantity_available, :quantity # in-line with {StockArticleSerializer}
def self.ransackable_attributes(auth_object = nil)
- super(auth_object) - %w(supplier_id) + %w(quantity)
+ super(auth_object) - %w[supplier_id] + %w[quantity]
end
def self.ransackable_associations(auth_object = nil)
- super(auth_object) - %w(supplier)
+ super(auth_object) - %w[supplier]
end
# Update the quantity of items in stock
@@ -48,7 +48,7 @@ class StockArticle < Article
protected
def check_quantity
- raise I18n.t('stockit.check.not_empty', :name => name) 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.
diff --git a/app/models/stock_change.rb b/app/models/stock_change.rb
index 4cbd8939..03d92c74 100644
--- a/app/models/stock_change.rb
+++ b/app/models/stock_change.rb
@@ -4,11 +4,11 @@ class StockChange < ApplicationRecord
belongs_to :stock_taking, optional: true, foreign_key: 'stock_event_id'
belongs_to :stock_article
- validates_presence_of :stock_article_id, :quantity
- validates_numericality_of :quantity
+ validates :stock_article_id, :quantity, presence: true
+ validates :quantity, numericality: true
- after_save :update_article_quantity
after_destroy :update_article_quantity
+ after_save :update_article_quantity
protected
diff --git a/app/models/stock_event.rb b/app/models/stock_event.rb
index 4fd82864..7134f7b0 100644
--- a/app/models/stock_event.rb
+++ b/app/models/stock_event.rb
@@ -2,5 +2,5 @@ class StockEvent < ApplicationRecord
has_many :stock_changes, dependent: :destroy
has_many :stock_articles, through: :stock_changes
- validates_presence_of :date
+ validates :date, presence: true
end
diff --git a/app/models/supplier.rb b/app/models/supplier.rb
index 06ef36bb..56999be1 100644
--- a/app/models/supplier.rb
+++ b/app/models/supplier.rb
@@ -1,9 +1,10 @@
-require 'foodsoft_article_import'
class Supplier < ApplicationRecord
include MarkAsDeletedWithName
include CustomFields
- has_many :articles, -> { where(:type => nil).includes(:article_category).order('article_categories.name', 'articles.name') }
+ has_many :articles, lambda {
+ where(type: nil).includes(:article_category).order('article_categories.name', 'articles.name')
+ }
has_many :stock_articles, -> { includes(:article_category).order('article_categories.name', 'articles.name') }
has_many :orders
has_many :deliveries
@@ -11,24 +12,24 @@ class Supplier < ApplicationRecord
belongs_to :supplier_category
belongs_to :shared_supplier, optional: true # for the sharedLists-App
- validates :name, :presence => true, :length => { :in => 4..30 }
- validates :phone, :presence => true, :length => { :in => 8..25 }
- validates :address, :presence => true, :length => { :in => 8..50 }
- validates_format_of :iban, :with => /\A[A-Z]{2}[0-9]{2}[0-9A-Z]{,30}\z/, :allow_blank => true
- validates_uniqueness_of :iban, :case_sensitive => false, :allow_blank => true
- validates_length_of :order_howto, :note, maximum: 250
+ validates :name, presence: true, length: { in: 4..30 }
+ validates :phone, presence: true, length: { in: 8..25 }
+ validates :address, presence: true, length: { in: 8..50 }
+ validates :iban, format: { with: /\A[A-Z]{2}[0-9]{2}[0-9A-Z]{,30}\z/, allow_blank: true }
+ validates :iban, uniqueness: { case_sensitive: false, allow_blank: true }
+ validates :order_howto, :note, length: { maximum: 250 }
validate :valid_shared_sync_method
validate :uniqueness_of_name
scope :undeleted, -> { where(deleted_at: nil) }
scope :having_articles, -> { where(id: Article.undeleted.select(:supplier_id).distinct) }
- def self.ransackable_attributes(auth_object = nil)
- %w(id name)
+ def self.ransackable_attributes(_auth_object = nil)
+ %w[id name]
end
- def self.ransackable_associations(auth_object = nil)
- %w(articles stock_articles orders)
+ def self.ransackable_associations(_auth_object = nil)
+ %w[articles stock_articles orders]
end
# sync all articles with the external database
@@ -36,7 +37,9 @@ class Supplier < ApplicationRecord
# also returns an array with outlisted_articles, which should be deleted
# also returns an array with new articles, which should be added (depending on shared_sync_method)
def sync_all
- updated_article_pairs, outlisted_articles, new_articles = [], [], []
+ updated_article_pairs = []
+ outlisted_articles = []
+ new_articles = []
existing_articles = Set.new
for article in articles.undeleted
# try to find the associated shared_article
@@ -45,53 +48,44 @@ class Supplier < ApplicationRecord
if shared_article # article will be updated
existing_articles.add(shared_article.id)
unequal_attributes = article.shared_article_changed?(self)
- unless unequal_attributes.blank? # skip if shared_article has not been changed
+ if unequal_attributes.present? # skip if shared_article has not been changed
article.attributes = unequal_attributes
updated_article_pairs << [article, unequal_attributes]
end
# Articles with no order number can be used to put non-shared articles
# in a shared supplier, with sync keeping them.
- elsif not article.order_number.blank?
+ elsif article.order_number.present?
# article isn't in external database anymore
outlisted_articles << article
end
end
# Find any new articles, unless the import is manual
- if ['all_available', 'all_unavailable'].include?(shared_sync_method)
+ if %w[all_available all_unavailable].include?(shared_sync_method)
# build new articles
shared_supplier
.shared_articles
.where.not(id: existing_articles.to_a)
.find_each { |new_shared_article| new_articles << new_shared_article.build_new_article(self) }
# make them unavailable when desired
- if shared_sync_method == 'all_unavailable'
- new_articles.each { |new_article| new_article.availability = false }
- end
+ new_articles.each { |new_article| new_article.availability = false } if shared_sync_method == 'all_unavailable'
end
- return [updated_article_pairs, outlisted_articles, new_articles]
+ [updated_article_pairs, outlisted_articles, new_articles]
end
# Synchronise articles with spreadsheet.
#
# @param file [File] Spreadsheet file to parse
- # @param options [Hash] Options passed to {FoodsoftArticleImport#parse} except when listed here.
+ # @param options [Hash] Options passed to {FoodsoftFile#parse} except when listed here.
# @option options [Boolean] :outlist_absent Set to +true+ to remove articles not in spreadsheet.
# @option options [Boolean] :convert_units Omit or set to +true+ to keep current units, recomputing unit quantity and price.
- def sync_from_file(file, type, options = {})
+ def sync_from_file(file, options = {})
all_order_numbers = []
- updated_article_pairs, outlisted_articles, new_articles = [], [], []
- custom_codes_path = File.join(Rails.root, "config", "custom_codes.yml")
- opts = options.except(:convert_units, :outlist_absent, :update_category)
- custom_codes_file_path = custom_codes_path if File.exist?(custom_codes_path)
- FoodsoftArticleImport.parse(file, custom_file_path: custom_codes_file_path, type: type, **opts) do |new_attrs, status, line|
+ updated_article_pairs = []
+ outlisted_articles = []
+ new_articles = []
+ FoodsoftFile.parse file, options do |status, new_attrs, line|
article = articles.undeleted.where(order_number: new_attrs[:order_number]).first
-
- if new_attrs[:article_category].present? && options[:update_category]
- new_attrs[:article_category] = ArticleCategory.find_match(new_attrs[:article_category]) || ArticleCategory.create_or_find_by!(name: new_attrs[:article_category])
- else
- new_attrs[:article_category] = nil
- end
-
+ new_attrs[:article_category] = ArticleCategory.find_match(new_attrs[:article_category])
new_attrs[:tax] ||= FoodsoftConfig[:tax_default]
new_article = articles.build(new_attrs)
@@ -99,7 +93,7 @@ class Supplier < ApplicationRecord
if article.nil?
new_articles << new_article
else
- unequal_attributes = article.unequal_attributes(new_article, options.slice(:convert_units, :update_category))
+ unequal_attributes = article.unequal_attributes(new_article, options.slice(:convert_units))
unless unequal_attributes.empty?
article.attributes = unequal_attributes
updated_article_pairs << [article, unequal_attributes]
@@ -111,15 +105,13 @@ class Supplier < ApplicationRecord
# stop when there is a parsing error
elsif status.is_a? String
# @todo move I18n key to model
- raise I18n.t('articles.model.error_parse', :msg => status, :line => line.to_s)
+ raise I18n.t('articles.model.error_parse', msg: status, line: line.to_s)
end
all_order_numbers << article.order_number if article
end
- if options[:outlist_absent]
- outlisted_articles += articles.undeleted.where.not(order_number: all_order_numbers + [nil])
- end
- return [updated_article_pairs, outlisted_articles, new_articles]
+ outlisted_articles += articles.undeleted.where.not(order_number: all_order_numbers + [nil]) if options[:outlist_absent]
+ [updated_article_pairs, outlisted_articles, new_articles]
end
# default value
@@ -150,18 +142,18 @@ class Supplier < ApplicationRecord
# make sure the shared_sync_method is allowed for the shared supplier
def valid_shared_sync_method
- if shared_supplier && !shared_supplier.shared_sync_methods.include?(shared_sync_method)
- errors.add :shared_sync_method, :included
- end
+ return unless shared_supplier && !shared_supplier.shared_sync_methods.include?(shared_sync_method)
+
+ errors.add :shared_sync_method, :included
end
# Make sure, the name is uniq, add usefull message if uniq group is already deleted
def uniqueness_of_name
supplier = Supplier.where(name: name)
- supplier = supplier.where.not(id: self.id) unless new_record?
- if supplier.exists?
- message = supplier.first.deleted? ? :taken_with_deleted : :taken
- errors.add :name, message
- end
+ supplier = supplier.where.not(id: id) unless new_record?
+ return unless supplier.exists?
+
+ message = supplier.first.deleted? ? :taken_with_deleted : :taken
+ errors.add :name, message
end
end
diff --git a/app/models/task.rb b/app/models/task.rb
index cd748eb3..1343b8f4 100644
--- a/app/models/task.rb
+++ b/app/models/task.rb
@@ -1,9 +1,9 @@
class Task < ApplicationRecord
- has_many :assignments, :dependent => :destroy
- has_many :users, :through => :assignments
+ has_many :assignments, dependent: :destroy
+ has_many :users, through: :assignments
belongs_to :workgroup, optional: true
belongs_to :periodic_task_group, optional: true
- belongs_to :created_by, :class_name => 'User', :foreign_key => 'created_by_user_id', optional: true
+ belongs_to :created_by, class_name: 'User', foreign_key: 'created_by_user_id', optional: true
scope :non_group, -> { where(workgroup_id: nil, done: false) }
scope :done, -> { where(done: true) }
@@ -11,12 +11,12 @@ class Task < ApplicationRecord
attr_accessor :current_user_id
- validates :name, :presence => true, :length => { :minimum => 3 }
- validates :required_users, :presence => true
- validates_numericality_of :duration, :required_users, :only_integer => true, :greater_than => 0
- validates_length_of :description, maximum: 250
+ validates :name, presence: true, length: { minimum: 3 }
+ validates :required_users, presence: true
+ validates :duration, :required_users, numericality: { only_integer: true, greater_than: 0 }
+ validates :description, length: { maximum: 250 }
validates :done, exclusion: { in: [true] }, if: :periodic?, on: :create
- validates_presence_of :due_date, if: :periodic?
+ validates :due_date, presence: { if: :periodic? }
before_save :exclude_from_periodic_task_group, if: :changed?, unless: :new_record?
after_save :update_ordergroup_stats
@@ -35,7 +35,7 @@ class Task < ApplicationRecord
# find all tasks in the period (or another number of days)
def self.next_assigned_tasks_for(user, number = FoodsoftConfig[:tasks_period_days].to_i)
user.tasks.undone.where(assignments: { accepted: true })
- .where(["tasks.due_date >= ? AND tasks.due_date <= ?", Time.now, number.days.from_now])
+ .where(['tasks.due_date >= ? AND tasks.due_date <= ?', Time.now, number.days.from_now])
end
# count tasks with not enough responsible people
@@ -49,7 +49,7 @@ class Task < ApplicationRecord
def self.next_unassigned_tasks_for(user, max = 2)
periodic_task_group_count = {}
- self.unassigned_tasks_for(user).reject do |item|
+ unassigned_tasks_for(user).reject do |item|
next false unless item.periodic_task_group
count = periodic_task_group_count[item.periodic_task_group] || 0
@@ -59,19 +59,19 @@ class Task < ApplicationRecord
end
def periodic?
- not periodic_task_group.nil?
+ !periodic_task_group.nil?
end
def is_assigned?(user)
- self.assignments.detect { |ass| ass.user_id == user.id }
+ assignments.detect { |ass| ass.user_id == user.id }
end
def is_accepted?(user)
- self.assignments.detect { |ass| ass.user_id == user.id && ass.accepted }
+ assignments.detect { |ass| ass.user_id == user.id && ass.accepted }
end
def enough_users_assigned?
- assignments.to_a.count(&:accepted) >= required_users ? true : false
+ assignments.to_a.count(&:accepted) >= required_users
end
def still_required_users
@@ -82,39 +82,35 @@ class Task < ApplicationRecord
# and makes the users responsible for the task
# TODO: check for maximal number of users
def user_list=(ids)
- list = ids.split(",").map(&:to_i)
+ list = ids.split(',').map(&:to_i)
new_users = (list - users.collect(&:id)).uniq
old_users = users.reject { |user| list.include?(user.id) }
self.class.transaction do
# delete old assignments
- if old_users.any?
- assignments.where(user_id: old_users.map(&:id)).each(&:destroy)
- end
+ assignments.where(user_id: old_users.map(&:id)).find_each(&:destroy) if old_users.any?
# create new assignments
new_users.each do |id|
user = User.find(id)
if user.blank?
errors.add(:user_list)
+ elsif id == current_user_id.to_i
+ assignments.build user: user, accepted: true
+ # current_user will accept, when he puts himself to the list of users
else
- 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
- # normal assignement
- self.assignments.build :user => user
- end
+ # normal assignement
+ assignments.build user: user
end
end
end
end
def user_list
- @user_list ||= users.collect(&:id).join(", ")
+ @user_list ||= users.collect(&:id).join(', ')
end
def update_ordergroup_stats(user_ids = self.user_ids)
- Ordergroup.joins(:users).where(users: { id: user_ids }).each(&:update_stats!)
+ Ordergroup.joins(:users).where(users: { id: user_ids }).find_each(&:update_stats!)
end
def exclude_from_periodic_task_group
diff --git a/app/models/user.rb b/app/models/user.rb
index 05a67547..12d457b0 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -4,19 +4,19 @@ class User < ApplicationRecord
include CustomFields
# TODO: acts_as_paraniod ??
- has_many :memberships, :dependent => :destroy
- has_many :groups, :through => :memberships
+ has_many :memberships, dependent: :destroy
+ has_many :groups, through: :memberships
# has_one :ordergroup, :through => :memberships, :source => :group, :class_name => "Ordergroup"
def ordergroup
- Ordergroup.joins(:memberships).where(memberships: { user_id: self.id }).first
+ Ordergroup.joins(:memberships).where(memberships: { user_id: id }).first
end
- has_many :workgroups, :through => :memberships, :source => :group, :class_name => "Workgroup"
- has_many :assignments, :dependent => :destroy
- has_many :tasks, :through => :assignments
- has_many :send_messages, :class_name => "Message", :foreign_key => "sender_id"
- has_many :created_orders, :class_name => 'Order', :foreign_key => 'created_by_user_id', :dependent => :nullify
- has_many :mail_delivery_status, :class_name => 'MailDeliveryStatus', :foreign_key => 'email', :primary_key => 'email'
+ has_many :workgroups, through: :memberships, source: :group, class_name: 'Workgroup'
+ has_many :assignments, dependent: :destroy
+ has_many :tasks, through: :assignments
+ has_many :send_messages, class_name: 'Message', foreign_key: 'sender_id'
+ has_many :created_orders, class_name: 'Order', foreign_key: 'created_by_user_id', dependent: :nullify
+ has_many :mail_delivery_status, class_name: 'MailDeliveryStatus', foreign_key: 'email', primary_key: 'email'
attr_accessor :create_ordergroup, :password, :send_welcome_mail, :settings_attributes
@@ -26,22 +26,22 @@ class User < ApplicationRecord
# makes the current_user (logged-in-user) available in models
cattr_accessor :current_user
- validates_presence_of :email
- validates_presence_of :password, :on => :create
- validates_format_of :email, :with => /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i
- validates_uniqueness_of :email, :case_sensitive => false
- validates_presence_of :first_name # for simple_form validations
- validates_length_of :first_name, :in => 2..50
- validates_confirmation_of :password
- validates_length_of :password, :in => 5..50, :allow_blank => true
+ validates :email, presence: true
+ validates :password, presence: { on: :create }
+ validates :email, format: { with: /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i }
+ validates :email, uniqueness: { case_sensitive: false }
+ validates :first_name, presence: true # for simple_form validations
+ validates :first_name, length: { in: 2..50 }
+ validates :password, confirmation: true
+ validates :password, length: { in: 5..50, allow_blank: true }
# allow nick to be nil depending on foodcoop config
# TODO Rails 4 may have a more beautiful way
# http://stackoverflow.com/questions/19845910/conditional-allow-nil-part-of-validation
- validates_length_of :nick, :in => 2..25, :allow_nil => true, :unless => Proc.new { FoodsoftConfig[:use_nick] }
- validates_length_of :nick, :in => 2..25, :allow_nil => false, :if => Proc.new { FoodsoftConfig[:use_nick] }
- validates_uniqueness_of :nick, :case_sensitive => false, :allow_nil => true # allow_nil in length validation
- validates_format_of :iban, :with => /\A[A-Z]{2}[0-9]{2}[0-9A-Z]{,30}\z/, :allow_blank => true
- validates_uniqueness_of :iban, :case_sensitive => false, :allow_blank => true
+ validates :nick, length: { in: 2..25, allow_nil: true, unless: proc { FoodsoftConfig[:use_nick] } }
+ validates :nick, length: { in: 2..25, allow_nil: false, if: proc { FoodsoftConfig[:use_nick] } }
+ validates :nick, uniqueness: { case_sensitive: false, allow_nil: true } # allow_nil in length validation
+ validates :iban, format: { with: /\A[A-Z]{2}[0-9]{2}[0-9A-Z]{,30}\z/, allow_blank: true }
+ validates :iban, uniqueness: { case_sensitive: false, allow_blank: true }
before_validation :set_password
after_initialize do
@@ -58,17 +58,19 @@ class User < ApplicationRecord
end
after_save do
- settings_attributes.each do |key, value|
- value.each do |k, v|
- case v
- when '1'
- value[k] = true
- when '0'
- value[k] = false
+ if settings_attributes
+ settings_attributes.each do |key, value|
+ value.each do |k, v|
+ case v
+ when '1'
+ value[k] = true
+ when '0'
+ value[k] = false
+ end
end
+ settings.merge!(key, value)
end
- self.settings.merge!(key, value)
- end if settings_attributes
+ end
if ActiveModel::Type::Boolean.new.cast(create_ordergroup)
og = Ordergroup.new({ name: name })
@@ -103,7 +105,7 @@ class User < ApplicationRecord
match_name = q.split.map do |a|
users[:first_name].matches("%#{a}%").or users[:last_name].matches("%#{a}%")
end.reduce(:and)
- User.where(match_nick.or match_name)
+ User.where(match_nick.or(match_name))
end
def locale
@@ -111,7 +113,7 @@ class User < ApplicationRecord
end
def name
- [first_name, last_name].join(" ")
+ [first_name, last_name].join(' ')
end
def receive_email?
@@ -120,22 +122,24 @@ class User < ApplicationRecord
# Sets the user's password. It will be stored encrypted along with a random salt.
def set_password
- unless password.blank?
- salt = [Array.new(6) { rand(256).chr }.join].pack("m").chomp
- self.password_hash, self.password_salt = Digest::SHA1.hexdigest(password + salt), salt
- end
+ return if password.blank?
+
+ salt = [Array.new(6) { rand(256).chr }.join].pack('m').chomp
+ self.password_hash = Digest::SHA1.hexdigest(password + salt)
+ self.password_salt = salt
end
# Returns true if the password argument matches the user's password.
def has_password(password)
- Digest::SHA1.hexdigest(password + self.password_salt) == self.password_hash
+ Digest::SHA1.hexdigest(password + password_salt) == password_hash
end
# Returns a random password.
def new_random_password(size = 6)
- c = %w(b c d f g h j k l m n p qu r s t v w x z ch cr fr nd ng nk nt ph pr rd sh sl sp st th tr)
- v = %w(a e i o u y)
- f, r = true, ''
+ c = %w[b c d f g h j k l m n p qu r s t v w x z ch cr fr nd ng nk nt ph pr rd sh sl sp st th tr]
+ v = %w[a e i o u y]
+ f = true
+ r = ''
(size * 2).times do
r << (f ? c[rand * c.size] : v[rand * v.size])
f = !f
@@ -198,12 +202,12 @@ class User < ApplicationRecord
# returns true if user is a member of a given group
def member_of?(group)
- group.users.exists?(self.id)
+ group.users.exists?(id)
end
# Returns an array with the users groups (but without the Ordergroups -> because tpye=>"")
- def member_of_groups()
- self.groups.where(type: '')
+ def member_of_groups
+ groups.where(type: '')
end
def deleted?
@@ -220,11 +224,9 @@ class User < ApplicationRecord
def self.authenticate(login, password)
user = find_by_nick(login) || find_by_email(login)
- if user && password && user.has_password(password)
- user
- else
- nil
- end
+ return unless user && password && user.has_password(password)
+
+ user
end
def self.custom_fields
@@ -248,29 +250,29 @@ class User < ApplicationRecord
def token_attributes
# would be sensible to match ApplicationController#show_user
# this should not be part of the model anyway
- { :id => id, :name => "#{display} (#{ordergroup.try(:name)})" }
+ { id: id, name: "#{display} (#{ordergroup.try(:name)})" }
end
def self.sort_by_param(param)
- param ||= "name"
+ param ||= 'name'
sort_param_map = {
- "nick" => "nick",
- "nick_reverse" => "nick DESC",
- "name" => "first_name, last_name",
- "name_reverse" => "first_name DESC, last_name DESC",
- "email" => "users.email",
- "email_reverse" => "users.email DESC",
- "phone" => "phone",
- "phone_reverse" => "phone DESC",
- "last_activity" => "last_activity",
- "last_activity_reverse" => "last_activity DESC",
- "ordergroup" => "IFNULL(groups.type, '') <> 'Ordergroup', groups.name",
- "ordergroup_reverse" => "IFNULL(groups.type, '') <> 'Ordergroup', groups.name DESC"
+ 'nick' => 'nick',
+ 'nick_reverse' => 'nick DESC',
+ 'name' => 'first_name, last_name',
+ 'name_reverse' => 'first_name DESC, last_name DESC',
+ 'email' => 'users.email',
+ 'email_reverse' => 'users.email DESC',
+ 'phone' => 'phone',
+ 'phone_reverse' => 'phone DESC',
+ 'last_activity' => 'last_activity',
+ 'last_activity_reverse' => 'last_activity DESC',
+ 'ordergroup' => "IFNULL(groups.type, '') <> 'Ordergroup', groups.name",
+ 'ordergroup_reverse' => "IFNULL(groups.type, '') <> 'Ordergroup', groups.name DESC"
}
# Never pass user input data to Arel.sql() because of SQL Injection vulnerabilities.
# This case here is okay, as param is mapped to the actual order string.
- self.eager_load(:groups).order(Arel.sql(sort_param_map[param])) # eager_load is like left_join but without duplicates
+ eager_load(:groups).order(Arel.sql(sort_param_map[param])) # eager_load is like left_join but without duplicates
end
end
diff --git a/app/models/workgroup.rb b/app/models/workgroup.rb
index bf50c27b..271dec8d 100644
--- a/app/models/workgroup.rb
+++ b/app/models/workgroup.rb
@@ -3,26 +3,26 @@ class Workgroup < Group
has_many :tasks
# returns all non-finished tasks
- has_many :open_tasks, -> { where(:done => false).order('due_date', 'name') }, :class_name => 'Task'
+ has_many :open_tasks, -> { where(done: false).order('due_date', 'name') }, class_name: 'Task'
- validates_uniqueness_of :name
- validate :last_admin_on_earth, :on => :update
+ validates :name, uniqueness: true
+ validate :last_admin_on_earth, on: :update
before_destroy :check_last_admin_group
protected
# 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 I18n.t('workgroups.error_last_admin_group')
- end
+ return unless role_admin && Workgroup.where(role_admin: true).size == 1
+
+ raise I18n.t('workgroups.error_last_admin_group')
end
# add validation check on update
# 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: true).where.not(id: id).exists?
- errors.add(:role_admin, I18n.t('workgroups.error_last_admin_role'))
- end
+ return unless !role_admin && !Workgroup.where(role_admin: true).where.not(id: id).exists?
+
+ errors.add(:role_admin, I18n.t('workgroups.error_last_admin_role'))
end
end
diff --git a/app/views/active_storage/blobs/_blob.html.erb b/app/views/active_storage/blobs/_blob.html.erb
deleted file mode 100644
index 49ba357d..00000000
--- a/app/views/active_storage/blobs/_blob.html.erb
+++ /dev/null
@@ -1,14 +0,0 @@
- attachment--<%= blob.filename.extension %>">
- <% if blob.representable? %>
- <%= image_tag blob.representation(resize_to_limit: local_assigns[:in_gallery] ? [ 800, 600 ] : [ 1024, 768 ]) %>
- <% end %>
-
-
- <% if caption = blob.try(:caption) %>
- <%= caption %>
- <% else %>
- <%= blob.filename %>
- <%= number_to_human_size blob.byte_size %>
- <% end %>
-
-
diff --git a/app/views/active_storage/blobs/_blob.html.haml b/app/views/active_storage/blobs/_blob.html.haml
new file mode 100644
index 00000000..6ddb2e08
--- /dev/null
+++ b/app/views/active_storage/blobs/_blob.html.haml
@@ -0,0 +1,9 @@
+%figure{class: "attachment attachment--#{blob.representable? ? "preview" : "file"} attachment--#{blob.filename.extension}"}
+ - if blob.representable?
+ = image_tag blob.representation(resize_to_limit: local_assigns[:in_gallery] ? [ 800, 600 ] : [ 1024, 768 ])
+ %figcaption.attachment__caption
+ - if caption = blob.try(:caption)
+ = caption
+ - else
+ %span.attachment__name= link_to blob.filename, blob
+ %span.attachment__size= number_to_human_size blob.byte_size
diff --git a/app/views/admin/configs/_tab_others.html.haml b/app/views/admin/configs/_tab_others.html.haml
index 907cf840..93e1be2d 100644
--- a/app/views/admin/configs/_tab_others.html.haml
+++ b/app/views/admin/configs/_tab_others.html.haml
@@ -4,5 +4,6 @@
= config_input form, :distribution_strategy, as: :select, collection: distribution_strategy_options,
include_blank: false, input_html: {class: 'input-xxlarge'}, label_method: ->(s){ t("config.keys.distribution_strategy_options.#{s}") }
= config_input form, :disable_invite, as: :boolean
+= config_input form, :disable_members_overview, as: :boolean
= config_input form, :help_url, as: :url, input_html: {class: 'input-xlarge'}
= config_input form, :webstats_tracking_code, as: :text, input_html: {class: 'input-xxlarge', rows: 3}
diff --git a/app/views/articles/_sync_table.html.haml b/app/views/articles/_sync_table.html.haml
index 62640cbe..68db9477 100644
--- a/app/views/articles/_sync_table.html.haml
+++ b/app/views/articles/_sync_table.html.haml
@@ -32,8 +32,8 @@
= form.text_field 'name', :size => 0
- hidden_fields.each do |field|
= form.hidden_field field
- %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, :note)}= form.text_field 'note', class: 'input-medium'
+ %td{:style => highlight_new(attrs, :manufacturer)}= form.text_field 'manufacturer', class: 'input-medium'
%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'
@@ -50,8 +50,7 @@
%span.add-on= t 'number.currency.format.unit'
= form.text_field 'deposit', class: 'input-mini', style: 'width: 45px'
%td{:style => highlight_new(attrs, :article_category)}
- = form.select :article_category_id, ArticleCategory.all.map {|a| [ a.name, a.id ] },
- {include_blank: true}, class: 'input-small'
+ = form.select :article_category_id, ArticleCategory.all.map {|a| [ a.name, a.id ] }, {include_blank: true}
- unless changed_article.errors.empty?
%tr.alert
%td(colspan=11)= changed_article.errors.full_messages.join(', ')
diff --git a/app/views/articles/upload.html.haml b/app/views/articles/upload.html.haml
index dc32fe3a..8f91d790 100644
--- a/app/views/articles/upload.html.haml
+++ b/app/views/articles/upload.html.haml
@@ -71,19 +71,11 @@
= form_for :articles, :url => parse_upload_supplier_articles_path(@supplier),
:html => { multipart: true, class: "form-horizontal" } do |f|
-
.control-group
- %label(for="articles_file")
- %strong= t '.file_label'
+ %label(for="articles_file")= t '.file_label'
= f.file_field "file"
- %label(for="articles_file")
- %strong="select the file type you are about to upload"
- =f.collection_select :type, ["bnn","foodsoft","odin"], :to_s, :to_s
.control-group
- %label(for="articles_update_category")
- = f.check_box "update_category"
- = t '.options.update_category'
%label(for="articles_outlist_absent")
= f.check_box "outlist_absent"
= t '.options.outlist_absent'
diff --git a/app/views/finance/ordergroups/_ordergroups.html.haml b/app/views/finance/ordergroups/_ordergroups.html.haml
index 3e0c99fc..6cf12c16 100644
--- a/app/views/finance/ordergroups/_ordergroups.html.haml
+++ b/app/views/finance/ordergroups/_ordergroups.html.haml
@@ -28,6 +28,6 @@
%th
- FinancialTransactionClass.sorted.each do |c|
- name = FinancialTransactionClass.has_multiple_classes ? c.display : heading_helper(Ordergroup, :account_balance)
- %th.numeric= format_currency @total_balances[c.id]
- %th.numeric
+ %th.numeric{:id => "total_balance#{c.id}"}= format_currency @total_balances[c.id]
+ %th.numeric#total_balance_sum
= format_currency @total_balances.values.reduce(:+)
\ No newline at end of file
diff --git a/app/views/group_orders/_explanations.haml b/app/views/group_orders/_explanations.haml
deleted file mode 100644
index 30e5b91c..00000000
--- a/app/views/group_orders/_explanations.haml
+++ /dev/null
@@ -1,15 +0,0 @@
-%h4= t '.title'
-%hr
-%table.table-condensed
- %thead
- %th= t '.package_fill_level'
- %tbody
- %tr{class: "missing-none"}
- %td= t '.missing_none'
- %tr{class: "missing-few"}
- %td= t '.missing_few'
- %tr{class: "missing-many"}
- %td= t '.missing_many'
-%hr
- %b= t('.tolerance') + ':'
- = t '.tolerance_explained'
\ No newline at end of file
diff --git a/app/views/group_orders/_form.html.haml b/app/views/group_orders/_form.html.haml
index 9d13e525..3ffd583e 100644
--- a/app/views/group_orders/_form.html.haml
+++ b/app/views/group_orders/_form.html.haml
@@ -11,142 +11,170 @@
var listjsResetPlugin = ['reset', {highlightClass: 'btn-primary'}];
var listjsDelayPlugin = ['delay', {delayedSearchTime: 500}];
new List(document.body, {
- valueNames: ['name'],
- engine: 'unlist',
- plugins: [listjsResetPlugin, listjsDelayPlugin],
- // make large pages work too (as we don't have paging - articles may disappear!)
- page: 10000,
- indexAsync: true
+ valueNames: ['name'],
+ engine: 'unlist',
+ plugins: [listjsResetPlugin, listjsDelayPlugin],
+ // make large pages work too (as we don't have paging - articles may disappear!)
+ page: 10000,
+ indexAsync: true
});
});
- title t('.title'), false
-.alert.alert-error#balance-alert{style: ('display:none')}
- =t 'group_orders.errors.balance_alert'
.row-fluid
- .span2
- .well
- = render 'switch_order', current_order: @order
- .well
- = render 'explanations'
- .well.span9
- %h2.span9= t '.sub_title', order_name: @order.name
- .span3
- %table.table-condensed
- -if @order.ends
- %tr
- %td= heading_helper(Order, :ends) + ': '
- %td= format_time(@order.ends)
- - unless @order.stockit? or @order.supplier.min_order_quantity.blank?
- %tr
- %td= heading_helper(Supplier, :min_order_quantity)
- %td= number_to_currency(@order.supplier.min_order_quantity)
- %tr
- %td= t('group_orders.form.sum_amount') + ':'
- %td= number_to_currency(@order.sum)
- %hr
- .form-search.pull-right
+ .well.pull-left
+ = close_button :alert
+ %h2= @order.name
+ %dl.dl-horizontal
+ - unless @order.note.blank?
+ %dt= heading_helper Order, :note
+ %dd= @order.note
+ %dt= heading_helper Order, :created_by
+ %dd= show_user_link(@order.created_by)
+ %dt= heading_helper Order, :ends
+ %dd= format_time(@order.ends)
+ %dt= heading_helper Order, :pickup
+ %dd= format_date(@order.pickup)
+ - unless @order.stockit? or @order.supplier.min_order_quantity.blank?
+ %dt= heading_helper Supplier, :min_order_quantity, short: true
+ %dd= @order.supplier.min_order_quantity
+ %dt= t '.sum_amount'
+ %dd= number_to_currency @order.sum
+ - unless @group_order.new_record?
+ %dt= heading_helper GroupOrder, :updated_by
+ %dd
+ = show_user(@group_order.updated_by)
+ (#{format_time(@group_order.updated_on)})
+ %dt= heading_helper Ordergroup, :account_balance
+ %dd= number_to_currency(@ordering_data[:account_balance])
+ - unless FoodsoftConfig[:charge_members_manually]
+ %dt= heading_helper Ordergroup, :available_funds
+ %dd= number_to_currency(@ordering_data[:available_funds])
+
+ .well.pull-right
+ = close_button :alert
+ = render 'switch_order', current_order: @order
+
+.row-fluid
+ .well.clear
+ .form-search
.input-append
= text_field_tag :article, params[:article], placeholder: t('.search_article'), class: 'search-query delayed-search resettable'
%button.add-on.btn.reset-search{:type => :button, :title => t('.reset_article_search')}
%i.icon.icon-remove
- = form_for @group_order do |f|
- = f.hidden_field :lock_version
- = f.hidden_field :order_id
- = f.hidden_field :updated_by_user_id
- = f.hidden_field :ordergroup_id
- %table.table
- %thead
- %tr
- %th= heading_helper Article, :name
+
+= form_for @group_order do |f|
+ = f.hidden_field :lock_version
+ = f.hidden_field :order_id
+ = f.hidden_field :updated_by_user_id
+ = f.hidden_field :ordergroup_id
+ %table.table.table-hover
+ %thead
+ %tr
+ %th= heading_helper Article, :name
+ - if @order.stockit?
+ %th{style: 'width:120px'}= heading_helper StockArticle, :supplier
+ %th{style: "width:13px;"}
+ %th{style: "width:4.5em;"}= t '.price'
+ %th{style: "width:4.5em;"}= heading_helper Article, :unit
+ - unless @order.stockit?
+ %th{style: "width:70px;"}= heading_helper OrderArticle, :missing_units, short: true
+ %th#col_required= heading_helper GroupOrderArticle, :quantity
+ %th#col_tolerance= heading_helper GroupOrderArticle, :tolerance
+ - else
+ %th(style="width:20px")= heading_helper StockArticle, :available
+ %th#col_required= heading_helper GroupOrderArticle, :quantity
+ %th{style: "width:15px;"}= heading_helper GroupOrderArticle, :total_price
+ %tbody.list
+ - @order.articles_grouped_by_category.each do |category, order_articles|
+ %tr.list-heading.article-category
+ %td
+ = category
+ %i.icon-tag
+ %td{colspan: "9"}
+ - order_articles.each do |order_article|
+ %tr{class: "#{cycle('even', 'odd', name: 'articles')} order-article #{get_missing_units_css_class(@ordering_data[:order_articles][order_article.id][:missing_units])}", valign: "top"}
+ %td.name= order_article.article.name
- if @order.stockit?
- %th{style: 'width:120px'}= heading_helper StockArticle, :supplier
- %th{style: "width:13px;"}
- %th{style: "width:4.5em;"}= t '.price'
- %th{style: "width:4.5em;"}= t '.price_per_base_unit'
- %th{style: "width:4.5em;"}= heading_helper Article, :unit
- - unless @order.stockit?
- %th{style: "width:70px;"}= heading_helper OrderArticle, :missing_units, short: true
- %th#col_required= heading_helper GroupOrderArticle, :quantity
- %th#col_tolerance= heading_helper GroupOrderArticle, :tolerance
- - else
- %th(style="width:20px")= heading_helper StockArticle, :available
- %th#col_required= heading_helper GroupOrderArticle, :quantity
- %th{style: "width:15px;"}= heading_helper GroupOrderArticle, :total_price
- %tbody.list
- - @order.articles_grouped_by_category.each do | category, order_articles|
- %tr.list-heading.article-category
- %td
- = category
- %i.icon-tag
- %td{colspan: "9"}
- - order_articles.each do |order_article|
- %tr{class: "#{cycle('even', 'odd', name: 'articles')} order-article #{get_missing_units_css_class(@ordering_data[:order_articles][order_article.id][:missing_units])}", valign: "top", tabindex: "0"}
- %td.name= order_article.article.name
- - if @order.stockit?
- %td= truncate order_article.article.supplier.name, length: 15
- %td= h order_article.article.origin
- %td= number_to_currency(@ordering_data[:order_articles][order_article.id][:price])
- %td= price_per_base_unit(article: order_article.article, price: @ordering_data[:order_articles][order_article.id][:price])
- %td= order_article.article.unit
- %td
- - if @order.stockit?
- = @ordering_data[:order_articles][order_article.id][:quantity_available]
- - else
- %span{id: "missing_units_#{order_article.id}"}= @ordering_data[:order_articles][order_article.id][:missing_units]
+ %td= truncate order_article.article.supplier.name, length: 15
+ %td= h order_article.article.origin
+ %td= number_to_currency(@ordering_data[:order_articles][order_article.id][:price])
+ %td= order_article.article.unit
+ %td
+ - if @order.stockit?
+ = @ordering_data[:order_articles][order_article.id][:quantity_available]
+ - else
+ %span{id: "missing_units_#{order_article.id}"}= @ordering_data[:order_articles][order_article.id][:missing_units]
- %td.quantity
- .outer{style: "diyplay: inline-block; float: left; width: 50px;"}
- %input{id: "q_#{order_article.id}", name: "group_order[group_order_articles_attributes][#{order_article.id}][quantity]", type: "hidden", value: @ordering_data[:order_articles][order_article.id][:quantity], 'data-min' => (@ordering_data[:order_articles][order_article.id][:quantity] if @order.boxfill?), 'data-max' => (@ordering_data[:order_articles][order_article.id][:quantity]+@ordering_data[:order_articles][order_article.id][:missing_units] if @order.boxfill?)}/
- %span.used{id: "q_used_#{order_article.id}"}= @ordering_data[:order_articles][order_article.id][:used_quantity]
- +
- %span.unused{id: "q_unused_#{order_article.id}"}= @ordering_data[:order_articles][order_article.id][:quantity] - @ordering_data[:order_articles][order_article.id][:used_quantity]
- .btn-group
- %a.btn.btn-ordering{'data-decrease_quantity' => order_article.id}
- %i.icon-minus
- %a.btn.btn-ordering{'data-increase_quantity' => order_article.id}
- %i.icon-plus
+ %td.quantity
+ %input{id: "q_#{order_article.id}", name: "group_order[group_order_articles_attributes][#{order_article.id}][quantity]", type: "hidden", value: @ordering_data[:order_articles][order_article.id][:quantity], 'data-min' => (@ordering_data[:order_articles][order_article.id][:quantity] if @order.boxfill?), 'data-max' => (@ordering_data[:order_articles][order_article.id][:quantity]+@ordering_data[:order_articles][order_article.id][:missing_units] if @order.boxfill?)}/
+ %span.used{id: "q_used_#{order_article.id}"}= @ordering_data[:order_articles][order_article.id][:used_quantity]
+ +
+ %span.unused{id: "q_unused_#{order_article.id}"}= @ordering_data[:order_articles][order_article.id][:quantity] - @ordering_data[:order_articles][order_article.id][:used_quantity]
+ .btn-group
+ %a.btn.btn-ordering{'data-increase_quantity' => order_article.id}
+ %i.icon-plus
+ %a.btn.btn-ordering{'data-decrease_quantity' => order_article.id}
+ %i.icon-minus
- %td.tolerance{style: ('display:none' if @order.stockit?)}
- %input{id: "t_#{order_article.id}", name: "group_order[group_order_articles_attributes][#{order_article.id}][tolerance]", type: "hidden", value: @ordering_data[:order_articles][order_article.id][:tolerance], 'data-min' => (@ordering_data[:order_articles][order_article.id][:tolerance] if @order.boxfill?)}/
- - if (@ordering_data[:order_articles][order_article.id][:unit] > 1)
- %span.used{id: "t_used_#{order_article.id}"}= @ordering_data[:order_articles][order_article.id][:used_tolerance]
- +
- %span.unused{id: "t_unused_#{order_article.id}"}= @ordering_data[:order_articles][order_article.id][:tolerance] - @ordering_data[:order_articles][order_article.id][:used_tolerance]
- .btn-group
- %a.btn.btn-ordering{'data-decrease_tolerance' => order_article.id}
- %i.icon-minus
- %a.btn.btn-ordering{'data-increase_tolerance' => order_article.id}
- %i.icon-plus
+ %td.tolerance{style: ('display:none' if @order.stockit?)}
+ %input{id: "t_#{order_article.id}", name: "group_order[group_order_articles_attributes][#{order_article.id}][tolerance]", type: "hidden", value: @ordering_data[:order_articles][order_article.id][:tolerance], 'data-min' => (@ordering_data[:order_articles][order_article.id][:tolerance] if @order.boxfill?)}/
+ - if (@ordering_data[:order_articles][order_article.id][:unit] > 1)
+ %span.used{id: "t_used_#{order_article.id}"}= @ordering_data[:order_articles][order_article.id][:used_tolerance]
+ +
+ %span.unused{id: "t_unused_#{order_article.id}"}= @ordering_data[:order_articles][order_article.id][:tolerance] - @ordering_data[:order_articles][order_article.id][:used_tolerance]
+ .btn-group
+ %a.btn.btn-ordering{'data-increase_tolerance' => order_article.id}
+ %i.icon-plus
+ %a.btn.btn-ordering{'data-decrease_tolerance' => order_article.id}
+ %i.icon-minus
- %td{id: "td_price_#{order_article.id}", style: "text-align:right; padding-right:10px; width:4em"}
- %span{id: "price_#{order_article.id}_display"}= number_to_currency(@ordering_data[:order_articles][order_article.id][:total_price])
- .article-info
- .article-name= order_article.article.name
- .pull-right
- = t('.units_full') + ':'
- %span{id: "units_#{order_article.id}"}= order_article.units_to_order
- %br/
- = t('.units_total') + ':'
- %span{id: "q_total_#{order_article.id}"}= @ordering_data[:order_articles][order_article.id][:quantity] + @ordering_data[:order_articles][order_article.id][:others_quantity]
- %br/
- = t('.total_tolerance') + ':'
- %span{id: "t_total_#{order_article.id}"}= @ordering_data[:order_articles][order_article.id][:tolerance] + @ordering_data[:order_articles][order_article.id][:others_tolerance]
- %br/
- .pull-left
- #{heading_helper Article, :manufacturer}: #{order_article.article.manufacturer}
- %br/
- #{heading_helper Article, :units}: #{@order.stockit? ? order_article.article.quantity_available : @ordering_data[:order_articles][order_article.id][:unit]} * #{h order_article.article.unit}
- %br/
- #{heading_helper Article, :note}: #{order_article.article.note}
- %br/
- #order-footer
- #info-box
- #total-sum
- = render 'total_sum'
- #order-button
- = submit_tag( t('.action_save'), id: 'submit_button', class: 'btn btn-primary' )
- #{link_to t('ui.or_cancel'), group_orders_path}
- %input#total_balance{name: "total_balance", type: "hidden", value: @ordergroup.account_balance - @group_order.price}/
- %input{name: "version", type: "hidden", value: @version}/
+ %td{id: "td_price_#{order_article.id}", style: "text-align:right; padding-right:10px; width:4em"}
+ %span{id: "price_#{order_article.id}_display"}= number_to_currency(@ordering_data[:order_articles][order_article.id][:total_price])
+ .article-info
+ .article-name= order_article.article.name
+ .pull-right
+ = t('.units_full') + ':'
+ %span{id: "units_#{order_article.id}"}= order_article.units_to_order
+ %br/
+ = t('.units_total') + ':'
+ %span{id: "q_total_#{order_article.id}"}= @ordering_data[:order_articles][order_article.id][:quantity] + @ordering_data[:order_articles][order_article.id][:others_quantity]
+ %br/
+ = t('.total_tolerance') + ':'
+ %span{id: "t_total_#{order_article.id}"}= @ordering_data[:order_articles][order_article.id][:tolerance] + @ordering_data[:order_articles][order_article.id][:others_tolerance]
+ %br/
+ .pull-left
+ #{heading_helper Article, :manufacturer}: #{order_article.article.manufacturer}
+ %br/
+ #{heading_helper Article, :units}: #{@order.stockit? ? order_article.article.quantity_available : @ordering_data[:order_articles][order_article.id][:unit]} * #{h order_article.article.unit}
+ %br/
+ #{heading_helper Article, :note}: #{order_article.article.note}
+ %br/
+ #order-footer
+ #info-box
+ #total-sum
+ %table
+ %tr
+ %td= t('.total_sum_amount') + ':'
+ %td.currency
+ %span#total_price= number_to_currency(@group_order.price)
+ %tr
+ - if FoodsoftConfig[:charge_members_manually]
+ - old_balance = @ordering_data[:account_balance]
+ %td= heading_helper(Ordergroup, :account_balance) + ':'
+ %td.currency= number_to_currency(@ordering_data[:account_balance])
+ - else
+ - old_balance = @ordering_data[:available_funds]
+ %td= heading_helper(Ordergroup, :available_funds) + ':'
+ %td.currency= number_to_currency(@ordering_data[:available_funds])
+ %tr
+ %td= t('.new_funds') + ':'
+ %td.currency
+ %strong
+ %span#new_balance= number_to_currency(old_balance - @group_order.price)
+ #order-button
+ = submit_tag( t('.action_save'), id: 'submit_button', class: 'btn btn-primary' )
+ #{link_to t('ui.or_cancel'), group_orders_path}
+ %input#total_balance{name: "total_balance", type: "hidden", value: @ordergroup.account_balance - @group_order.price}/
+ %input{name: "version", type: "hidden", value: @version}/
diff --git a/app/views/group_orders/_switch_order.html.haml b/app/views/group_orders/_switch_order.html.haml
index 70234b39..76443524 100644
--- a/app/views/group_orders/_switch_order.html.haml
+++ b/app/views/group_orders/_switch_order.html.haml
@@ -1,10 +1,9 @@
-- orders = Order.open.started
+- orders = Order.open.started.reject{ |order| order == current_order }
- unless orders.empty?
- %ul.nav.nav-pills.nav-stacked
- .nav-header= t '.title'
- %li= link_to t('ui.overview'), :group_orders
+ %h2= t '.title'
+ %ul.unstyled
- orders.each do |order|
- .btn-small.pull-right
- =link_to_ordering(order, style: (order == current_order ? 'color: white' : '' ), 'data-confirm_switch_order' => true){ t 'ui.edit' }
- %li( class="#{ order == current_order ? 'active' : ''}")
- =link_to_ordering(order, show: true, 'data-confirm_switch_order' => true)
\ No newline at end of file
+ %li
+ = link_to_ordering(order, 'data-confirm_switch_order' => true)
+ - if order.ends
+ = t '.remaining', remaining: time_ago_in_words(order.ends)
diff --git a/app/views/group_orders/_total_sum.haml b/app/views/group_orders/_total_sum.haml
deleted file mode 100644
index 28911b32..00000000
--- a/app/views/group_orders/_total_sum.haml
+++ /dev/null
@@ -1,19 +0,0 @@
-%table
- %tr
- %td= t('group_orders.form.total_sum_amount') + ':'
- %td.currency
- %span#total_price= number_to_currency(@group_order.price)
- %tr
- - if FoodsoftConfig[:charge_members_manually]
- - old_balance = @ordering_data[:account_balance]
- %td= heading_helper(Ordergroup, :account_balance) + ':'
- %td.currency= number_to_currency(@ordering_data[:account_balance])
- - else
- - old_balance = @ordering_data[:available_funds]
- %td= heading_helper(Ordergroup, :available_funds) + ':'
- %td.currency= number_to_currency(@ordering_data[:available_funds])
- %tr
- %td= t('group_orders.form.new_funds') + ':'
- %td.currency
- %strong
- %span#new_balance= number_to_currency(old_balance - @group_order.price)
diff --git a/app/views/group_orders/index.html.haml b/app/views/group_orders/index.html.haml
index 55c97c81..158bc06c 100644
--- a/app/views/group_orders/index.html.haml
+++ b/app/views/group_orders/index.html.haml
@@ -18,27 +18,22 @@
%th= heading_helper Ordergroup, :available_funds
%th.numeric= number_to_currency(@ordergroup.get_available_funds)
-.row-fluid
- .span9
- = render :partial => "shared/open_orders", :locals => {:ordergroup => @ordergroup}
- // finished orders
+= render :partial => "shared/open_orders", :locals => {:ordergroup => @ordergroup}
+
+// finished orders
- unless @finished_not_closed_orders_including_group_order.empty?
- .row-fluid
- .span9
- %section
- %h2= t '.finished_orders.title'
- = render partial: 'orders', locals: {orders: @finished_not_closed_orders_including_group_order, pagination: false}
- - if @ordergroup.value_of_finished_orders > 0
- %p
- = t('.finished_orders.total_sum') + ':'
- %b= number_to_currency(@ordergroup.value_of_finished_orders)
+ %section
+ %h2= t '.finished_orders.title'
+ = render partial: 'orders', locals: {orders: @finished_not_closed_orders_including_group_order, pagination: false}
+ - if @ordergroup.value_of_finished_orders > 0
+ %p
+ = t('.finished_orders.total_sum') + ':'
+ %b= number_to_currency(@ordergroup.value_of_finished_orders)
// closed orders
- unless @closed_orders_including_group_order.empty?
- .row-fluid
- .span9
- %section
- %h2= t '.closed_orders.title'
- = render partial: 'orders', locals: {orders: @closed_orders_including_group_order, pagination: false}
- %br/
- = link_to t('.closed_orders.more'), archive_group_orders_path
+ %section
+ %h2= t '.closed_orders.title'
+ = render partial: 'orders', locals: {orders: @closed_orders_including_group_order, pagination: false}
+ %br/
+ = link_to t('.closed_orders.more'), archive_group_orders_path
diff --git a/app/views/group_orders/show.html.haml b/app/views/group_orders/show.html.haml
index b9d4f674..8c9678d7 100644
--- a/app/views/group_orders/show.html.haml
+++ b/app/views/group_orders/show.html.haml
@@ -7,115 +7,107 @@
- title t('.title', order: @order.name)
.row-fluid
-
- .well.span2
- = render 'switch_order', current_order: @order
- .well.span9
- %h2= t '.articles.title'
+ .well.pull-left
+ // Order summary
%dl.dl-horizontal
- // Name
%dt= heading_helper Order, :name
%dd= @order.name
- // Order Ends
+ %dt= heading_helper Order, :note
+ %dd= @order.note
%dt= heading_helper Order, :ends
%dd= format_time(@order.ends)
- // Pickup
- - unless @order.pickup.blank?
- %dt= heading_helper Order, :pickup
- %dd= format_date(@order.pickup)
- // Min Order Quantity
- - unless @order.stockit? or @order.supplier.min_order_quantity.blank?
- %dt= heading_helper Supplier, :min_order_quantity, short: true
- %dd= @order.supplier.min_order_quantity
- // Group Order Sum Amount
- %dt= t 'group_orders.form.sum_amount'
- %dd= number_to_currency @order.sum
- // Created By
- %dt= heading_helper Order, :created_by
- %dd= show_user_link(@order.created_by)
- // Updated By
- - unless @group_order.new_record?
- %dt= heading_helper GroupOrder, :updated_by
- %dd
- = show_user(@group_order.updated_by)
- (#{format_time(@group_order.updated_on)})
- // Closed By
+ %dt= heading_helper Order, :pickup
+ %dd= format_date(@order.pickup)
+ %dt= heading_helper GroupOrder, :price
+ %dd
+ - if @group_order
+ = number_to_currency(@group_order.price)
+ - else
+ = t '.not_ordered'
+ - if @group_order && @group_order.transport
+ %dt= heading_helper GroupOrder, :transport
+ %dd= number_to_currency(@group_order.transport)
+ %dt= heading_helper GroupOrder, :total
+ %dd= number_to_currency(@group_order.total)
- if @order.closed?
%dt= heading_helper Order, :closed_by
%dd= show_user_link @order.updated_by
- // Note
- - unless @order.note.blank?
- %dt= heading_helper Order, :note
- %dd= @order.note
+ %p= link_to t('.comment'), "#comments"
- // Article box
- %section
- .column_content#result
- - if @group_order
- %p= link_to t('.articles.show_hide'), '#', 'data-toggle-this' => 'tr.ignored'
- %table.table.table-hover
- %thead
- %tr
- %th{style: "width:40%"}= heading_helper Article, :name
- %th= heading_helper Article, :units
- %th= t '.articles.unit_price'
- %th
- %abbr{title: t('.articles.ordered_title')}= t '.articles.ordered'
- %th
- %abbr{title: t('.articles.order_nopen_title')}
- - if @order.open?
- = t '.articles.order_open'
- - else
- = t '.articles.order_not_open'
- %th= heading_helper GroupOrderArticle, :total_price
- %tbody
- - for category_name, order_articles in @order.articles_grouped_by_category
- %tr.article-category
- %td
- = category_name
- %i.icon-tag
- %td{colspan: "9"}
- - order_articles.each do |oa|
- - # get the order-results for the ordergroup
- - r = get_order_results(oa, @group_order.id)
- %tr{class: cycle('even', 'odd', name: 'articles') + " " + order_article_class_name(r[:quantity], r[:tolerance], r[:result])}
- %td{style: "width:40%"}
- = oa.article.name
- - unless oa.article.note.blank?
- = image_tag("lamp_grey.png", {alt: t('.articles.show_note'), size: "15x16", border: "0", onmouseover: "$('#note_#{oa.id}').show();", onmouseout: "$('#note_#{oa.id}').hide();"})
- %td= "#{oa.price.unit_quantity} x #{oa.article.unit}"
- %td= number_to_currency(oa.price.fc_price)
- %td
- = r[:quantity]
- = "+ #{r[:tolerance]}" if oa.price.unit_quantity > 1
- %td= r[:result] > 0 ? r[:result] : "0"
- %td= number_to_currency(r[:sub_total])
+ .well.pull-right
+ = close_button :alert
+ = render 'switch_order', current_order: @order
+
+// Article box
+%section
+ %h2= t '.articles.title'
+ .column_content#result
+ - if @group_order
+ %p.pull-right= link_to t('.articles.show_hide'), '#', 'data-toggle-this' => 'tr.ignored'
+ %p= link_to(t('.articles.edit_order'), edit_group_order_path(@group_order, order_id: @order.id), class: 'btn btn-primary') if @order.open?
+ %table.table.table-hover
+ %thead
+ %tr
+ %th{style: "width:40%"}= heading_helper Article, :name
+ %th= heading_helper Article, :units
+ %th= t '.articles.unit_price'
+ %th
+ %abbr{title: t('.articles.ordered_title')}= t '.articles.ordered'
+ %th
+ %abbr{title: t('.articles.order_nopen_title')}
+ - if @order.open?
+ = t '.articles.order_open'
+ - else
+ = t '.articles.order_not_open'
+ %th= heading_helper GroupOrderArticle, :total_price
+ %tbody
+ - for category_name, order_articles in @order.articles_grouped_by_category
+ %tr.article-category
+ %td
+ = category_name
+ %i.icon-tag
+ %td{colspan: "9"}
+ - order_articles.each do |oa|
+ - # get the order-results for the ordergroup
+ - r = get_order_results(oa, @group_order.id)
+ %tr{class: cycle('even', 'odd', name: 'articles') + " " + order_article_class_name(r[:quantity], r[:tolerance], r[:result])}
+ %td{style: "width:40%"}
+ = oa.article.name
- unless oa.article.note.blank?
- %tr{id: "note_#{oa.id}", class: "note even", style: "display:none"}
- %td{colspan: "6"}=h oa.article.note
- %tr{class: cycle('even', 'odd', name: 'articles')}
- %th{colspan: "5"}= heading_helper GroupOrder, :price
- %th= number_to_currency(@group_order.price)
- - if @group_order.transport
- %tr{class: cycle('even', 'odd', name: 'articles')}
- %td{colspan: "5"}= heading_helper GroupOrder, :transport
- %td= number_to_currency(@group_order.transport)
- %tr{class: cycle('even', 'odd', name: 'articles')}
- %th{colspan: "5"}= heading_helper GroupOrder, :total
- %th= number_to_currency(@group_order.total)
- %br/
- = link_to_top
- %p.pull-right= link_to(t('.articles.edit_order'), edit_group_order_path(@group_order, order_id: @order.id), class: 'btn btn-primary') if @order.open?
- - else
- - if @order.open?
- = t '.articles.not_ordered_msg'
- = link_to t('.articles.order_now'), action: "order", id: @order
- - else
- = t '.articles.order_closed_msg'
+ = image_tag("lamp_grey.png", {alt: t('.articles.show_note'), size: "15x16", border: "0", onmouseover: "$('#note_#{oa.id}').show();", onmouseout: "$('#note_#{oa.id}').hide();"})
+ %td= "#{oa.price.unit_quantity} x #{oa.article.unit}"
+ %td= number_to_currency(oa.price.fc_price)
+ %td
+ = r[:quantity]
+ = "+ #{r[:tolerance]}" if oa.price.unit_quantity > 1
+ %td= r[:result] > 0 ? r[:result] : "0"
+ %td= number_to_currency(r[:sub_total])
+ - unless oa.article.note.blank?
+ %tr{id: "note_#{oa.id}", class: "note even", style: "display:none"}
+ %td{colspan: "6"}=h oa.article.note
+ %tr{class: cycle('even', 'odd', name: 'articles')}
+ %th{colspan: "5"}= heading_helper GroupOrder, :price
+ %th= number_to_currency(@group_order.price)
+ - if @group_order.transport
+ %tr{class: cycle('even', 'odd', name: 'articles')}
+ %td{colspan: "5"}= heading_helper GroupOrder, :transport
+ %td= number_to_currency(@group_order.transport)
+ %tr{class: cycle('even', 'odd', name: 'articles')}
+ %th{colspan: "5"}= heading_helper GroupOrder, :total
+ %th= number_to_currency(@group_order.total)
+ %br/
+ = link_to_top
+ - else
+ - if @order.open?
+ = t '.articles.not_ordered_msg'
+ = link_to t('.articles.order_now'), action: "order", id: @order
+ - else
+ = t '.articles.order_closed_msg'
+
// Comments box
-%hr
-%h2= t '.comments.title'
-#comments
- = render 'shared/comments', comments: @order.comments
-#new_comment= render 'order_comments/form', order_comment: @order.comments.build(user: current_user)
-= link_to_top
\ No newline at end of file
+%section
+ %h2= t '.comments.title'
+ #comments
+ = render 'shared/comments', comments: @order.comments
+ #new_comment= render 'order_comments/form', order_comment: @order.comments.build(user: current_user)
+ = link_to_top
diff --git a/app/views/home/_start_nav.haml b/app/views/home/_start_nav.haml
index 708e4c85..96313861 100644
--- a/app/views/home/_start_nav.haml
+++ b/app/views/home/_start_nav.haml
@@ -2,7 +2,8 @@
%h3= t '.title'
%ul.nav.nav-list
%li.nav-header= t '.foodcoop'
- %li= link_to t('.members'), foodcoop_users_path
+ - unless FoodsoftConfig[:disable_members_overview]
+ %li= link_to t('.members'), foodcoop_users_path
%li= link_to t('.tasks'), user_tasks_path
- has_ordergroup = !@current_user.ordergroup.nil?
diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml
index 7781096d..c1b1cf00 100644
--- a/app/views/layouts/application.html.haml
+++ b/app/views/layouts/application.html.haml
@@ -13,9 +13,9 @@
%li= link_to t('.reference_calculator'), home_reference_calculator_path
%li= link_to t('.logout'), logout_path
%li{class: ('disabled' if FoodsoftConfig[:homepage].blank?)}
- = link_to FoodsoftConfig[:name], FoodsoftConfig[:homepage]
+ = link_to FoodsoftConfig[:name], FoodsoftConfig[:homepage], target: '_blank'
- if FoodsoftConfig[:help_url]
- %li= link_to t('.help'), FoodsoftConfig[:help_url]
+ %li= link_to t('.help'), FoodsoftConfig[:help_url], target: '_blank'
%li= link_to t('.feedback.title'), new_feedback_path, title: t('.feedback.desc')
.clearfix
diff --git a/app/views/orders/_custom_csv_form.html.haml b/app/views/orders/_custom_csv_form.html.haml
deleted file mode 100644
index 87295af0..00000000
--- a/app/views/orders/_custom_csv_form.html.haml
+++ /dev/null
@@ -1,15 +0,0 @@
-= simple_form_for :custom_csv,format: :csv, :url => order_path(@order, view: @view, format: :csv), method: :get do |f|
- .modal-header
- = close_button :modal
- .h3=I18n.t('.orders.custom_csv.description')
- .modal-body
- = f.input :first, as: :select, collection: custom_csv_collection, label: "1. " + I18n.t('.orders.custom_csv.column')
- = f.input :second, as: :select, collection: custom_csv_collection, required: false, label: "2. " + I18n.t('.orders.custom_csv.column')
- = f.input :third, as: :select, collection: custom_csv_collection, required: false, label: "3. " + I18n.t('.orders.custom_csv.column')
- = f.input :fourth, as: :select, collection: custom_csv_collection, required: false, label: "4. " + I18n.t('.orders.custom_csv.column')
- = f.input :fifth, as: :select, collection: custom_csv_collection, required: false, label: "5. " + I18n.t('.orders.custom_csv.column')
- = f.input :sixth, as: :select, collection: custom_csv_collection, required: false, label: "6. " + I18n.t('.orders.custom_csv.column')
- = f.input :seventh, as: :select, collection: custom_csv_collection, required: false, label: "7. " + I18n.t('.orders.custom_csv.column')
- .modal-footer
- = link_to t('ui.close'), '#', class: 'btn', data: {dismiss: 'modal'}
- = f.submit class: 'btn btn-primary'
diff --git a/app/views/orders/custom_csv.js.haml b/app/views/orders/custom_csv.js.haml
deleted file mode 100644
index 41a6ec83..00000000
--- a/app/views/orders/custom_csv.js.haml
+++ /dev/null
@@ -1,3 +0,0 @@
-$('#modalContainer').html('#{j(render("custom_csv_form"))}');
-$('#modalContainer').modal();
-$('#modalContainer').submit(function() {$('#modalContainer').modal('hide');});
\ No newline at end of file
diff --git a/app/views/orders/index.html.haml b/app/views/orders/index.html.haml
index 1bd870ad..51b426bc 100644
--- a/app/views/orders/index.html.haml
+++ b/app/views/orders/index.html.haml
@@ -33,7 +33,7 @@
%td= order.name
%td= format_date(order.pickup) unless order.pickup.nil?
%td= format_time(order.ends) unless order.ends.nil?
- %td= truncate(order.note)
+ %td= truncate(order.note, length: 25, tooltip: true)
%td= link_to t('.action_end'), finish_order_path(order),
data: {confirm: t('.confirm_end', order: order.name)}, method: :post,
class: 'btn btn-small btn-success'
diff --git a/app/views/sessions/new.html.haml b/app/views/sessions/new.html.haml
index 76760654..5f147baf 100644
--- a/app/views/sessions/new.html.haml
+++ b/app/views/sessions/new.html.haml
@@ -6,6 +6,8 @@
- title t('.title')
+.lead= FoodsoftConfig[:name]
+
%noscript
.alert.alert-error
!= t '.nojs', link: link_to(t('.noscript'), "http://noscript.net/")
diff --git a/app/views/shared/_open_orders.html.haml b/app/views/shared/_open_orders.html.haml
index 80e4621f..cef00797 100644
--- a/app/views/shared/_open_orders.html.haml
+++ b/app/views/shared/_open_orders.html.haml
@@ -9,7 +9,6 @@
%thead
%tr
%th= heading_helper Order, :name
- %th
%th= heading_helper Order, :pickup
%th= heading_helper Order, :ends
%th= t '.who_ordered'
@@ -18,23 +17,21 @@
- total = 0
- orders.each do |order|
%tr
- %td
- = link_to_ordering(order, show: true)
- %td
- .btn-small= link_to_ordering(order){ t 'ui.edit' }
+ %td= link_to_ordering(order)
%td= format_date(order.pickup) unless order.pickup.nil?
%td= format_time(order.ends) unless order.ends.nil?
- if group_order = order.group_order(ordergroup)
- total += group_order.price
%td= "#{show_user group_order.updated_by} (#{format_time(group_order.updated_on)})"
%td.numeric
- = number_to_currency(group_order.price)
+ = link_to_ordering(order, show: true) do
+ = number_to_currency(group_order.price)
- else
%td{:colspan => 2}
- if total > 0
%tfooter
%tr
- %th(colspan="4")
+ %th(colspan="3")
%th= t('.total_sum') + ':'
%th.numeric= number_to_currency(total)
- else
diff --git a/app/views/shared/_order_download_button.html.haml b/app/views/shared/_order_download_button.html.haml
index 2c362533..6890c3ca 100644
--- a/app/views/shared/_order_download_button.html.haml
+++ b/app/views/shared/_order_download_button.html.haml
@@ -10,4 +10,3 @@
- unless order.stockit?
%li= link_to t('.fax_txt'), order_path(order, format: :txt), {title: t('.download_file')}
%li= link_to t('.fax_csv'), order_path(order, format: :csv), {title: t('.download_file')}
- %li= link_to t('.custom_csv'), custom_csv_order_path(order), remote: true
diff --git a/config.ru b/config.ru
index f986eadb..eeab736b 100644
--- a/config.ru
+++ b/config.ru
@@ -1,6 +1,6 @@
# This file is used by Rack-based servers to start the application.
-require ::File.expand_path('../config/environment', __FILE__)
+require File.expand_path('config/environment', __dir__)
# https://gist.github.com/ebeigarts/5450422
map ENV.fetch('RAILS_RELATIVE_URL_ROOT', '/') do
diff --git a/config/app_config.yml.SAMPLE b/config/app_config.yml.SAMPLE
index e43705b6..b43b7935 100644
--- a/config/app_config.yml.SAMPLE
+++ b/config/app_config.yml.SAMPLE
@@ -32,6 +32,9 @@ default: &defaults
# custom foodsoft software URL (used in footer)
#foodsoft_url: https://github.com/foodcoops/foodsoft
+ # URL to redirect to after logging out
+ # logout_redirect_url: https://foodcoop.test
+
# Default language
#default_locale: en
# By default, foodsoft takes the language from the webbrowser/operating system.
@@ -90,6 +93,9 @@ default: &defaults
#use_wiki: true
#use_messages: true
+ # When enabled only administrators can access the member list.
+ #disable_members_overview: true
+
# Base font size for generated PDF documents
#pdf_font_size: 12
# Page size for generated PDF documents
@@ -167,6 +173,9 @@ default: &defaults
# default to allow automatically adding new articles on sync only when less than 200 articles in total
#shared_supplier_article_sync_limit: 200
+ # number of days after which attachment files get deleted
+ #attachment_retention_days: 365
+
development:
<<: *defaults
diff --git a/config/application.rb b/config/application.rb
index f76faa95..696d6647 100644
--- a/config/application.rb
+++ b/config/application.rb
@@ -29,12 +29,14 @@ module Foodsoft
# Internationalization.
config.i18n.load_path += Dir[Rails.root.join('config', 'locales', '*.yml')]
- config.i18n.available_locales = Pathname.glob(Rails.root.join('config', 'locales', '{??,???}{-*,}.yml')).map { |p| p.basename('.yml').to_s }
+ config.i18n.available_locales = Pathname.glob(Rails.root.join('config', 'locales', '{??,???}{-*,}.yml')).map do |p|
+ p.basename('.yml').to_s
+ end
config.i18n.default_locale = :en
config.i18n.fallbacks = [:en]
# Configure the default encoding used in templates for Ruby 1.9.
- config.encoding = "utf-8"
+ config.encoding = 'utf-8'
# Enable escaping HTML in JSON.
config.active_support.escape_html_entities_in_json = true
@@ -44,7 +46,7 @@ module Foodsoft
# like if you have constraints or database-specific column types
# config.active_record.schema_format = :sql
- # TODO Disable this. Uncommenting this line will currently cause rspec to fail.
+ # TODO: Disable this. Uncommenting this line will currently cause rspec to fail.
config.action_controller.permit_all_parameters = true
config.active_job.queue_adapter = :resque
@@ -68,21 +70,14 @@ module Foodsoft
config.autoloader = :zeitwerk
config.active_storage.variant_processor = :mini_magick
-
- # Ex:- :default =>''
-
- # CORS for API
- config.middleware.insert_before 0, Rack::Cors do
- allow do
- origins '*'
- # this restricts Foodsoft scopes to certain characters - let's discuss it when it becomes an actual problem
- resource %r{\A/[-a-zA-Z0-9_]+/api/v1/}, headers: :any, methods: :any
- end
- end
end
# Foodsoft version
VERSION = Rails.root.join('VERSION').read.strip
# Current revision, or +nil+
- REVISION = (Rails.root.join('REVISION').read.strip rescue nil)
+ REVISION = begin
+ Rails.root.join('REVISION').read.strip
+ rescue StandardError
+ nil
+ end
end
diff --git a/config/environments/production.rb b/config/environments/production.rb
index d08234e5..bb846bd7 100644
--- a/config/environments/production.rb
+++ b/config/environments/production.rb
@@ -1,4 +1,4 @@
-require "active_support/core_ext/integer/time"
+require 'active_support/core_ext/integer/time'
# Foodsoft production configuration.
#
@@ -51,7 +51,7 @@ Rails.application.configure do
# config.action_cable.allowed_request_origins = [ 'http://example.com', /http:\/\/example.*/ ]
# Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
- config.force_ssl = ENV["RAILS_FORCE_SSL"] != "false"
+ config.force_ssl = ENV['RAILS_FORCE_SSL'] != 'false'
# Include generic and useful information about system operation, but avoid logging too much
# information to avoid inadvertent exposure of personally identifiable information (PII).
@@ -97,9 +97,18 @@ Rails.application.configure do
config.action_mailer.smtp_settings[:domain] = ENV['SMTP_DOMAIN'] if ENV['SMTP_DOMAIN'].present?
config.action_mailer.smtp_settings[:user_name] = ENV['SMTP_USER_NAME'] if ENV['SMTP_USER_NAME'].present?
config.action_mailer.smtp_settings[:password] = ENV['SMTP_PASSWORD'] if ENV['SMTP_PASSWORD'].present?
- config.action_mailer.smtp_settings[:authentication] = ENV['SMTP_AUTHENTICATION'] if ENV['SMTP_AUTHENTICATION'].present?
- config.action_mailer.smtp_settings[:enable_starttls_auto] = ENV['SMTP_ENABLE_STARTTLS_AUTO'] == 'true' if ENV['SMTP_ENABLE_STARTTLS_AUTO'].present?
- config.action_mailer.smtp_settings[:openssl_verify_mode] = ENV['SMTP_OPENSSL_VERIFY_MODE'] if ENV['SMTP_OPENSSL_VERIFY_MODE'].present?
+ if ENV['SMTP_AUTHENTICATION'].present?
+ config.action_mailer.smtp_settings[:authentication] =
+ ENV['SMTP_AUTHENTICATION']
+ end
+ if ENV['SMTP_ENABLE_STARTTLS_AUTO'].present?
+ config.action_mailer.smtp_settings[:enable_starttls_auto] =
+ ENV['SMTP_ENABLE_STARTTLS_AUTO'] == 'true'
+ end
+ if ENV['SMTP_OPENSSL_VERIFY_MODE'].present?
+ config.action_mailer.smtp_settings[:openssl_verify_mode] =
+ ENV['SMTP_OPENSSL_VERIFY_MODE']
+ end
else
# Use sendmail as default to avoid ssl cert problems
config.action_mailer.delivery_method = :sendmail
@@ -112,7 +121,7 @@ Rails.application.configure do
# require 'syslog/logger'
# config.logger = ActiveSupport::TaggedLogging.new(Syslog::Logger.new 'app-name')
- if ENV["RAILS_LOG_TO_STDOUT"].present?
+ if ENV['RAILS_LOG_TO_STDOUT'].present?
logger = ActiveSupport::Logger.new(STDOUT)
logger.formatter = config.log_formatter
config.logger = ActiveSupport::TaggedLogging.new(logger)
diff --git a/config/environments/test.rb b/config/environments/test.rb
index 6ea4d1e7..5f6cef4d 100644
--- a/config/environments/test.rb
+++ b/config/environments/test.rb
@@ -1,4 +1,4 @@
-require "active_support/core_ext/integer/time"
+require 'active_support/core_ext/integer/time'
# The test environment is used exclusively to run your application's
# test suite. You never need to work with it otherwise. Remember that
@@ -14,12 +14,12 @@ Rails.application.configure do
# Eager loading loads your whole application. When running a single test locally,
# this probably isn't necessary. It's a good idea to do in a continuous integration
# system, or in some way before deploying your code.
- config.eager_load = ENV["CI"].present?
+ config.eager_load = ENV['CI'].present?
# Configure public file server for tests with Cache-Control for performance.
config.public_file_server.enabled = true
config.public_file_server.headers = {
- "Cache-Control" => "public, max-age=#{1.hour.to_i}"
+ 'Cache-Control' => "public, max-age=#{1.hour.to_i}"
}
# Show full error reports and disable caching.
diff --git a/config/importmap.rb b/config/importmap.rb
index f882664b..3ba2318b 100644
--- a/config/importmap.rb
+++ b/config/importmap.rb
@@ -2,3 +2,4 @@
pin "application", preload: true
pin "trix"
pin "@rails/actiontext", to: "actiontext.js"
+pin "trix-editor-overrides"
diff --git a/config/initializers/assets.rb b/config/initializers/assets.rb
index e1c4d5fa..d52cecaa 100644
--- a/config/initializers/assets.rb
+++ b/config/initializers/assets.rb
@@ -9,4 +9,4 @@ Rails.application.config.assets.version = '1.0'
# Precompile additional assets.
# application.js, application.css, and all non-JS/CSS in the app/assets
# folder are already added.
-Rails.application.config.assets.precompile += %w( application_legacy.js jquery.min.js )
+Rails.application.config.assets.precompile += %w[application_legacy.js jquery.min.js trix-editor-overrides.js]
diff --git a/config/initializers/cors.rb b/config/initializers/cors.rb
index e5a82f16..24ec0662 100644
--- a/config/initializers/cors.rb
+++ b/config/initializers/cors.rb
@@ -5,12 +5,10 @@
# Read more: https://github.com/cyu/rack-cors
-# Rails.application.config.middleware.insert_before 0, Rack::Cors do
-# allow do
-# origins "example.com"
-#
-# resource "*",
-# headers: :any,
-# methods: [:get, :post, :put, :patch, :delete, :options, :head]
-# end
-# end
+Rails.application.config.middleware.insert_before 0, Rack::Cors do
+ allow do
+ origins '*'
+ # this restricts Foodsoft scopes to certain characters - let's discuss it when it becomes an actual problem
+ resource %r{\A/[-a-zA-Z0-9_]+/api/v1/}, headers: :any, methods: :any
+ end
+end
diff --git a/config/initializers/currency_display.rb b/config/initializers/currency_display.rb
index 71d108d2..24ceeb8b 100644
--- a/config/initializers/currency_display.rb
+++ b/config/initializers/currency_display.rb
@@ -2,6 +2,7 @@
# have it shown in all other languages too
I18n.available_locales.each do |locale|
unless locale == I18n.default_locale
- I18n.backend.store_translations(locale, number: { currency: { format: { unit: nil } } })
+ I18n.backend.store_translations(locale,
+ number: { currency: { format: { unit: nil } } })
end
end
diff --git a/config/initializers/doorkeeper.rb b/config/initializers/doorkeeper.rb
index 83293820..d01c9a5f 100644
--- a/config/initializers/doorkeeper.rb
+++ b/config/initializers/doorkeeper.rb
@@ -100,7 +100,7 @@ Doorkeeper.configure do
# http://tools.ietf.org/html/rfc6819#section-4.4.2
# http://tools.ietf.org/html/rfc6819#section-4.4.3
#
- grant_flows %w(authorization_code implicit password)
+ grant_flows %w[authorization_code implicit password]
# Under some circumstances you might want to have applications auto-approved,
# so that the user skips the authorization step.
diff --git a/config/initializers/exception_notification.rb b/config/initializers/exception_notification.rb
index 10107865..3d342465 100644
--- a/config/initializers/exception_notification.rb
+++ b/config/initializers/exception_notification.rb
@@ -14,7 +14,7 @@ ExceptionNotification.configure do |config|
# Adds a condition to decide when an exception must be ignored or not.
# The ignore_if method can be invoked multiple times to add extra conditions.
- config.ignore_if do |exception, options|
+ config.ignore_if do |_exception, _options|
Rails.env.development? || Rails.env.test?
end
@@ -23,9 +23,9 @@ ExceptionNotification.configure do |config|
# Email notifier sends notifications by email.
if notification = FoodsoftConfig[:notification]
config.add_notifier :email, {
- :email_prefix => notification[:email_prefix],
- :sender_address => notification[:sender_address],
- :exception_recipients => notification[:error_recipients],
+ email_prefix: notification[:email_prefix],
+ sender_address: notification[:sender_address],
+ exception_recipients: notification[:error_recipients]
}
end
diff --git a/config/initializers/extensions.rb b/config/initializers/extensions.rb
index 68c7c8f4..d276aecb 100644
--- a/config/initializers/extensions.rb
+++ b/config/initializers/extensions.rb
@@ -2,7 +2,7 @@
class String
# remove comma from decimal inputs
def self.delocalized_decimal(string)
- if !string.blank? and string.is_a?(String)
+ if string.present? and string.is_a?(String)
BigDecimal(string.sub(',', '.'))
else
string
@@ -13,6 +13,6 @@ end
class Array
def cumulative_sum
csum = 0
- self.map { |val| csum += val }
+ map { |val| csum += val }
end
end
diff --git a/config/initializers/filter_parameter_logging.rb b/config/initializers/filter_parameter_logging.rb
index adc6568c..166997c5 100644
--- a/config/initializers/filter_parameter_logging.rb
+++ b/config/initializers/filter_parameter_logging.rb
@@ -3,6 +3,6 @@
# Configure parameters to be filtered from the log file. Use this to limit dissemination of
# sensitive information. See the ActiveSupport::ParameterFilter documentation for supported
# notations and behaviors.
-Rails.application.config.filter_parameters += [
- :passw, :secret, :token, :_key, :crypt, :salt, :certificate, :otp, :ssn
+Rails.application.config.filter_parameters += %i[
+ passw secret token _key crypt salt certificate otp ssn
]
diff --git a/config/initializers/rack.rb b/config/initializers/rack.rb
index 30970ec9..aa462561 100644
--- a/config/initializers/rack.rb
+++ b/config/initializers/rack.rb
@@ -1,3 +1,3 @@
# Increase key space for post request.
# Warning, this is dangerous. See http://stackoverflow.com/questions/12243694/getting-error-exceeded-available-parameter-key-space
-Rack::Utils.key_space_limit = 262144
+Rack::Utils.key_space_limit = 262_144
diff --git a/config/initializers/ruby_units.rb b/config/initializers/ruby_units.rb
index b8b56cca..af422fcb 100644
--- a/config/initializers/ruby_units.rb
+++ b/config/initializers/ruby_units.rb
@@ -2,28 +2,28 @@
if defined? RubyUnits
RubyUnits::Unit.redefine!('liter') do |unit|
- unit.aliases += %w{ltr}
+ unit.aliases += %w[ltr]
end
RubyUnits::Unit.redefine!('kilogram') do |unit|
- unit.aliases += %w{KG}
+ unit.aliases += %w[KG]
end
RubyUnits::Unit.redefine!('gram') do |unit|
- unit.aliases += %w{gr}
+ unit.aliases += %w[gr]
end
RubyUnits::Unit.define('piece') do |unit|
unit.definition = RubyUnits::Unit.new('1 each')
- unit.aliases = %w{pc pcs piece pieces} # locale: en
- unit.aliases += %w{st stuk stuks} # locale: nl
+ unit.aliases = %w[pc pcs piece pieces] # locale: en
+ unit.aliases += %w[st stuk stuks] # locale: nl
unit.kind = :counting
end
RubyUnits::Unit.define('bag') do |unit|
unit.definition = RubyUnits::Unit.new('1 each')
- unit.aliases = %w{bag bags blt sachet sachets} # locale: en
- unit.aliases += %w{zak zakken zakje zakjes} # locale: nl
+ unit.aliases = %w[bag bags blt sachet sachets] # locale: en
+ unit.aliases += %w[zak zakken zakje zakjes] # locale: nl
unit.kind = :counting
end
diff --git a/config/initializers/secret_token.rb b/config/initializers/secret_token.rb
index 4f01f173..fe62df4a 100644
--- a/config/initializers/secret_token.rb
+++ b/config/initializers/secret_token.rb
@@ -8,12 +8,12 @@ Foodsoft::Application.config.secret_key_base = begin
if (token = ENV.fetch('SECRET_KEY_BASE', nil)).present?
token
elsif Rails.env.production? || Rails.env.staging?
- raise "You must set SECRET_KEY_BASE"
+ raise 'You must set SECRET_KEY_BASE'
elsif Rails.env.test?
SecureRandom.hex(30) # doesn't really matter
else
sf = Rails.root.join('tmp', 'secret_key_base')
- if File.exists?(sf)
+ if File.exist?(sf)
File.read(sf)
else
puts "=> Generating initial SECRET_KEY_BASE in #{sf}"
diff --git a/config/initializers/session_store.rb b/config/initializers/session_store.rb
index d7841180..370a202e 100644
--- a/config/initializers/session_store.rb
+++ b/config/initializers/session_store.rb
@@ -3,7 +3,7 @@
module ActionDispatch
module Session
class SlugCookieStore < CookieStore
- alias_method :orig_set_cookie, :set_cookie
+ alias orig_set_cookie set_cookie
def set_cookie(request, session_id, cookie)
if script_name = FoodsoftConfig[:script_name]
diff --git a/config/initializers/simple_form_bootstrap.rb b/config/initializers/simple_form_bootstrap.rb
index a95278d0..1292ac83 100644
--- a/config/initializers/simple_form_bootstrap.rb
+++ b/config/initializers/simple_form_bootstrap.rb
@@ -11,7 +11,7 @@ SimpleForm.setup do |config|
end
end
- config.wrappers :prepend, tag: 'div', class: "control-group", error_class: 'error' do |b|
+ config.wrappers :prepend, tag: 'div', class: 'control-group', error_class: 'error' do |b|
b.use :html5
b.use :placeholder
b.use :label
@@ -24,7 +24,7 @@ SimpleForm.setup do |config|
end
end
- config.wrappers :append, tag: 'div', class: "control-group", error_class: 'error' do |b|
+ config.wrappers :append, tag: 'div', class: 'control-group', error_class: 'error' do |b|
b.use :html5
b.use :placeholder
b.use :label
diff --git a/config/initializers/time_formats.rb b/config/initializers/time_formats.rb
new file mode 100644
index 00000000..b0447b7e
--- /dev/null
+++ b/config/initializers/time_formats.rb
@@ -0,0 +1 @@
+Time::DATE_FORMATS[:foodsoft_datetime] = "%d.%m.%Y %H:%M"
diff --git a/config/initializers/zeitwerk.rb b/config/initializers/zeitwerk.rb
index 9c505a26..ede05b16 100644
--- a/config/initializers/zeitwerk.rb
+++ b/config/initializers/zeitwerk.rb
@@ -1,5 +1,4 @@
# config/initializers/zeitwerk.rb
ActiveSupport::Dependencies
.autoload_paths
- .delete("#{Rails.root}/app/controllers/concerns")
-
\ No newline at end of file
+ .delete(Rails.root.join('app/controllers/concerns').to_s)
diff --git a/config/locales/de.yml b/config/locales/de.yml
index d6254d84..b7f77c5d 100644
--- a/config/locales/de.yml
+++ b/config/locales/de.yml
@@ -568,7 +568,6 @@ de:
options:
convert_units: Derzeitige Einheiten beibehalten, berechne Mengeneinheit und Preis (wie Synchronisieren).
outlist_absent: Artikel löschen, die nicht in der hochgeladenen Datei sind.
- update_category: Kategorien aus der Datei übernehmen und erstellen.
sample:
juices: Säfte
nuts: Nüsse
@@ -656,6 +655,7 @@ de:
default_role_pickups: Abholtage
default_role_suppliers: Lieferanten
disable_invite: Einladungen deaktivieren
+ disable_members_overview: Mitgliederliste deaktivieren
email_from: Absenderadresse
email_replyto: Antwortadresse
email_sender: Senderadresse
@@ -1046,33 +1046,17 @@ de:
error_stale: In der Zwischenzeit hat jemand anderes auch bestellt, daher konnte die Bestellung nicht aktualisiert werden.
notice: Die Bestellung wurde gespeichert.
errors:
- balance_alert: Kontostand im Minus
closed: Diese Bestellung ist bereits abgeschlossen.
no_member: Du bist kein Mitglieder einer Bestellgruppe.
notfound: Fehlerhafte URL, das ist nicht Deine Bestellung.
- explanations:
- package_fill_level: |
- Gebindefüllstand
- missing_none: |
- Voll
- missing_few: |
- Wenig fehlt
- missing_many: |
- Viel fehlt
- title: Erklärungen
- tolerance_explained: |
- Zusätzliche Menge die du bestellen würdest, damit das Gebinde voll wird.
- tolerance: Toleranz
form:
action_save: Bestellung speichern
new_funds: Neuer Kontostand
price: Preis
- price_per_base_unit: Grundpreis
reset_article_search: Suche zurücksetzen
search_article: Artikel suchen...
sum_amount: Gesamtbestellmenge bisher
title: Bestellen
- sub_title: Bestellung für %{order_name} aufgeben
total_sum_amount: Gesamtbetrag
total_tolerance: Gesamt-Toleranz
units: Gebinde
@@ -1116,6 +1100,7 @@ de:
sum: Summe
title: Dein Bestellergebnis für %{order}
switch_order:
+ remaining: "noch %{remaining}"
title: Laufende Bestellungen
update:
error_general: Die Bestellung konnte nicht aktualisiert werden, da ein Fehler auftrat.
@@ -1231,6 +1216,8 @@ de:
js:
ordering:
confirm_change: Änderungen an dieser Bestellung gehen verloren, wenn zu einer anderen Bestellung gewechselt wird. Möchtest Du trotzdem wechseln?
+ trix_editor:
+ file_size_alert: Der Dateianhang ist zu groß! Die maximale Größe beträgt 512Mb
layouts:
email:
footer_1_separator: "--"
@@ -1480,9 +1467,6 @@ de:
units_ordered: Bestellte Einheiten
create:
notice: Die Bestellung wurde erstellt.
- custom_csv:
- description: Wähle die Attribute und deren Reihenfolge für die zu erzeugende CSV Datei
- column: Spalte
edit:
title: 'Bestellung bearbeiten: %{name}'
edit_amount:
@@ -1692,6 +1676,7 @@ de:
language:
de: Deutsch
es: Spanisch
+ tr: Türkisch
fr: Französisch
nl: Niederländisch
required:
@@ -1895,3 +1880,6 @@ de:
title: Arbeitsgruppen
update:
notice: Arbeitsgruppe wurde aktualisiert
+ time:
+ formats:
+ foodsoft_datetime: "%d.%m.%Y %H:%M"
diff --git a/config/locales/en.yml b/config/locales/en.yml
index ea65f309..b4f41c5c 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -569,7 +569,6 @@ en:
options:
convert_units: Keep current units, recompute unit quantity and price (like synchronize).
outlist_absent: Delete articles not in uploaded file.
- update_category: Create and replace categories from uploaded file.
sample:
juices: Juices
nuts: Nuts
@@ -657,6 +656,7 @@ en:
default_role_pickups: Pickup days
default_role_suppliers: Suppliers
disable_invite: Disable invites
+ disable_members_overview: Disable members list
email_from: From address
email_replyto: Reply-to address
email_sender: Sender address
@@ -1048,33 +1048,17 @@ en:
error_stale: Someone else has ordered in the meantime, couldn't update the order.
notice: The order was saved.
errors:
- balance_alert: Negative account balance
closed: This order is already closed.
no_member: You are not a member of an ordergroup.
notfound: Incorrect URL, this is not your order.
- explanations:
- title: Explanations
- tolerance: Tolerance
- package_fill_level: |
- Package Fill Level
- missing_none: |
- No more missing
- missing_few: |
- Few missing
- missing_many: |
- Many missing
- tolerance_explained: |
- Additional amount you would buy to fill a wholesale package
form:
action_save: Save order
new_funds: New account balance
price: Price
- price_per_base_unit: Base price
reset_article_search: Reset search
search_article: Search for articles...
sum_amount: Current amount
title: Orders
- sub_title: Place order for %{order_name}
total_sum_amount: Total amount
total_tolerance: Total tolerance
units: Units
@@ -1118,6 +1102,7 @@ en:
sum: Sum
title: Your order result for %{order}
switch_order:
+ remaining: "%{remaining} remaining"
title: Current orders
update:
error_general: The order couldn’t be updated due to a bug.
@@ -1234,6 +1219,8 @@ en:
js:
ordering:
confirm_change: Modifications to this order will be lost when you change the order. Do you want to lose the changes you made and continue?
+ trix_editor:
+ file_size_alert: The file is to large! The supported file size is 512Mb!
layouts:
email:
footer_1_separator: "--"
@@ -1490,9 +1477,6 @@ en:
units_ordered: Units ordered
create:
notice: The order was created.
- custom_csv:
- description: Please choose the order as well as the attributes for the csv file
- column: column
edit:
title: 'Edit order: %{name}'
edit_amount:
@@ -1646,7 +1630,6 @@ en:
who_ordered: Who ordered?
order_download_button:
article_pdf: Article PDF
- custom_csv: Custom CSV
download_file: Download file
fax_csv: Fax CSV
fax_pdf: Fax PDF
@@ -1714,6 +1697,7 @@ en:
es: Spanish
fr: French
nl: Dutch
+ tr: Turkish
required:
mark: "*"
text: required
@@ -1923,3 +1907,6 @@ en:
title: Workgroups
update:
notice: Workgroup was updated
+ time:
+ formats:
+ foodsoft_datetime: "%Y-%m-%d %H:%M"
diff --git a/config/locales/es.yml b/config/locales/es.yml
index 1f594ead..6cacb564 100644
--- a/config/locales/es.yml
+++ b/config/locales/es.yml
@@ -515,7 +515,6 @@ es:
options:
convert_units: Mantener unidades actuales, recomputar la cantidad y precio de unidades (como sincronizar).
outlist_absent: Borrar artículos que no están en el archivo subido.
- update_category: Toma las categorías del archivo subido.
sample:
juices: Jugos
nuts: Nueces
@@ -581,6 +580,7 @@ es:
custom_css: CSS adicional
default_locale: Idioma por defecto
disable_invite: Desactivar invitaciones
+ disable_members_overview: Desactivar la lista de miembros
email_from: Dirección de email de origen
email_replyto: Dirección reply-to
email_sender: Dirección del remitente
@@ -930,7 +930,6 @@ es:
action_save: Guardar pedido
new_funds: Nuevo balance de cuenta
price: Precio
- price_per_base_unit: Precio de base
reset_article_search: Reinicia la búsqueda
search_article: Busca artículos...
sum_amount: Cantidad actual
@@ -1081,6 +1080,8 @@ es:
js:
ordering:
confirm_change: Las modificaciones sobre este pedido se perderán cuando cambies el pedido. ¿Quieres perder los cambios que has hecho y continuar?
+ trix_editor:
+ file_size_alert: ¡El archivo adjunto es demasiado grande! El tamaño máximo es de 512Mb
layouts:
email:
footer_4_help: 'Ayuda: %{url}'
@@ -1262,9 +1263,6 @@ es:
units_ordered: Unidades pedidas
create:
notice: Se ha creado el pedido
- custom_csv:
- description: Por favor elija el orden de los atributos así como los atributos para el archivo csv
- column: columna
edit:
title: 'Edita pedido: %{name}'
edit_amount:
@@ -1446,6 +1444,7 @@ es:
es: Español
fr: Francés
nl: Neerlandés
+ tr: Turco
required:
text: requerido
'yes': 'Sí'
@@ -1623,3 +1622,6 @@ es:
title: Grupos de trabajo
update:
notice: El grupo de trabajo se actualizó.
+ time:
+ formats:
+ foodsoft_datetime: "%d/%b/%Y %H:%M"
diff --git a/config/locales/fr.yml b/config/locales/fr.yml
index 04dc03fc..cd0971da 100644
--- a/config/locales/fr.yml
+++ b/config/locales/fr.yml
@@ -418,6 +418,7 @@ fr:
zip_code: Code postal
currency_unit: Monnaie
name: Nom
+ disable_members_overview: Désactiver la liste des membres
distribution_strategy: Stratégie de distribution
distribution_strategy_options:
first_order_first_serve: Distribuez d'abord à ceux qui ont commandé en premier
@@ -678,7 +679,6 @@ fr:
action_save: Enregistrer ta commande
new_funds: Nouveau solde
price: Prix
- price_per_base_unit: Prix de base
reset_article_search: Réinitialiser la recherche
search_article: Rechercher des produits...
sum_amount: Quantité déjà commandée
@@ -831,6 +831,8 @@ fr:
js:
ordering:
confirm_change: Les changements apportés à cette commande vont être perdus. Est-ce que tu veux vraiment continuer?
+ trix_editor:
+ file_size_alert: Le fichier joint est trop volumineux ! La taille maximale est de 512Mb
layouts:
email:
footer_3_homepage: 'Boufcoop: %{url}'
@@ -1012,9 +1014,6 @@ fr:
units_ordered: Unités commandées
create:
notice: La commande a bien été définie.
- custom_csv:
- description: Veuillez choisir l'ordre des attributs ainsi que les attributs pour le fichier csv
- column: colonne
edit:
title: 'Modifier la commande: %{name}'
edit_amount:
@@ -1201,6 +1200,7 @@ fr:
es: Espagnol
fr: Français
nl: Néerlandais
+ tr: Turc
required:
text: requis
'yes': 'Oui'
@@ -1379,3 +1379,6 @@ fr:
title: Équipes
update:
notice: L'équipe a été mise à jour
+ time:
+ formats:
+ foodsoft_datetime: "%d/%m/%Y %H:%M"
diff --git a/config/locales/nl.yml b/config/locales/nl.yml
index dd41b666..d972c088 100644
--- a/config/locales/nl.yml
+++ b/config/locales/nl.yml
@@ -6,19 +6,19 @@ nl:
availability: Artikel leverbaar?
availability_short: leverb.
deposit: Statiegeld
- fc_price: Foodcoop prijs
- fc_price_desc: Prijs inclusief belasting, statiegeld en foodcoop marge.
- fc_price_short: FC prijs
- fc_share: Foodcoop marge
- fc_share_short: FC marge
- gross_price: Bruto prijs
+ fc_price: Foodcoop-prijs
+ fc_price_desc: Prijs inclusief belasting, statiegeld en foodcoop-marge.
+ fc_price_short: FC-prijs
+ fc_share: Foodcoop-marge
+ fc_share_short: FC-marge
+ gross_price: Brutoprijs
manufacturer: Producent
name: Naam
note: Notitie
order_number: Artikelnummer
order_number_short: Nr.
origin: Herkomst
- price: Netto prijs
+ price: Nettoprijs
supplier: Leverancier
tax: BTW
unit: Eenheid
@@ -26,11 +26,11 @@ nl:
unit_quantity_short: Colli
units: Eenheden
article_category:
- description: Import namen
+ description: Namen importeren
name: Naam
article_price:
deposit: Statiegeld
- price: Netto prijs
+ price: Nettoprijs
tax: BTW
unit_quantity: Colligrootte
bank_account:
@@ -69,7 +69,7 @@ nl:
financial_transaction_type:
bank_account: Bankrekening
name: Naam
- financial_transaction_class: Financiële transactie klasse
+ financial_transaction_class: Klasse financiële transactie
name_short: Verkorte naam
group_order:
ordergroup: Huishouden
@@ -89,7 +89,7 @@ nl:
created_at: Gemaakt op
created_by: Gemaakt door
date: Factuurdatum
- delete_attachment: Verwijder bijlage
+ delete_attachment: Bijlage verwijderen
deliveries: Voorraad levering
deposit: Statiegeld in rekening gebracht
deposit_credit: Statiegeld teruggekregen
@@ -102,7 +102,7 @@ nl:
supplier: Leverancier
mail_delivery_status:
created_at: Tijd
- email: Email
+ email: E-mail
message: Bericht
order:
boxfill: Dozen vullen na
@@ -111,8 +111,8 @@ nl:
end_action: Sluitingsactie
end_actions:
auto_close: Bestelling sluiten
- auto_close_and_send: Sluit de bestelling en verzend het naar de leverancier
- auto_close_and_send_min_quantity: Sluit de bestelling en verzend het naar de leverancier als de minimum bestelhoeveelheid gehaald is
+ auto_close_and_send: De bestelling sluiten en naar de leverancier verzenden
+ auto_close_and_send_min_quantity: De bestelling sluiten en naar de leverancier verzenden als de minimale bestelhoeveelheid gehaald is
no_end_action: Geen automatische actie
ends: Sluit op
name: Leverancier
@@ -124,10 +124,10 @@ nl:
transport: Vervoerskosten
transport_distribution: Verdeling van vervoerskosten
transport_distributions:
- articles: Verdeel de kosten over het aantal ontvangen artikelen
- ordergroup: Ieder huishouden betaald hetzelfde bedrag
- price: Verdeel de kosten over het orderbedrag
- skip: Verdeel de kosten niet
+ articles: De kosten over het aantal ontvangen artikelen verdelen
+ ordergroup: Ieder huishouden betaalt hetzelfde bedrag
+ price: De kosten over het orderbedrag verdelen
+ skip: De kosten niet verdelen
updated_by: Laatst aangepast door
order_article:
article: Artikel
@@ -141,7 +141,7 @@ nl:
units_to_order_short: Besteld
update_global_price: Huidige prijs overal bijwerken
order_comment:
- text: Commentaar voor deze bestelling toevoegen ...
+ text: Commentaar voor deze bestelling toevoegen…
ordergroup:
account_balance: Tegoed
available_funds: Beschikbaar tegoed
@@ -173,7 +173,7 @@ nl:
customer_number: Klantnummer
customer_number_short: Klantnr.
delivery_days: Bezorgdagen
- email: Email
+ email: E-mail
fax: Fax
iban: IBAN
is_subscribed: geabonneerd?
@@ -198,11 +198,11 @@ nl:
user_list: Verantwoordelijken
workgroup: Werkgroep
user:
- email: Email
+ email: E-mail
first_name: Voornaam
iban: IBAN
last_activity: Laatst actief
- last_login: Laatste login
+ last_login: Laatste aanmelding
last_name: Achternaam
name: Naam
nick: Gebruikersnaam
@@ -246,11 +246,11 @@ nl:
bank_transaction: Banktransactie
delivery: Levering
financial_transaction: Financiële transactie
- financial_transaction_class: Financiële transactie klasse
- financial_transaction_type: Financiële transactie type
+ financial_transaction_class: Klasse financiële transactie
+ financial_transaction_type: Type financiële transactie
invoice: Factuur
order: Bestelling
- order_article: Bestellingsartikel
+ order_article: Bestelartikel
order_comment: Commentaar
ordergroup:
one: Huishouden
@@ -269,8 +269,8 @@ nl:
all_users: Alle gebruikers
all_workgroups: Alle werkgroepen
created_at: gemaakt op
- first_paragraph: Hier kun je de groepen en gebruiker van Foodsoft beheren.
- groupname: Groepnaam
+ first_paragraph: Hier kun je de groepen en gebruikers van Foodsoft beheren.
+ groupname: Groepsnaam
members: leden
name: naam
new_ordergroup: Nieuw huishouden
@@ -290,14 +290,14 @@ nl:
submit: Opslaan
title: Configuratie
tab_layout:
- pdf_title: PDF documenten
+ pdf_title: PDF-documenten
tab_messages:
- emails_title: Emailinstellingen
+ emails_title: E-mailinstellingen
tab_payment:
schedule_title: Bestelrooster
tab_security:
default_roles_title: Toegang tot
- default_roles_paragraph: Ieder lid van de foodcoop heeft standaard toegang tot de volgende onderdelen.
+ default_roles_paragraph: "Ieder lid van de foodcoop heeft standaard toegang tot de volgende onderdelen:"
tab_tasks:
periodic_title: Periodieke taken
tabs:
@@ -308,29 +308,29 @@ nl:
finances:
index:
bank_accounts: Bankrekeningen
- first_paragraph: Hier kunt u de financiële transactieklassen en de bijbehorende financiële transactietypes beheren. Elke financiële transactie heeft een type, die je bij elke transactie moet selecteren, als je meer dan één type hebt gemaakt. De financiële transactieklassen kunnen worden gebruikt om de financiële transactietypes te groeperen en zullen worden weergegeven als extra kolommen in het rekeningoverzicht, als er meer dan één is gecreëerd.
+ first_paragraph: Hier kunt u de klassen van financiële transacties en de bijbehorende typen financiële transacties beheren. Elke financiële transactie heeft een type, die je bij elke transactie moet selecteren, als je meer dan één type hebt gemaakt. De klassen financiële transacties kunnen worden gebruikt om de types financiële transacties te groeperen en zullen worden weergegeven als extra kolommen in het rekeningoverzicht, als er meer dan één is gecreëerd.
new_bank_account: Nieuwe bankrekening toevoegen
- new_financial_transaction_class: Nieuwe financiële transactie klasse toevoegen
+ new_financial_transaction_class: Nieuwe klasse voor financiële transacties toevoegen
title: Financiën
- transaction_types: Financiële transactie typen
+ transaction_types: Typen financiële transacties
transaction_types:
name: Naam
- new_financial_transaction_type: Nieuw financiëel transactie type toevoegen
+ new_financial_transaction_type: Nieuw type financiële transactie toevoegen
financial_transaction_classes:
form:
- title_edit: Financiële transactie klasse bewerken
- title_new: Nieuw financiëel transactie type toevoegen
+ title_edit: Klasse voor financiële transactie bewerken
+ title_new: Nieuw type financiële transactie toevoegen
financial_transaction_types:
form:
- name_short_desc: De korte naam is verplicht voor financiële transactietypes die automatisch moeten kunnen worden toegewezen bij banktransacties. Als er meerdere bankrekeningen zijn, kan de voorkeursrekening voor bankoverschrijvingen worden geselecteerd.
- title_edit: Financiëel transactie type bewerken
- title_new: Nieuw financiëel transactie type toevoegen
+ name_short_desc: De korte naam is verplicht voor typen financiële transacties die automatisch moeten kunnen worden toegewezen bij banktransacties. Als er meerdere bankrekeningen zijn, kan de voorkeursrekening voor bankoverschrijvingen worden geselecteerd.
+ title_edit: Type financiële transactie bewerken
+ title_new: Nieuw type financiëel transactie toevoegen
mail_delivery_status:
destroy_all:
- notice: Alle emailproblemen zijn verwijderd
+ notice: Alle e-mailproblemen zijn verwijderd
index:
- destroy_all: Alle emailproblemen verwijderen
- title: Emailproblemen
+ destroy_all: Alle e-mailproblemen verwijderen
+ title: E-mailproblemen
ordergroups:
destroy:
error: 'Huishouden kon niet als verwijderd gemarkeerd worden: %{error}'
@@ -342,9 +342,9 @@ nl:
here: hier
index:
first_paragraph: Hier kun je %{url} toevoegen, bewerken en verwijderen.
- new_ordergroup: Nieuw huishouden
+ new_ordergroup: een nieuw huishouden
new_ordergroups: nieuwe huishoudens
- second_paragraph: 'Bedenk het onderscheid tussen werkgroep en huishouden: een huishouden heeft een rekening en kan bestellen. in een %{url} (bijv. sorteergroep) werken leden samen om taken te vervullen. Leden kunnen slechts lid zijn van éen huishouden, maar van meerdere werkgroepen.'
+ second_paragraph: 'Let op het onderscheid tussen werkgroep en huishouden: een huishouden heeft een rekening en kan bestellen; in een %{url} (bijv. sorteergroep) werken leden samen om taken te vervullen. Leden kunnen slechts lid zijn van één huishouden, maar van meerdere werkgroepen.'
title: Huishoudens
workgroup: werkgroep
new:
@@ -353,39 +353,39 @@ nl:
confirm: Weet je het zeker?
edit: Groep/leden bewerken
title: Huishouden %{name}
- search_placeholder: naam ...
+ search_placeholder: naam…
users:
controller:
- sudo_done: Je bent nu ingelogd als %{user}. Wees voorzichtig, en vergeet niet uit te loggen als je klaar bent!
+ sudo_done: Je bent nu aangemeld als %{user}. Wees voorzichtig, en vergeet niet af te melden als je klaar bent!
destroy:
error: 'Gebruiker kon niet verwijderd worden: %{error}'
notice: Gebruiker is verwijderd
edit:
title: Lid bewerken
form:
- create_ordergroup: Maak een huishouden met dezelfde naam en voeg een gebruiker toe.
- send_welcome_mail: Verstuur een welkomstmail naar de gebruiker.
+ create_ordergroup: Een huishouden met dezelfde naam aanmaken en een gebruiker toevoegen.
+ send_welcome_mail: Een welkomstmail naar de gebruiker versturen.
index:
first_paragraph: Hier kun je gebruikers %{url}, bewerken en wissen.
new_user: Nieuwe gebruiker
new_users: toevoegen
show_deleted: Verwijderde gebruikers tonen
- title: Gebruikers admin
+ title: Gebruikersbeheer
new:
title: Nieuwe gebruiker toevoegen
restore:
error: 'Gebruiker kon niet opnieuw actief gemaakt worden: %{error}'
notice: Gebruiker is opnieuw actief
show:
- confirm_sudo: Als je doorgaat, neem je de identiteit aan van gebruiker %{user}. Vergeet hierna niet uit te loggen!
+ confirm_sudo: Als je doorgaat, neem je de identiteit aan van gebruiker %{user}. Vergeet hierna niet af te melden!
groupabos: Groepslidmaatschappen
member_since: Lid sinds %{time}
person: Persoon
preference: Voorkeuren
- show_email_problems: Bekijk emailproblemen
- sudo: Inloggen als
+ show_email_problems: E-mailproblemen bekijken
+ sudo: Aanmelden als
users:
- show_email_problems: Bekijk emailproblemen
+ show_email_problems: E-mailproblemen bekijken
workgroups:
destroy:
error: 'Werkgroep kon niet verwijderd worden: %{error}'
@@ -400,7 +400,7 @@ nl:
new_workgroup: Nieuwe werkgroep
new_workgroups: nieuwe werkgroepen
ordergroup: huishouden
- second_paragraph: 'Let op het verschil tussen een groep en een huishouden: een %{url} heeft een tegoed en kan bestellen. In een werkgroep (bijv. ''sorteergroep'') organizeren zich de leden met behulp van taken en berichten. Gebruikers kunnen slechts lid zijn van één huishouden, maar van meerdere werkgroepen.'
+ second_paragraph: 'Let op het verschil tussen een groep en een huishouden: een %{url} heeft een tegoed en kan bestellen. In een werkgroep (bijv. ''sorteergroep'') organiseren zich de leden met behulp van taken en berichten. Gebruikers kunnen slechts lid zijn van één huishouden, maar van meerdere werkgroepen.'
title: Werkgroepen
new:
title: Werkgroep toevoegen
@@ -413,9 +413,9 @@ nl:
name: naam
application:
controller:
- error_authn: Inloggen vereist!
- error_denied: Je hebt geen toegang tot de gevraagde pagina. Als je denkt dat je dat wel zou moeten hebben, vraag dan een beheerder je die rechten te geven. Als je meerdere accounts hebt, wil je mogelijk %{sign_in}.
- error_denied_sign_in: inloggen als een andere gebruiker
+ error_authn: Aanmelden vereist!
+ error_denied: Je hebt geen toegang tot de gevraagde pagina. Als je denkt dat je dat wel zou moeten hebben, vraag dan een beheerder je die rechten te geven. Als je meerdere accounts hebt, wil je je mogelijk %{sign_in}.
+ error_denied_sign_in: aanmelden als een andere gebruiker
error_feature_disabled: Deze optie is momenteel niet actief.
error_members_only: Deze actie is alleen beschikbaar voor leden van de groep!
error_minimum_balance: Sorry, je tegoed is lager dan het minimum van %{min}.
@@ -429,7 +429,7 @@ nl:
title: Categorie bewerken
index:
new: Nieuwe categorie
- title: Categoriën
+ title: Categorieën
new:
title: Nieuwe categorie maken
update:
@@ -440,9 +440,9 @@ nl:
articles:
confirm_delete: Weet je zeker dat je alle artikelen wilt verwijderen?
option_available: Artikelen beschikbaar maken
- option_delete: Verwijder artikel
+ option_delete: Artikel verwijderen
option_not_available: Artikelen onbeschikbaar maken
- option_select: Kies actie ...
+ option_select: Actie kiezen…
price_netto: Prijs
unit_quantity_desc: Aantal eenheden per doos (colli)
unit_quantity_short: Colli
@@ -451,10 +451,10 @@ nl:
notice: "Er zijn %{count} nieuwe artikelen opgeslagen."
error_invalid: Er zijn artikelen die een fout hebben
error_nosel: Geen artikelen geselecteerd
- error_parse: "%{msg} ... in regel %{line}"
+ error_parse: "%{msg} … in regel %{line}"
error_update: 'Er trad een fout op bij het bijwerken van artikel ''%{article}'': %{msg}'
parse_upload:
- no_file: Kies een bestand om te uploaden.
+ no_file: Een bestand om te uploaden kiezen.
notice: "%{count} artikelen zijn geanalyseerd"
sync:
notice: Catalogus is bijgewerkt
@@ -472,7 +472,7 @@ nl:
drop: verwijderen
note: "%{article} is deel van een lopende bestelling en kan niet verwijderd worden. Het artikel graag eerst uit de bestelling(en) %{drop_link}."
edit_all:
- note: 'Verplichte velden zijn: Naam, eenheid, (netto) prijs en bestellingsnummer.'
+ note: 'Verplichte velden zijn: Naam, eenheid, (netto) prijs en bestelnummer.'
submit: Alle artikelen bijwerken
title: Alle artikelen van %{supplier} bewerken
warning: 'Let op, alle artikelen worden bijgewerkt!'
@@ -484,7 +484,7 @@ nl:
already_imported: geïmporteerd
not_found: Geen artikelen gevonden
index:
- change_supplier: Leverancier wisselen ...
+ change_supplier: Leverancier wisselen…
download: Artikelen downloaden
edit_all: Alles bewerken
ext_db:
@@ -497,14 +497,14 @@ nl:
title: Artikel importeren
new: Nieuw artikel
new_order: Nieuwe bestelling
- search_placeholder: Naam ...
+ search_placeholder: Naam…
title: Artikelen van %{supplier} (%{count})
upload: Artikelen uploaden
model:
error_in_use: "%{article} kan niet gewist worden, want deze is deel van een lopende bestelling!"
error_nosel: Je hebt geen artikelen geselecteerd
parse_upload:
- body: "
Ingelezen artikelen graag controleren.
Let op, momenteel vind er geen controle op dubbele artikelen plaats.
"
+ body: "
Ingelezen artikelen graag controleren.
Let op, momenteel vindt er geen controle op dubbele artikelen plaats.
"
submit: Upload verwerken
title: Artikelen uploaden
sync:
@@ -512,34 +512,33 @@ nl:
alert_used: Opgelet, %{article} wordt gebruikt in een lopende bestelling. Haal het eerst uit de bestelling.
body: 'De volgende artikelen zijn uit de lijst gehaald en worden verwijderd:'
body_ignored:
- one: Er is één artikel zonder artikelnummer overslagen.
+ one: Er is één artikel zonder artikelnummer overgeslagen.
other: "%{count} artikelen zonder artikelnummer zijn overgeslagen."
body_skip: Er zijn geen artikelen om te verwijderen.
- title: Uit de lijst halen ...
+ title: Uit de lijst halen…
price_short: prijs
submit: Alles synchroniseren
title: Artikelen met externe database synchroniseren
unit_quantity_short: Colli
update:
body: 'Ieder artikel wordt tweemaal getoond: oude waarden zijn grijs, en de tekstvelden bevatten de nieuwe waarden. Verschillen met de oude artikelen zijn geel gemarkeerd.'
- title: Bijwerken ...
+ title: Bijwerken…
update_msg:
- one: Er moet éen artikel bijgewerkt worden.
+ one: Er moet één artikel bijgewerkt worden.
other: "Er moeten %{count} artikelen bijgewerkt worden."
upnew:
body_count:
- one: Er is éen nieuw artikel.
+ one: Er is één nieuw artikel.
other: Er zijn %{count} nieuwe artikelen.
- title: Toevoegen ...
+ title: Toevoegen…
upload:
fields:
reserved: "(Leeg)"
status: Status (x=overslaan)
- file_label: Graag een compatibel bestand uitkiezen
+ file_label: Kies een compatibel bestand uit
options:
- convert_units: Bestaande eenheden behouden, herbereken groothandelseenheid en prijs (net als synchronizeren).
+ convert_units: Bestaande eenheden behouden, groothandelseenheid en prijs herberekenen (net als synchroniseren).
outlist_absent: Artikelen die niet in het bestand voorkomen, verwijderen.
- upload_category: Categorieën overnemen uit bestand.
sample:
juices: Sappen
nuts: Noten
@@ -550,21 +549,21 @@ nl:
tomato_juice: Tomatensap
walnuts: Walnoten
submit: Bestand uploaden
- text_1: 'Hier kun je een spreadsheet uploaden om de artikelen van %{supplier} bij te werken. Zowel Excel (xls, xlsx) als OpenOffice (ods) spreadsheets worden gelezen, evenals csv-bestanden (kolommen geschieden door ";", utf-8 encoding). Alleen de eerste sheet wordt geïmporteerd, en kolommen worden verwacht in deze volgorde:'
- text_2: De rijen hier getoond zijn voorbeelden. Een "x" in de eerste kolom geeft aan dat het artikel niet meer beschikbaar is en zal worden verwijderd. Hiermee kun je snel meerdere artikelen tegelijk verwijderen. De categorie wordt gematched met de Foodsoft categorielijst (zowel met de categorienaam als de bijbehorende importnamen).
+ text_1: 'Hier kun je een spreadsheet uploaden om de artikelen van %{supplier} bij te werken. Spreadsheets van zowel Excel (xls, xlsx) als OpenOffice (ods) worden gelezen, evenals csv-bestanden (kolommen gescheiden door ";", utf-8 encoding). Alleen de eerste sheet wordt geïmporteerd, en kolommen worden verwacht in deze volgorde:'
+ text_2: De rijen hier getoond zijn voorbeelden. Een “x” in de eerste kolom geeft aan dat het artikel niet meer beschikbaar is en zal worden verwijderd. Hiermee kun je snel meerdere artikelen tegelijk verwijderen. De categorie wordt vergeleken met de categorielijst van Foodsoft (zowel met de categorienaam als de bijbehorende importnamen).
title: Artikelen uploaden voor %{supplier}
bank_account_connector:
- confirm: Bevestig de code %{code}.
+ confirm: Code %{code} bevestigen.
fields:
- email: E-Mail
+ email: E-mail
pin: PIN
password: Wachtwoord
tan: TAN
username: Gebruikersnaam
config:
hints:
- applepear_url: Website waar het appelpunten systeem wordt uitgelegd.
- charge_members_manually: Kies deze optie als je elders bijhoudt wie welke producten heeft gekregen (bijvoorbeeld op papier), en dat ook niet naderhand in Foodsoft invoert. Na het afrekenen van bestellingen moet je dan iedere keer bij leden handmatig het in rekening te brengen bedrag afschrijven (gebruik "Nieuwe transacties toevoegen"). Het blijft wel nodig bestellingen af te rekenen, maar dat brengt dan niets in rekening bij leden.
+ applepear_url: Website waar het appelpuntensysteem wordt uitgelegd.
+ charge_members_manually: Kies deze optie als je elders bijhoudt wie welke producten heeft gekregen (bijvoorbeeld op papier), en dat ook niet naderhand in Foodsoft invoert. Na het afrekenen van bestellingen moet je dan iedere keer bij leden handmatig het in rekening te brengen bedrag afschrijven (gebruik “Nieuwe transacties toevoegen”). Het blijft wel nodig bestellingen af te rekenen, maar dat brengt dan niets in rekening bij leden.
contact:
email: Algemeen contactadres, zowel voor op de website als in formulieren.
street: Adres, meestal is dit het aflever- en ophaaladres.
@@ -627,6 +626,7 @@ nl:
default_role_pickups: Ophaaldagen
default_role_suppliers: Leveranciers
disable_invite: Uitnodigingen deactiveren
+ disable_members_overview: Ledenlijst deactiveren
email_from: From adres
email_replyto: Reply-to adres
email_sender: Sender adres
@@ -1018,7 +1018,6 @@ nl:
error_stale: In de tussentijd heeft iemand anders ook bestelt, daarom kon de bestelling niet bijgewerkt worden.
notice: Bestelling opgeslagen.
errors:
- balance_alert: Accountsaldo in het rood
closed: Deze bestelling is al gesloten.
no_member: Je bent geen lid van dit huishouden.
notfound: Foute URL, dit is niet jouw bestelling.
@@ -1026,12 +1025,10 @@ nl:
action_save: Bestelling opslaan
new_funds: Nieuw tegoed
price: Prijs
- price_per_base_unit: Basisprjis
reset_article_search: Alles tonen
search_article: Artikelen zoeken...
sum_amount: Huidig totaalbedrag
title: Bestellen
- sub_title: Plaats bestelling voor %{order_name}
total_sum_amount: Totalbedrag
total_tolerance: Totale tolerantie
units: Eenheden
@@ -1075,6 +1072,7 @@ nl:
sum: Som
title: Jouw bestelling voor %{order}
switch_order:
+ remaining: "nog %{remaining}"
title: Lopende bestellingen
update:
error_general: Er is een probleem opgetreden, de bestelling kon niet bijgewerkt worden.
@@ -1191,6 +1189,8 @@ nl:
js:
ordering:
confirm_change: Als je naar een andere bestelling gaat, gaan je aanpassingen in deze bestelling verloren. Wijzigingen vergeten en naar de andere bestelling gaan?
+ trix_editor:
+ file_size_alert: De bestandsbijlage is te groot! De maximale grootte is 512Mb!
layouts:
email:
footer_1_separator: "--"
@@ -1442,9 +1442,6 @@ nl:
units_ordered: Bestelde eenheden
create:
notice: De bestelling is aangemaakt.
- custom_csv:
- description: Kies de volgorde van de attributen en de attributen voor het csv-bestand
- column: kolom
edit:
title: 'Bestelling aanpassen: %{name}'
edit_amount:
@@ -1665,6 +1662,7 @@ nl:
es: Spaans
fr: Frans
nl: Nederlands
+ tr: Turks
required:
mark: "*"
text: verplicht
@@ -1874,3 +1872,6 @@ nl:
title: Werkgroepen
update:
notice: Werkgroep is bijgewerkt
+ time:
+ formats:
+ foodsoft_datetime: "%d-%m-%Y %H:%M"
diff --git a/config/locales/tr.yml b/config/locales/tr.yml
new file mode 100644
index 00000000..76408463
--- /dev/null
+++ b/config/locales/tr.yml
@@ -0,0 +1,1910 @@
+tr:
+ activerecord:
+ attributes:
+ article:
+ article_category: Kategori
+ availability: Ürün mevcut mu?
+ availability_short: mevcut.
+ deposit: Depozito
+ fc_price: FoodCoop fiyatı
+ fc_price_desc: Vergiler, depozito ve Foodcoop ücreti dahil fiyat.
+ fc_price_short: FC fiyatı
+ fc_share: FoodCoop marjı
+ fc_share_short: FC marjı
+ gross_price: Brüt fiyat
+ manufacturer: Üretici
+ name: Adı
+ note: Not
+ order_number: Sipariş numarası
+ order_number_short: Nr.
+ origin: Menşei
+ price: Fiyat (net)
+ supplier: Tedarikçi
+ tax: KDV
+ unit: Birim
+ unit_quantity: Birim miktarı
+ unit_quantity_short: B.M.
+ units: Birimler
+ article_category:
+ description: İthalat isimleri
+ name: Adı
+ article_price:
+ deposit: Depozito
+ price: Fiyat (net)
+ tax: KDV
+ unit_quantity: Birim miktarı
+ bank_account:
+ balance: Bakiye
+ bank_gateway: Banka geçidi
+ description: Açıklama
+ iban: IBAN
+ name: Adı
+ bank_gateway:
+ authorization: Yetkilendirme başlığı
+ name: Adı
+ unattended_user: Devre dışı bırakılmış kullanıcı
+ url: URL
+ bank_transaction:
+ amount: Tutar
+ date: Tarih
+ external_id: Harici ID
+ financial_link: Finansal bağlantı
+ iban: IBAN
+ reference: Referans
+ text: Açıklama
+ delivery:
+ date: Teslim tarihi
+ note: Not
+ supplier: Tedarikçi
+ document:
+ created_at: Oluşturulma tarihi
+ created_by: Oluşturan
+ data: Veri
+ mime: MIME tipi
+ name: Adı
+ financial_transaction:
+ amount: Tutar
+ created_on: Tarih
+ financial_transaction_class: Finansal işlem sınıfı
+ financial_transaction_type: Finansal işlem türü
+ note: Not
+ ordergroup: Sipariş grubu
+ user: Giren kullanıcı
+ financial_transaction_class:
+ ignore_for_account_balance: Hesap bakiyesi için yoksay
+ name: Adı
+ financial_transaction_type:
+ bank_account: Banka Hesabı
+ name: Adı
+ financial_transaction_class: Finansal işlem sınıfı
+ name_short: Kısa Adı
+ group_order:
+ ordergroup: Sipariş grubu
+ price: Sipariş tutarı
+ updated_by: Son siparişi veren
+ group_order_article:
+ ordered: Sipariş edildi
+ quantity: Miktar
+ received: Alındı
+ result: Sonuç
+ tolerance: Tolerans
+ total_price: Toplam
+ unit_price: Birim fiyatı
+ invoice:
+ amount: Tutar
+ attachment: Ek
+ created_at: Oluşturulma tarihi
+ created_by: Oluşturan
+ date: Fatura tarihi
+ delete_attachment: Eki sil
+ deliveries: Stok teslimatı
+ deposit: Tahsil edilen depozito
+ deposit_credit: İade edilen depozito
+ financial_link: Finansal bağlantı
+ net_amount: İade için düzeltilmiş tutar
+ note: Not
+ number: Numara
+ orders: Sipariş
+ paid_on: Ödendiği tarih
+ supplier: Tedarikçi
+ mail_delivery_status:
+ created_at: Tarih
+ email: E-posta
+ message: Mesaj
+ order:
+ boxfill: Kutuları doldurma tarihi
+ closed_by: Kapatıldı
+ created_by: Oluşturan
+ end_action: Otomatik kapanma eylemi
+ end_actions:
+ auto_close: Siparişi kapat
+ auto_close_and_send: Siparişi kapat ve tedarikçiye gönder
+ auto_close_and_send_min_quantity: Minimum miktarı karşılandığında siparişi kapat ve tedarikçiye gönder
+ no_end_action: Otomatik eylem yok
+ ends: Bitiş tarihi
+ name: Tedarikçi
+ note: Not
+ pickup: Teslim alma
+ starts: Başlangıç tarihi
+ status: Durum
+ supplier: Tedarikçi
+ transport: Taşıma maliyeti
+ transport_distribution: Taşıma maliyeti dağıtımı
+ transport_distributions:
+ articles: Alınan ürün sayısına göre maliyeti dağıt
+ ordergroup: Her sipariş grubu aynı tutarı öder
+ price: Sipariş tutarına göre maliyeti dağıt
+ skip: Maliyeti dağıtma
+ updated_by: Son düzenleyen
+ order_article:
+ article: Ürün
+ missing_units: Eksik birimler
+ missing_units_short: Eksik
+ quantity: Talep edilen miktar
+ quantity_short: Talep
+ units_received: Alınan birimler
+ units_received_short: Alınan
+ units_to_order: Sipariş edilen birimler
+ units_to_order_short: Sipariş edildi
+ update_global_price: Mevcut fiyatı tüm siparişlerde güncelle
+ order_comment:
+ text: Bu siparişe yorum ekle ...
+ ordergroup:
+ account_balance: Hesap bakiyesi
+ available_funds: Kredi limiti
+ break: "(Son) mola"
+ break_until: kadar
+ contact: İletişim
+ contact_address: Adres
+ contact_person: İlgili kişi
+ contact_phone: Telefon
+ description: Açıklama
+ ignore_apple_restriction: Elma puan sınırlamasını yok say
+ last_order: Son sipariş
+ last_user_activity: Son etkinlik
+ name: Adı
+ user_tokens: Üyeler
+ stock_article:
+ available: Mevcut
+ price: Fiyat
+ quantity: Stoktaki miktar
+ quantity_available: Mevcut miktar
+ quantity_available_short: Mevcut
+ quantity_ordered: Sipariş edilen miktar
+ stock_taking:
+ date: Tarih
+ note: Not
+ supplier:
+ address: Adres
+ contact_person: İlgili kişi
+ customer_number: Müşteri numarası
+ customer_number_short: Müşteri nr.
+ delivery_days: Teslimat günleri
+ email: E-posta
+ fax: Faks
+ iban: IBAN
+ is_subscribed: abone mi?
+ min_order_quantity: Minimum sipariş miktarı
+ min_order_quantity_short: Min. miktar
+ name: Adı
+ note: Not
+ order_howto: Nasıl sipariş verilir
+ phone: Telefon
+ phone2: Telefon 2
+ shared_sync_method: Nasıl senkronize edilir
+ url: Ana sayfa
+ supplier_category:
+ name: Adı
+ description: Açıklama
+ financial_transaction_class: Finansal işlem sınıfı
+ bank_account: Banka hesabı
+ task:
+ created_by: Oluşturan
+ created_on: Oluşturma tarihi
+ description: Açıklama
+ done: Yapıldı mı?
+ due_date: Bitiş tarihi
+ duration: Süre
+ name: Aktivite
+ required_users: Gereken kişi sayısı
+ user_list: Sorumlu kullanıcılar
+ workgroup: Çalışma grubu
+ user:
+ email: E-posta
+ first_name: İsim
+ iban: IBAN
+ last_activity: Son etkinlik
+ last_login: Son giriş
+ last_name: Soyadı
+ name: Adı
+ nick: Kullanıcı adı
+ ordergroup: Sipariş grubu
+ password: Şifre
+ password_confirmation: Şifreyi tekrarla
+ phone: Telefon
+ workgroup:
+ one: Çalışma grubu
+ other: Çalışma grupları
+ workgroup:
+ description: Açıklama
+ name: Adı
+ role_admin: Yönetim
+ role_article_meta: Ürün veritabanı
+ role_finance: Finans
+ role_invoices: Faturalar
+ role_orders: Sipariş yönetimi
+ role_pickups: Teslim günleri
+ role_suppliers: Tedarikçiler
+ user_tokens: Üyeler
+ errors:
+ has_many_left: Bu %{collection} ile hala ilişkili!
+ models:
+ article:
+ attributes:
+ name:
+ taken: isim zaten alınmış
+ taken_with_unit: isim ve birim zaten alınmış
+ supplier:
+ attributes:
+ shared_sync_method:
+ included: bu tedarikçi için geçerli bir seçenek değil
+ task:
+ attributes:
+ done:
+ exclusion: tamamlanmış görevler tekrarlanamaz
+ models:
+ article: Ürün
+ article_category: Kategori
+ bank_account: Banka hesabı
+ bank_gateway: Banka geçidi
+ bank_transaction: Banka işlemi
+ delivery: Teslimat
+ financial_transaction: Finansal işlem
+ financial_transaction_class: Finansal işlem sınıfı
+ financial_transaction_type: Finansal işlem türü
+ invoice: Fatura
+ order: Sipariş
+ order_article: Sipariş ürünü
+ order_comment: Sipariş yorumu
+ ordergroup:
+ one: Sipariş grubu
+ other: Sipariş grupları
+ stock_article: Stok ürünü
+ stock_taking: Stok sayımı
+ supplier: Tedarikçi
+ supplier_category: Tedarikçi kategorisi
+ task: Görev
+ user: Kullanıcı
+ workgroup: Çalışma grubu
+ admin:
+ access_to: Erişim sağla
+ base:
+ index:
+ all_ordergroups: Tüm sipariş grupları
+ all_users: Tüm kullanıcılar
+ all_workgroups: Tüm çalışma grupları
+ created_at: oluşturma tarihi
+ first_paragraph: Burada Foodsoft gruplarını ve kullanıcılarını yönetebilirsiniz.
+ groupname: grup adı
+ members: üyeler
+ name: adı
+ new_ordergroup: Yeni sipariş grubu
+ new_user: Yeni kullanıcı
+ new_workgroup: Yeni çalışma grubu
+ newest_groups: en yeni gruplar
+ newest_users: en yeni kullanıcılar
+ title: Yönetim
+ type: tür
+ username: kullanıcı adı
+ bank_accounts:
+ form:
+ title_edit: Banka hesabını düzenle
+ title_new: Yeni banka hesabı ekle
+ bank_gateways:
+ form:
+ title_edit: Banka geçidini düzenle
+ title_new: Yeni banka geçidi ekle
+ configs:
+ list:
+ key: Anahtar
+ title: Konfigürasyon listesi
+ value: Değer
+ show:
+ submit: Kaydet
+ title: Konfigürasyon
+ tab_layout:
+ pdf_title: PDF belgeleri
+ tab_messages:
+ emails_title: E-posta gönderimi
+ tab_payment:
+ schedule_title: Sipariş takvimi
+ tab_security:
+ default_roles_title: Erişim sağlanacak alanlar
+ default_roles_paragraph: Foodcoop üyesi herkes varsayılan olarak aşağıdaki alanlara erişime sahiptir.
+ tab_tasks:
+ periodic_title: Düzenli görevler
+ tabs:
+ title: Yapılandırma
+ update:
+ notice: Yapılandırma kaydedildi.
+ confirm: Emin misiniz?
+ finances:
+ index:
+ bank_accounts: Banka hesapları
+ first_paragraph: Burada finansal işlem sınıflarını ve ilgili finansal işlem türlerini yönetebilirsiniz. Her finansal işlemin bir türü vardır ve birden fazla tür oluşturduysanız, her işlemde seçmeniz gerekmektedir. Finansal işlem sınıfları, finansal işlem türlerini gruplamak için kullanılabilir ve birden fazla oluşturulmuşsa hesap özeti sayfasında ek sütunlar olarak gösterilir.
+ new_bank_account: Yeni banka hesabı ekle
+ new_financial_transaction_class: Yeni finansal işlem sınıfı ekle
+ new_bank_gateway: Yeni banka ağ geçidi ekle
+ title: Finanslar
+ transaction_types: Finansal işlem türleri
+ supplier_categories: Tedarikçi kategorileri
+ new_supplier_category: Yeni tedarikçi kategorisi
+ transaction_types:
+ name: İsim
+ new_financial_transaction_type: Yeni finansal işlem türü ekle
+ financial_transaction_classes:
+ form:
+ title_edit: Finansal işlem sınıfını düzenle
+ title_new: Yeni finansal işlem sınıfı ekle
+ financial_transaction_types:
+ form:
+ name_short_desc: Kısa isim, banka işlemlerinde otomatik olarak atanacak finansal işlem türleri için zorunludur. Birden fazla banka hesabı varsa, banka transferleri için tercih edilen hedef hesap seçilebilir.
+ title_edit: Finansal işlem türünü düzenle
+ title_new: Yeni finansal işlem türü ekle
+ mail_delivery_status:
+ destroy_all:
+ notice: Tüm e-posta problemleri silindi
+ index:
+ destroy_all: Tüm e-posta problemlerini sil
+ title: E-posta problemleri
+ ordergroups:
+ destroy:
+ error: 'Sipariş grubu silindi olarak işaretlenemedi: %{error}'
+ notice: Sipariş grubu silindi olarak işaretlendi
+ edit:
+ title: Sipariş grubunu düzenle
+ form:
+ first_paragraph: Yeni üyeleri %{url} davet edebilirsiniz.
+ here: buradan
+ index:
+ first_paragraph: Burada %{url} grupları ekleyebilir, düzenleyebilir veya silebilirsiniz.
+ new_ordergroup: Yeni sipariş grubu ekle
+ new_ordergroups: yeni sipariş grupları
+ second_paragraph: 'Grup ve sipariş grubu arasındaki farkı şöyle düşünün: Bir sipariş grubu bir hesaba sahiptir ve yiyecek siparişi verebilir. Bir %{url} (örneğin ''sınıflandırma grubu'') içindeki üyeler, görevler ve mesajlar yoluyla birbirleri arasında koordinasyon sağlar. Kullanıcılar sadece bir sipariş grubunda olabilir, ancak birden fazla çalışma grubunda olabilirler.'
+ title: Sipariş grupları
+ workgroup: çalışma grubu
+ new:
+ title: Yeni sipariş grubu oluştur
+ show:
+ confirm: Emin misiniz?
+ edit: Grup/Üyeleri Düzenle
+ title: Sipariş grubu %{name}
+ search_placeholder: isim ...
+ users:
+ controller:
+ sudo_done: Şimdi %{user} olarak giriş yaptınız. Dikkatli olun ve işiniz bittiğinde çıkış yapmayı unutmayın!
+ destroy:
+ error: 'Kullanıcı silinemedi: %{error}'
+ notice: Kullanıcı silindi
+ edit:
+ title: Kullanıcıyı Düzenle
+ form:
+ create_ordergroup: Aynı adı taşıyan bir sipariş grubu oluşturun ve kullanıcıyı ekleyin.
+ send_welcome_mail: Kullanıcıya hoş geldiniz e-postası gönderin.
+ index:
+ first_paragraph: Burada %{url}, düzenleyebilir ve silebilirsiniz.
+ new_user: Yeni kullanıcı oluşturabilir
+ new_users: yeni oluştur
+ show_deleted: Silinmiş kullanıcıları göster
+ title: Kullanıcı Yönetimi
+ new:
+ title: Yeni kullanıcı oluştur
+ restore:
+ error: 'Kullanıcı geri yüklenemedi: %{error}'
+ notice: Kullanıcı geri yüklendi
+ show:
+ confirm_sudo: Devam ederseniz, %{user} kimliğine bürüneceksiniz. İşiniz bittiğinde çıkış yapmayı unutmayın!
+ groupabos: Grup abonelikleri
+ member_since: Üye %{time} tarihinden bu yana
+ person: Kişi
+ preference: Tercihler
+ show_email_problems: E-posta sorunlarını göster
+ sudo: Kimliği kullanarak giriş yap
+ users:
+ show_email_problems: E-posta sorunlarını göster
+ workgroups:
+ destroy:
+ error: 'Çalışma grubu silinemedi: %{error}'
+ notice: Çalışma grubu silindi
+ edit:
+ title: Çalışma grubunu düzenle
+ form:
+ first_paragraph: Yeni üyeleri %{url} davet edebilirsiniz.
+ here: buradan
+ index:
+ first_paragraph: Burada %{url} oluşturabilir, düzenleyebilir ve silebilirsiniz.
+ new_workgroup: Yeni çalışma grubu oluştur
+ new_workgroups: yeni çalışma grupları
+ ordergroup: sipariş grubu
+ second_paragraph: 'Çalışma grubu ve sipariş grubu arasındaki farkı dikkate alın: bir %{url} hesabı vardır ve yemek siparişi verebilir. Bir çalışma grubunda (örneğin ''sınıflandırma grubu''), üyeler görevler ve mesajlar aracılığıyla birbirleri arasında koordinasyon sağlarlar. Kullanıcılar yalnızca bir sipariş grubunda olabilir, ancak birden fazla çalışma grubunda olabilirler.'
+ title: Çalışma Grupları
+ new:
+ title: Yeni çalışma grubu oluştur
+ show:
+ confirm: Emin misiniz?
+ edit: Grubu/kullanıcıları düzenle
+ title: Çalışma Grubu %{name}
+ workgroups:
+ members: üyeler
+ name: isim
+ supplier_categories:
+ form:
+ title_new: Tedarikçi kategorisi ekle
+ title_edit: Tedarikçi kategorisi düzenle
+ application:
+ controller:
+ error_authn: Kimlik doğrulama gerekiyor!
+ error_denied: İstenen sayfayı görüntülemeye yetkiniz yok. İlgili izinlere sahip olmanız gerektiğini düşünüyorsanız bir yöneticiye başvurun. Birden fazla kullanıcı hesabına erişiminiz varsa, %{sign_in} deneyin.
+ error_denied_sign_in: başka bir kullanıcı olarak oturum açmayı
+ error_feature_disabled: Bu özellik şu anda devre dışı bırakılmış durumda.
+ error_members_only: Bu eylem, yalnızca grubun üyeleri tarafından kullanılabilir!
+ error_minimum_balance: Maalesef hesap bakiyeniz %{min} minimumunun altında.
+ error_token: Erişim reddedildi (geçersiz belirteç)!
+ article_categories:
+ create:
+ notice: Kategori kaydedildi
+ destroy:
+ error: 'Kategori silinemiyor: %{message}'
+ edit:
+ title: Kategori düzenleme
+ index:
+ new: Yeni kategori ekle
+ title: Ürün kategorileri
+ new:
+ title: Yeni kategori ekleme
+ update:
+ notice: Kategori güncellendi
+ articles:
+ article:
+ last_update: 'son güncelleme: %{last_update} | brüt: %{gross_price}'
+ articles:
+ confirm_delete: Seçilen ürünleri gerçekten silmek istiyor musunuz?
+ option_available: Ürünleri uygun hale getir
+ option_delete: Ürünü sil
+ option_not_available: Ürünleri uygun değil yap
+ option_select: Bir eylem seçin ...
+ price_netto: Fiyat
+ unit_quantity_desc: Birim miktarı
+ unit_quantity_short: B.M.
+ controller:
+ create_from_upload:
+ notice: "%{count} yeni ürün kaydedildi."
+ error_invalid: Ürünlerde hatalar var
+ error_nosel: Seçilmiş bir ürün yok
+ error_parse: "%{msg} ... satır %{line}'da"
+ error_update: '%{article} ürünleri güncellerken bir hata oluştu: %{msg}'
+ parse_upload:
+ no_file: Lütfen yüklemek için bir dosya seçin.
+ notice: "%{count} ürün başarıyla analiz edildi."
+ sync:
+ notice: Katalog güncel
+ shared_alert: "%{supplier} harici bir veritabanına bağlı değil"
+ update_all:
+ notice: Tüm ürünler ve fiyatlar güncellendi.
+ update_sel:
+ notice_avail: Tüm seçili ürünler uygun olarak ayarlandı.
+ notice_destroy: Tüm seçili ürünler silindi.
+ notice_noaction: Hiçbir işlem belirtilmedi!
+ notice_unavail: Tüm seçili ürünler uygun değil olarak ayarlandı.
+ update_sync:
+ notice: Tüm ürünler ve fiyatlar güncellendi.
+ destroy_active_article:
+ drop: sil
+ note: "%{article} mevcut siparişlerde kullanılıyor ve silinemez. Lütfen önce ... ürünleri siparişlerden %{drop_link} kaldırın."
+ edit_all:
+ note: 'Zorunlu alanlar: ad, birim, (net) fiyat ve sipariş numarası.'
+ submit: Tüm ürünleri güncelle
+ title: "%{supplier} tedarikçisinin tüm ürünleri düzenle"
+ warning: 'Uyarı: tüm ürünler güncellenecek!'
+ form:
+ title_edit: Ürün düzenle
+ title_new: Yeni ürün ekle
+ import_search_results:
+ action_import: İçe aktar
+ already_imported: içe aktarıldı
+ not_found: Ürün bulunamadı
+ index:
+ change_supplier: Tedarikçi değiştir ...
+ download: Ürünleri indir
+ edit_all: Tümünü düzenle
+ ext_db:
+ import: Ürünü içe aktar
+ sync: Senkronize et
+ import:
+ category: Doğrudan kategoriye aktar
+ placeholder: Ad ile arama yapın ...
+ restrict_region: Sadece bölgeye özgü hale getir
+ title: Ürünü içe aktar
+ new: Yeni ürün
+ new_order: Yeni sipariş oluştur
+ search_placeholder: Ad ...
+ title: "%{supplier} ürünleri (%{count})"
+ upload: Ürünleri yükle
+ model:
+ error_in_use: "%{article}, bir mevcut siparişin parçası olduğu için silinemiyor!"
+ error_nosel: Hiçbir ürün seçmediniz
+ parse_upload:
+ body: "
Lütfen ürünleri doğrulayın.
Dikkat, tekrar eden ürünler için şu anda herhangi bir kontrol yapılmıyor.
"
+ submit: Yüklemeyi işle
+ title: Ürünleri yükle
+ sync:
+ outlist:
+ alert_used: Uyarı, %{article} açık bir siparişte kullanılıyor. Lütfen önce siparişten kaldırın.
+ body: 'Aşağıdaki ürünler listeden çıkarıldı ve silinecek:'
+ body_ignored:
+ one: Sipariş numarası olmayan bir ürün atlandı.
+ other: "Sipariş numarası olmayan %{count} ürün atlandı."
+ body_skip: Silinecek ürün yok.
+ title: Listeden çıkar ...
+ price_short: Fiyat
+ submit: Tümünü senkronize et
+ title: Harici veritabanıyla ürünleri senkronize et
+ unit_quantity_short: Birim miktarı
+ update:
+ body: 'Her ürün iki kez gösterilir: eski değerler gri, metin alanları ise güncellenmiş değerler içerir. Eski ürünlerle farklılıklar sarı renkle işaretlenmiştir.'
+ title: Güncelle ...
+ update_msg:
+ one: Bir ürün güncellenmesi gerekiyor.
+ other: "%{count} ürün güncellenmesi gerekiyor."
+ upnew:
+ body_count:
+ one: Bir yeni ürün eklemek için.
+ other: Eklemek için %{count} ürün var.
+ title: Yeni ekle ...
+ upload:
+ fields:
+ reserved: "(Ayrılmış)"
+ status: Durum (x=atla)
+ file_label: Lütfen uyumlu bir dosya seçin
+ options:
+ convert_units: Mevcut birimleri koruyun, birim miktarını ve fiyatı yeniden hesaplayın (senkronize gibi).
+ outlist_absent: Yüklenen dosyada olmayan ürünleri sil.
+ sample:
+ juices: Meyve suları
+ nuts: Kuruyemişler
+ organic: Organik
+ supplier_1: Kuruyemişçi
+ supplier_2: Kahverengi tarladan
+ supplier_3: Yeşil tarladan
+ tomato_juice: Domates suyu
+ walnuts: Cevizler
+ submit: Dosyayı yükle
+ text_1: '%{supplier} ürünlerini güncellemek için bir elektronik tablo yükleyebilirsiniz. Excel (xls, xlsx) ve OpenOffice (ods) tabloları kabul edilir, virgülle ayrılmış dosyalar da kabul edilir (csv, utf-8 kodlamalı "; " ile ayrılmış sütunlar). Sadece ilk sayfa içe aktarılacak ve sütunlar aşağıdaki sıraya göre olmalıdır:'
+ text_2: Burada gösterilen satırlar örneklerdir. İlk sütunda "x" olduğunda, ürün listeden çıkarılır ve silinir. Bu, örneğin tedarikçiyle ürünler müsait olmadığında birçok ürünü hızlı bir şekilde kaldırmak için elektronik tabloyu düzenlemenize ve çıkarmanıza izin verir. Kategori, Foodsoft kategori listenize eşleştirilecek (hem kategori adı hem de içe aktarma adlarıyla).
+ title: "%{supplier} ürünlerini yükle"
+ bank_account_connector:
+ confirm: Lütfen %{code} kodunu onaylayın.
+ fields:
+ email: E-Posta
+ pin: PIN
+ password: Şifre
+ tan: TAN
+ username: Kullanıcı adı
+ config:
+ hints:
+ applepear_url: Görevler için kullanılan elma ve armut sisteminin açıklandığı web sitesi.
+ charge_members_manually: Üyelerin ne aldığını başka bir yerde takip ettiğinizde (örneğin kağıt üzerinde), bunu Foodsoft'a girmek istemezseniz, bunu seçin. Üye hesaplarını manuel olarak ücretlendirmeniz gerekecektir ("Yeni işlem ekle" kullanarak). Denge ekranında hala siparişleri uzlaştırmanız gerekecek, ancak üye hesaplarına ücret yansıtılmayacak.
+ contact:
+ email: Genel iletişim e-posta adresi, web sitesinde ve bazı formlarda gösterilir.
+ street: Adres, genellikle teslimat ve toplama noktanız olacaktır.
+ currency_space: Para birimi simgesinin ardından boşluk ekleyip eklemediğinizi belirtir.
+ currency_unit: Fiyatları görüntülemek için para birimi simgesi.
+ custom_css: Bu site'nin düzenini değiştirmek için, kaskatı stili (CSS) dilini kullanarak stil değişiklikleri yapabilirsiniz. Varsayılan stili kullanmak için boş bırakın.
+ email_from: E-postalar bu e-posta adresinden gönderilecek. Foodcoop'un iletişim adresini kullanmak için boş bırakın.
+ email_replyto: Foodsoft tarafından gönderilen e-postalardan farklı bir adresten yanıt almak istediğinizde bunu ayarlayın.
+ email_sender: E-postalar bu e-posta adresinden gönderilir. Gönderen e-posta adresinin etki alanının SPF kaydına web sunucusunun kaydedilmesi gerekebilir, böylece gönderilen e-postalar spam olarak sınıflandırılmaz.
+ help_url: Belgelendirme web sitesi.
+ homepage: Yiyecek kooperatifinizin web sitesi.
+ ignore_browser_locale: Kullanıcının henüz bir dil seçmediği zaman kullanıcının bilgisayarının dilini yoksayın.
+ minimum_balance: Üyeler, hesap bakiyelerinin bu miktarın üzerinde veya eşit olduğu durumlarda sadece sipariş verebilirler.
+ name: Yiyecek kooperatifinizin adı.
+ order_schedule:
+ boxfill:
+ recurr: Kutuları-doldurma aşamasının varsayılan başlama zamanı.
+ time: Siparişin başlangıç saati.
+ ends:
+ recurr: Varsayılan sipariş kapanma tarihi için plan.
+ time: Siparişlerin kapatılacağı varsayılan saat.
+ initial: Program bu tarihte başlar.
+ page_footer: Her sayfanın altında gösterilir. Tamamen devre dışı bırakmak için "boş" girin.
+ pdf_add_page_breaks:
+ order_by_articles: Her ürünü ayrı bir sayfada göster.
+ order_by_groups: Her sipariş grubunu ayrı bir sayfada göster.
+ pdf_font_size: PDF belgeleri için temel yazı tipi boyutu (standart 12'dir).
+ pdf_page_size: PDF belgeleri için sayfa boyutu, genellikle "A4" veya "zarf".
+ price_markup: Üyelerin toplam fiyatına eklenen yüzde.
+ stop_ordering_under: Üyeler sadece bu kadar elma puanı olduğunda sipariş verebilirler.
+ tasks_period_days: İki periyodik görev arasındaki gün sayısı (varsayılan olarak 7, yani bir hafta).
+ tasks_upfront_days: Periyodik görevleri kaç gün önceden planlamak istediğinize bağlı olarak değişir.
+ tax_default: Yeni ürünler için varsayılan KDV yüzdesi.
+ tolerance_is_costly: Üye toleransını maksimum dolduracak kadar sipariş edin (sadece son kutuyu dolduracak kadar ürün eklemek yerine). Açık siparişin toplam tutarına uygulanan tolerans da buna dahildir.
+ distribution_strategy: Bir sipariş alındıktan sonra ürünlerin nasıl dağıtılacağı.
+ use_apple_points: Elma puanı sistemi etkinleştirildiğinde, üyeler sipariş vermeye devam edebilmek için bazı görevleri yapmak zorundadırlar.
+ use_boxfill: Etkinleştirildiğinde, siparişin sonuna doğru, üyeler yalnızca toplam sipariş tutarını artırdığında siparişlerini değiştirebilirler. Bu, kalan kutuları doldurmaya yardımcı olur. Siparişler için bir kutuları-doldurma tarihi belirlemelisiniz.
+ use_iban: Etkinleştirildiğinde, tedarikçi ve kullanıcı uluslararası banka hesap numaralarını saklayabileceği ek bir alan sunar.
+ use_nick: Gerçek adlar yerine takma adları göster ve kullan. Bu seçeneği etkinleştirdiğinizde, her kullanıcının bir takma adı olup olmadığını kontrol edin.
+ use_self_service: Seçili dengeleme (balancing) işlevlerini üyeler kendileri kullanabilirler.
+ webstats_tracking_code: Web analitiği için takip kodu (Piwik veya Google analytics gibi). Takip etmek istemiyorsanız boş bırakın.
+ keys:
+ applepear_url: Elma sistemi yardım URL'si
+ charge_members_manually: Üyeleri manuel olarak şarj et
+ contact:
+ city: Şehir
+ country: Ülke
+ email: E-posta
+ phone: Telefon
+ street: Cadde/Sokak
+ zip_code: Posta kodu
+ currency_space: Boşluk ekle
+ currency_unit: Para birimi
+ custom_css: Özel CSS
+ default_locale: Varsayılan dil
+ default_role_article_meta: Ürünler
+ default_role_finance: Finans
+ default_role_invoices: Faturalar
+ default_role_orders: Siparişler
+ default_role_pickups: Alım günleri
+ default_role_suppliers: Tedarikçiler
+ disable_invite: Davetiyeleri devre dışı bırak
+ email_from: Adresinden
+ email_replyto: Yanıtlanacak adres
+ email_sender: Gönderen adresi
+ help_url: Belgeleme URL'si
+ homepage: Ana sayfa
+ ignore_browser_locale: Tarayıcı dilini yoksay
+ minimum_balance: Minimum bakiye
+ name: İsim
+ order_schedule:
+ boxfill:
+ recurr: Kutu doldurma sonrası
+ time: zaman
+ ends:
+ recurr: Sipariş sonu
+ time: zaman
+ initial: Program başlangıcı
+ page_footer: Sayfa altbilgisi
+ pdf_add_page_breaks: Sayfa atlamaları
+ pdf_font_size: Yazı tipi boyutu
+ pdf_page_size: Sayfa boyutu
+ price_markup: Foodcoop marjı
+ stop_ordering_under: Minimum elma puanı
+ tasks_period_days: Dönem
+ tasks_upfront_days: Önceden oluştur
+ tax_default: Varsayılan KDV
+ time_zone: Zaman dilimi
+ tolerance_is_costly: Tolerans maliyetlidir
+ distribution_strategy: Dağıtım stratejisi
+ distribution_strategy_options:
+ first_order_first_serve: İlk sipariş edenlere öncelik verin
+ no_automatic_distribution: Otomatik dağıtım yok
+ use_apple_points: Elma puanları kullan
+ use_boxfill: Kutuları-doldurma aşamasını kullan
+ use_iban: IBAN kullan
+ use_nick: Takma ad kullan
+ use_self_service: Kendi kendine (self service) hizmet kullan
+ webstats_tracking_code: Takip kodu
+ tabs:
+ applications: Uygulamalar
+ foodcoop: Foodcoop
+ language: Dil
+ layout: Düzen
+ list: Liste
+ messages: Mesajlar
+ others: Diğerleri
+ payment: Finans
+ security: Güvenlik
+ tasks: Görevler
+ deliveries:
+ add_stock_change:
+ how_many_units: 'Kaç birim (%{unit}) teslim edilecek? Stoğun adı: %{name}.'
+ create:
+ notice: Teslimat oluşturuldu. Lütfen fatura eklemeyi unutmayın!
+ destroy:
+ notice: Teslimat silindi.
+ edit:
+ title: Teslimatı düzenle
+ form:
+ confirm_foreign_supplier_reedit: Stok ürünü %{name} başarıyla kaydedildi. Ancak, bu teslimatın tedarikçisinden farklı bir tedarikçiye ait. Stok ürününü tekrar düzenlemek ister misiniz?
+ create_from_blank: Yeni ürün oluştur
+ create_stock_article: Stok ürünü oluştur
+ title_fill_quantities: 2. Teslimat miktarlarını belirle
+ title_finish_delivery: 3. Teslimatı tamamla
+ title_select_stock_articles: 1. Stok ürünlerini seç
+ index:
+ confirm_delete: Silmek istediğinizden emin misiniz?
+ new_delivery: '%{supplier} için yeni teslimat oluştur '
+ title: "%{supplier}/teslimatlar"
+ invoice_amount: Fatura tutarı
+ invoice_net_amount: Fatura net tutarı
+ new:
+ title: "%{supplier} için yeni teslimat"
+ show:
+ sum: Toplam
+ sum_diff: Brüt - fatura tutarı
+ sum_gross: Brüt toplam
+ sum_net: Net toplam
+ title: Teslimatı göster
+ title_articles: Ürünler
+ stock_article_for_adding:
+ action_add_to_delivery: Teslimata ekle
+ action_edit: Düzenle
+ action_other_price: Kopyala
+ stock_change_fields:
+ remove_article: Teslimattan çıkar
+ suppliers_overview: Tedarikçi genel bakış
+ update:
+ notice: Teslimat güncellendi.
+ documents:
+ order_by_articles:
+ filename: Sipariş %{name}-%{date} - ürünlere göre
+ title: '%{name} için ürünlere göre sıralanmış sipariş, %{date} tarihinde kapanmıştır'
+ order_by_groups:
+ filename: Sipariş %{name}-%{date} - gruba göre
+ sum: Toplam
+ title: '%{name} için gruba göre sıralanmış sipariş, %{date} tarihinde kapanmıştır'
+ order_fax:
+ filename: Sipariş %{name}-%{date} - Faks
+ rows:
+ - Sipariş Numarası
+ - Miktar
+ - Ad
+ - Birim miktarı
+ - Birim
+ - Birim fiyatı
+ - Ara toplam
+ total: Toplam
+ order_matrix:
+ filename: Sipariş %{name}-%{date} - sıralama matrisi
+ heading: Ürün genel bakışı (%{count})
+ title: '%{date} tarihinde kapatılan %{name} sipariş sıralama matrisi'
+ errors:
+ general: Bir problem oluştu.
+ general_again: Bir problem oluştu. Lütfen tekrar deneyin.
+ general_msg: 'Bir problem oluştu: %{msg}'
+ internal_server_error:
+ text1: Beklenmeyen bir hata oluştu. Özür dileriz!
+ text2: Bildirildi. Eğer sorun devam ederse, bize bildirin lütfen.
+ title: Dahili sunucu hatası
+ not_found:
+ text: Bu sayfa mevcut değil, üzgünüz!
+ title: Sayfa bulunamadı
+ feedback:
+ create:
+ notice: Geri bildiriminiz başarıyla gönderildi. Teşekkür ederiz!
+ new:
+ first_paragraph: Bir hata buldunuz mu? Önerileriniz mi var? Fikirleriniz mi? Geri bildirimlerinizi duymaktan mutluluk duyarız.
+ second_paragraph: Lütfen unutmayın, Foodsoft ekibi yalnızca yazılımın bakımından sorumludur. Foodcoop'unuzun organizasyonuyla ilgili sorularınız için uygun kişiye başvurmanız gerekmektedir.
+ send: Gönder
+ title: Geri Bildirim Ver
+ finance:
+ balancing:
+ close:
+ alert: 'Muhasebe yapılırken bir hata oluştu: %{message}'
+ notice: Sipariş başarıyla tamamlandı, hesap bakiyesi güncellendi.
+ close_all_direct_with_invoice:
+ notice: '%{count} sipariş tamamlandı.'
+ close_direct:
+ alert: 'Sipariş tamamlanamadı: %{message}'
+ notice: Sipariş tamamlandı.
+ confirm:
+ clear: Hesapla
+ first_paragraph: 'Sipariş tamamlandığında, tüm grup hesapları güncellenecektir. Hesaplar şu şekilde tahsil edilecektir:'
+ or_cancel: ya da muhasebeye geri dön
+ title: Siparişi tamamla
+ edit_note:
+ title: Sipariş notunu düzenle
+ edit_results_by_articles:
+ add_article: Ürün ekle
+ amount: Miktar
+ edit_transport: Taşıma masraflarını düzenle
+ gross: Brüt
+ net: Net
+ edit_transport:
+ title: Taşıma maliyetlerini dağıt
+ group_order_articles:
+ add_group: Grup ekle
+ total: Toplam maliyet
+ total_fc: Toplam (FC fiyat)
+ units: Birimler
+ index:
+ close_all_direct_with_invoice: Hepsini faturayla kapat
+ title: Kapatılan siparişler
+ invoice:
+ edit: Faturayı düzenle
+ invoice_amount: 'Fatura tutarı:'
+ invoice_date: 'Fatura tarihi:'
+ invoice_number: 'Fatura numarası:'
+ minus_refund_calculated: "- Tahsil edilen depozito:"
+ new: Yeni fatura oluştur
+ new_body: 'Bu sipariş için bir fatura oluştur:'
+ plus_refund_credited: "+ İade edilen depozito:"
+ refund_adjusted_amount: 'iade için düzeltilen tutar:'
+ new:
+ alert: Dikkat, sipariş zaten hesaba katılmış
+ articles_overview: Ürünlere genel bakışı
+ close_direct: Ödemeyi atla
+ close_direct_confirm: Üye hesaplarını ücretlendirmeden siparişi tamamla. Üye hesaplarını zaten manuel olarak borçlandırdıysanız veya gerçekten ne yaptığınızı biliyorsanız bunu yapın.
+ comment_on_transaction: Muhasebenize bir yorum ekleyebilirsiniz.
+ comments: Yorumlar
+ confirm_order: Siparişi tamamla
+ create_invoice: Fatura ekle
+ edit_note: Notu düzenle
+ edit_order: Siparişi düzenle
+ groups_overview: Gruplara genel bakış
+ invoice: Fatura
+ notes_and_journal: Sipariş Notları
+ summary: Özet
+ title: Hesap defteri %{name}
+ view_options: Görüntüleme seçenekleri
+ order_article:
+ confirm: Emin misiniz?
+ orders:
+ clear: Hesapla
+ cleared: Hesaplandı (%{amount})
+ end: Son
+ ended: Kapatıldı
+ name: Tedarikçi
+ no_closed_orders: Şu anda kapatılmış bir sipariş yok.
+ state: Durum
+ summary:
+ changed: Veri değiştirildi!
+ duration: "%{starts} ile %{ends} arası"
+ fc_amount: 'Satış değeri:'
+ fc_profit: Foodcoop'tan artan (surplus)
+ gross_amount: 'Brüt değer:'
+ groups_amount: 'Sipariş grupları toplamı:'
+ net_amount: 'Net değer:'
+ reload: Özeti yeniden yükle
+ with_extra_charge: 'ek ücretle birlikte:'
+ without_extra_charge: 'ek ücretsiz:'
+ bank_accounts:
+ assign_unlinked_transactions:
+ notice: '%{count} işlem atanmıştır'
+ import:
+ notice: '%{count} yeni işlem içe aktarıldı'
+ no_import_method: Bu banka hesabı için içe aktarma yöntemi yapılandırılmamıştır.
+ submit: İçe aktar
+ title: '%{name} için banka işlemlerini içe aktar'
+ index:
+ title: Banka Hesapları
+ bank_transactions:
+ index:
+ assign_unlinked_transactions: İşlemleri Ata
+ import_transactions: İçe Aktar
+ title: '%{name} için Banka İşlemleri (%{balance})'
+ show:
+ add_financial_link: Finansal bağlantı ekle
+ belongs_to_supplier: tedarikçiye ait
+ belongs_to_user: kullanıcıya ait
+ in_ordergroup: sipariş grubunda
+ transactions:
+ add_financial_link: Bağlantı ekle
+ create:
+ notice: Fatura oluşturuldu.
+ financial_links:
+ add_bank_transaction:
+ notice: Bağlantı banka işlemine eklendi.
+ add_financial_transaction:
+ notice: Bağlantı finansal işleme eklendi.
+ add_invoice:
+ notice: Bağlantı faturaya eklendi.
+ create:
+ notice: Yeni finansal bağlantı oluşturuldu.
+ create_financial_transaction:
+ notice: Finansal işlem eklendi.
+ index_bank_transaction:
+ title: Banka işlemi ekle
+ index_financial_transaction:
+ title: Finansal işlem ekle
+ index_invoice:
+ title: Fatura ekle
+ new_financial_transaction:
+ title: Finansal işlem ekle
+ remove_bank_transaction:
+ notice: Bağlantı banka işleminden kaldırıldı.
+ remove_financial_transaction:
+ notice: Bağlantı finansal işlemden kaldırıldı.
+ remove_invoice:
+ notice: Bağlantı faturadan kaldırıldı.
+ show:
+ add_bank_transaction: Banka işlemi ekle
+ add_financial_transaction: Finansal işlem ekle
+ add_invoice: Fatura ekle
+ amount: Miktar
+ date: Tarih
+ description: Açıklama
+ new_financial_transaction: Yeni finansal işlem
+ title: Finansal bağlantı %{number}
+ type: Tip
+ financial_transactions:
+ controller:
+ create:
+ notice: İşlem kaydedildi.
+ create_collection:
+ alert: 'Bir hata oluştu: %{error}'
+ error_note_required: Not doldurulması gereklidir!
+ notice: Tüm işlemler kaydedildi.
+ destroy:
+ notice: İşlem kaldırıldı.
+ index:
+ balance: '%{balance} hesap bakiyesi'
+ last_updated_at: "(son güncelleme %{when} tarihinden önce)"
+ new_transaction: Yeni işlem oluştur
+ title: '%{name} için hesap özeti'
+ index_collection:
+ show_groups: Hesapları yönet
+ title: Finansal işlemler
+ new:
+ paragraph: Burada, %{name} için para yatırabilir veya çekebilirsiniz.
+ paragraph_foodcoop: Burada, gıda kooperatifi için para yatırabilir veya çekebilirsiniz.
+ title: Yeni işlem
+ new_collection:
+ add_all_ordergroups: Tüm sipariş gruplarını ekle
+ add_all_ordergroups_custom_field: '%{label} etiketi ile tüm sipariş gruplarını ekle'
+ create_financial_link: Yeni işlemler için ortak finansal bağlantı oluşturun.
+ create_foodcoop_transaction: Gıda kooperatifi için ters toplam tutarlı bir işlem oluşturun ("çift taraflı muhasebe" durumunda)
+ new_ordergroup: Yeni sipariş grubu ekle
+ save: İşlemi kaydet
+ set_balance: Sipariş grubunun bakiyesini girilen tutara ayarlayın.
+ sidebar: Burada aynı anda birden fazla hesabı güncelleyebilirsiniz. Örneğin, bir hesap özetinden tüm sipariş grubu transferlerini.
+ title: Birden fazla hesap güncelleme
+ ordergroup:
+ remove: Kaldır
+ remove_group: Grubu kaldır
+ transactions:
+ confirm_revert: '%{name} işlemi geri almak istediğinizden emin misiniz? Bu durumda, tersine çevrilen bir miktarla yeni bir işlem oluşturulacak ve orijinal işlemle birleştirilecektir. Bu gizli işlemler, "Gizli işlemleri göster" seçeneği aracılığıyla sadece görüntülenebilir ve normal kullanıcılara hiç görünmez.'
+ revert_title: Normal kullanıcılardan gizleyecek şekilde işlemi geri alın.
+ transactions_search:
+ show_hidden: Gizli işlemleri göster
+ index:
+ amount_fc: Tutar(FC)
+ end: Son
+ everything_cleared: Harika, her şey hesaplandı...
+ last_transactions: Son işlemler
+ open_transactions: Tamamlanmamış siparişler
+ show_all: tümünü göster
+ title: Finanslar
+ unpaid_invoices: Ödenmemiş faturalar
+ invoices:
+ edit:
+ title: Faturayı düzenle
+ form:
+ attachment_hint: Sadece JPEG ve PDF dosyaları kabul edilir.
+ index:
+ action_new: Yeni fatura oluştur
+ show_unpaid: Ödenmemiş faturaları göster
+ title: Faturalar
+ new:
+ title: Yeni fatura oluştur
+ show:
+ title: Fatura %{number}
+ unpaid:
+ invoices_sum: Toplam tutar
+ invoices_text: Referans
+ title: Ödenmemiş faturalar
+ ordergroups:
+ index:
+ new_financial_link: Yeni finansal bağlantı ekle
+ new_transaction: Yeni işlem ekle
+ show_all: Tüm işlemler
+ show_foodcoop: Gıda kooperatifi işlemleri
+ title: Hesapları yönet
+ ordergroups:
+ account_statement: Hesap özeti
+ new_transaction: Yeni işlem
+ update:
+ notice: Fatura güncellendi
+ foodcoop:
+ ordergroups:
+ index:
+ name: İsim ...
+ only_active: Sadece aktif gruplar
+ only_active_desc: "(son 3 ayda en az bir kez sipariş vermiş olanlar)"
+ title: Sipariş Grupları
+ ordergroups:
+ break: "%{start} - %{end}"
+ users:
+ index:
+ body: "
Burada Gıda Kooperatifinizin üyelerine bir mesaj yazabilirsiniz. Diğer üyelerin sizinle iletişim kurmasını isterseniz, bunu %{profile_link} bölümünden etkinleştirin.
"
+ ph_name: İsim ...
+ ph_ordergroup: Sipariş grubu ...
+ profile_link: seçenekler
+ title: Kullanıcılar
+ workgroups:
+ edit:
+ invite_link: burada
+ invite_new: Yeni üyeleri %{invite_link} davet edebilirsiniz.
+ title: Grubu Düzenle
+ index:
+ body: "
Bir grubu düzenlemek yalnızca grubun üyeleri tarafından yapılabilir. Bir gruba katılmak istiyorsanız, lütfen üyelere bir mesaj gönderin.
"
+ title: Çalışma Grupları
+ workgroup:
+ edit: Grubu Düzenle
+ show_tasks: Tüm Görevleri Göster
+ group_order_articles:
+ form:
+ amount_change_for: '%{article} için miktarı değiştirin'
+ result_hint: 'Birim: %{unit}'
+ group_orders:
+ archive:
+ desc: Tüm %{link} burada görüntüleyebilirsiniz.
+ open_orders: Mevcut siparişler
+ title: '%{group} Siparişleri'
+ title_closed: Hesaplandı
+ title_open: Hesaplanmadı/Kapatılmadı
+ create:
+ error_general: Sipariş hatası nedeniyle güncellenemedi.
+ error_stale: Başkası sipariş vermiş olabilir, sipariş güncellenemedi.
+ notice: Sipariş kaydedildi.
+ errors:
+ closed: Bu sipariş zaten kapatıldı.
+ no_member: Bir sipariş grubunun üyesi değilsiniz.
+ notfound: Yanlış URL, bu sizin siparişiniz değil.
+ form:
+ action_save: Siparişi kaydet
+ new_funds: Yeni hesap bakiyesi
+ price: Fiyat
+ reset_article_search: Arama sıfırla
+ search_article: Ürün ara...
+ sum_amount: Mevcut miktar
+ title: Siparişler
+ total_sum_amount: Toplam miktar
+ total_tolerance: Toplam tolerans
+ units: Birimler
+ units_full: Dolu birimler
+ units_total: Toplam birimler
+ index:
+ closed_orders:
+ more: daha fazla...
+ title: Kapanmış siparişler
+ finished_orders:
+ title: Unsettled orders
+ total_sum: Total sum
+ funds:
+ finished_orders: Tamamlanmamış siparişler
+ open_orders: Mevcut siparişler
+ title: Kredi
+ title: Siparişler genel bakışı
+ messages:
+ not_enough_apples: Sipariş vermek için en az %{stop_ordering_under} elma puanınız olmalıdır. Şu anda sipariş grubunuzda sadece %{apples} elma puanı var.
+ order:
+ title: Ürünler
+ show:
+ articles:
+ edit_order: Siparişi Düzenle
+ not_ordered_msg: Henüz sipariş vermediniz.
+ order_closed_msg: Maalesef, bu sipariş kapandı.
+ order_nopen_title: Tüm grupların güncel siparişleri göz önüne alındığında
+ order_not_open: Alındı
+ order_now: İşte şansın!
+ order_open: Mevcut
+ ordered: Sipariş edildi
+ ordered_title: Tutar + tolerans
+ show_hide: Sipariş edilmemiş ürünleri göster/gizle
+ show_note: Notu göster
+ title: Ürün genel bakışı
+ unit_price: Birim fiyatı
+ comment: Yorum
+ comments:
+ title: Yorumlar
+ not_ordered: Sipariş vermediniz.
+ sum: Toplam
+ title: '%{order} için sipariş sonucunuz'
+ switch_order:
+ remaining: "%{remaining} kaldı"
+ title: Mevcut siparişler
+ update:
+ error_general: Sipariş bir hatadan dolayı güncellenemedi.
+ error_stale: Bu sırada başka birisi sipariş vermiş, sipariş güncellenemedi.
+ notice: Sipariş kaydedildi.
+ helpers:
+ application:
+ edit_user: Kullanıcıyı düzenle
+ nick_fallback: "(kullanıcı adı yok)"
+ role_admin: Yönetici
+ role_article_meta: Ürünler
+ role_finance: Finans
+ role_invoices: Faturalar
+ role_orders: Siparişler
+ role_pickups: Teslimat günleri
+ role_suppliers: Tedarikçiler
+ show_google_maps: Google Haritalarda göster
+ sort_by: 'Şuna göre sırala: %{text}'
+ deliveries:
+ new_invoice: Yeni fatura
+ show_invoice: Faturayı göster
+ orders:
+ old_price: Eski fiyat
+ option_choose: Tedarikçi/Depo seçin
+ option_stock: Depo
+ order_pdf: PDF oluştur
+ submit:
+ invite:
+ create: davetiye gönder
+ tasks:
+ required_users: "%{count} üye daha gerekiyor!"
+ task_title: "%{name} (%{duration} saat)"
+ home:
+ apple_bar:
+ desc: 'Bu, sipariş grubunuzdaki tamamlanan görevlerin sipariş hacmi ile Foodcoop ortalaması arasındaki oranını gösterir. Uygulamada: Her %{amount} toplam sipariş için bir görev yapmalısınız!'
+ more_info: Daha fazla bilgi
+ points: 'Mevcut elma puanınız: %{points}'
+ warning: Uyarı, elma puanınız %{threshold} değerinden azsa, sipariş vermenize izin verilmez!
+ changes_saved: Değişiklikler kaydedildi.
+ index:
+ due_date_format: "%A %d %B"
+ my_ordergroup:
+ last_update: Son güncelleme %{when} tarihinden önce yapıldı
+ title: Benim sipariş grubum
+ transactions:
+ title: Son işlemler
+ view: Hesap özetini göster
+ ordergroup:
+ title: Sipariş grubunun katılımı
+ tasks_move:
+ action: Görevleri üstlen / görevleri reddet
+ desc: Bu görevlerden siz sorumlusunuz.
+ title: Görevleri üstlen
+ tasks_open:
+ title: Açık görevler
+ view_all: Tüm görevleri göster
+ title: Ana Sayfa
+ your_tasks: Görevleriniz
+ no_ordergroups: Maalesef bir sipariş grubu üyesi değilsiniz.
+ ordergroup:
+ account_summary: Hesap özeti
+ invite: Yeni kişi davet et
+ search: Ara ...
+ title: Benim sipariş grubum
+ ordergroup_cancelled: '%{group} grubundaki üyeliğinizi iptal ettiniz.'
+ profile:
+ groups:
+ cancel: Grubu terk et
+ cancel_confirm: Bu grubu terk etmek istediğinizden emin misiniz?
+ invite: Yeni üye davet et
+ title: Grup üyeliğiniz
+ title: Profilim
+ user:
+ since: "(%{when} üyesi)"
+ title: "%{user}"
+ reference_calculator:
+ transaction_types_headline: Amaç
+ placeholder: Bu işlem için kullanmanız gereken referansı görmek için önce lütfen her alan için aktarmak istediğiniz miktarları girin.
+ text0: Lütfen şu miktarı transfer edin
+ text1: referans numarası ile birlikte
+ text2: şu banka hesabına
+ title: Referans Hesaplayıcı
+ start_nav:
+ admin: Yönetim
+ finances:
+ accounts: Hesapları güncelle
+ settle: Hesap siparişleri
+ title: Finanslar
+ foodcoop: Gıda kooperatifi
+ members: Üyeler
+ new_ordergroup: Yeni sipariş grubu
+ new_user: Yeni üye
+ orders:
+ end: Siparişleri kapat
+ overview: Sipariş özeti
+ title: Siparişler
+ products:
+ edit: Ürünleri güncelle
+ edit_stock: Stokları güncelle
+ edit_suppliers: Tedarikçileri güncelle
+ title: Ürünler
+ tasks: Görevlerim
+ title: Direkt olarak...
+ invites:
+ errors:
+ already_member: kullanımda. Kişi zaten bu Foodcoop'un üyesi.
+ modal_form:
+ body: "
Burada, Foodcoop'un üyesi olmayan bir kişiyi <%{group}> gruplarına davet edebilirsiniz. Davet kabul edildikten sonra, kişi siparişinize ürün ekleyebilecek (ve kaldırabilecek).
Bu, birini foodcoop'a tanıtmak veya aynı evde birden fazla kişiyle sipariş vermeye yardımcı olmak için harika bir yoldur.
"
+ title: Kişi davet et
+ new:
+ action: Davet gönder
+ body: "
Burada, henüz Foodcoop üyesi olmayan bir kişiyi <%{group}> grubuna ekleyebilirsiniz.
"
+ success: Kullanıcı başarıyla davet edildi.
+ js:
+ ordering:
+ confirm_change: Bu siparişe yapılan değişiklikler kaybolacak. Değişikliklerinizi kaybetmek ve devam etmek istiyor musunuz?
+ trix_editor:
+ file_size_alert: Dosya eki çok büyük! Maksimum boyut 512Mb
+ layouts:
+ email:
+ footer_1_separator: "--"
+ footer_2_foodsoft: 'Foodsoft: %{url}'
+ footer_3_homepage: 'Foodcoop: %{url}'
+ footer_4_help: 'Yardım: %{url}'
+ foodsoft: Foodsoft
+ footer:
+ revision: revizyon %{revision}
+ header:
+ feedback:
+ desc: Bir hata mı buldunuz? Öneriler? Fikirler? İnceleme?
+ title: Geri bildirim
+ help: Yardım
+ logout: Çıkış yap
+ ordergroup: Benim sipariş grubum
+ profile: Profili düzenle
+ reference_calculator: Referans Hesaplayıcı
+ logo: "foodsoft"
+ lib:
+ render_pdf:
+ page: "%{count} sayfasının %{number}. sayfası"
+ login:
+ accept_invitation:
+ body: "
%{foodcoop} gıda kooperatifinin %{group} grubunun bir üyesi olarak davet edildiniz.
Katılmak isterseniz, lütfen bu formu doldurun.
Doğal olarak, kişisel bilgileriniz herhangi bir nedenle üçüncü taraflarla paylaşılmayacaktır. Tüm'ü, tüm Gıda Kooperatifleri üyeleri için görünür olacak şekilde kişisel bilgilerinizin ne kadarının görünür olacağını siz belirleyebilirsiniz. Lütfen not edin ki, yöneticiler bilgilerinize erişebilirler.
"
+ submit: Bir Foodsoft hesabı oluşturun
+ title: "%{name} için davet"
+ controller:
+ accept_invitation:
+ notice: Tebrikler, hesabınız başarıyla oluşturuldu. Şimdi giriş yapabilirsiniz.
+ error_group_invalid: Davet edildiğiniz grup artık mevcut değil.
+ error_invite_invalid: Davetiniz geçersiz (artık geçerli değil).
+ error_token_invalid: Geçersiz veya süresi dolmuş belirteç (token). Lütfen tekrar deneyin.
+ reset_password:
+ notice: Eğer e-postanız kayıtlıysa, şifrenizi sıfırlamak için bir bağlantı içeren bir mesaj alacaksınız. Spam klasörünüzü kontrol etmeniz gerekebilir.
+ update_password:
+ notice: Şifreniz güncellendi. Artık giriş yapabilirsiniz.
+ forgot_password:
+ body: "
Sorun değil, yeni bir şifre seçebilirsiniz.
Lütfen burada kayıtlı olan e-posta adresinizi girin. Daha fazla talimat için bir e-posta alacaksınız.
"
+ submit: Yeni şifre iste
+ title: Şifremi unuttum?
+ new_password:
+ body: "
%{user} için yeni şifreyi girin.
"
+ submit: Yeni şifreyi kaydet
+ title: Yeni şifre
+ mailer:
+ dateformat: "%d %b"
+ feedback:
+ header: "%{user} tarafından %{date} tarihinde yazıldı:"
+ subject: Foodsoft için geri bildirim
+ from_via_foodsoft: "%{name} Foodsoft aracılığıyla"
+ invite:
+ subject: Foodcoop Davetiyesi
+ text: |
+ Merhaba!
+
+ %{user} <%{mail}> seni "%{group}" grubuna katılmaya davet etti.
+ Davetiye kabul etmek ve foodcoop'a katılmak için lütfen bu bağlantıyı takip et: %{link}
+ Bu bağlantı sadece bir kez kullanılabilir ve %{expires} tarihinde süresi dolacaktır.
+
+
+ Sevgiler, Foodsoft Ekibi!
+ negative_balance:
+ subject: Negatif hesap bakiyesi
+ text: |
+ Sayın %{group},
+
+ Hesap bakiyeniz %{when} tarihinde yapılan %{amount} TL'lik işlem nedeniyle sıfırın altına düştü: "%{balance}"
+
+ "%{user}" tarafından "%{note}" için %{amount} ücret alındı.
+
+ Lütfen mümkün olan en kısa sürede hesabınıza para yatırınız.
+
+
+
+ %{foodcoop} adına saygılar.
+ not_enough_users_assigned:
+ subject: '"%{task}" için hala kişilere ihtiyaç var!'
+ text: |
+ Sevgili %{user},
+
+ Çalışma grubunun '%{task}' görevi %{when} tarihinde tamamlanacak
+ ve daha fazla katılımcıya ihtiyaç duyuyor!
+
+ Eğer henüz bu göreve atanmadıysanız, şimdi fırsatınız var:
+
+ %{workgroup_tasks_url}
+
+ Görevleriniz: %{user_tasks_url}
+ order_result:
+ subject: '%{name} siparişi kapatıldı'
+ text0: |
+ Sevgili %{ordergroup},
+
+ "%{order}" siparişi %{user} tarafından %{when} tarihinde kapatıldı.
+ text1: |
+ Tahmini olarak %{pickup} tarihinde teslim edilebilir.
+ text2: |
+ Sipariş grubunuz için aşağıdaki ürünler sipariş edildi:
+ text3: |-
+ o Toplam tutar: %{sum}
+
+ Siparişi çevrimiçi olarak görüntüleyebilirsiniz: %{order_url}
+
+
+ %{foodcoop} adına sevgiler.
+ order_received:
+ subject: '%{name} için sipariş teslimi kaydedildi'
+ text0: |
+ Sevgili %{ordergroup},
+
+ "%{order}" için sipariş teslimi kaydedilmiştir.
+ abundant_articles: Fazla alındı
+ scarce_articles: Az alındı
+ article_details: |
+ o %{name}:
+ -- Sipariş edilen: %{ordered} x %{unit}
+ -- Alınan: %{received} x %{unit}
+ order_result_supplier:
+ subject: '%{name} için yeni sipariş'
+ text: |
+ Merhaba!
+
+ %{foodcoop} Foodcoop'u sipariş vermek istiyor.
+
+ Lütfen ekli PDF ve hesap tablosunu inceleyiniz.
+
+ Saygılarımızla,
+ %{user}
+ %{foodcoop}
+ reset_password:
+ subject: '%{username} için yeni şifre'
+ text: |
+ Merhaba %{user},
+
+ Yeni bir şifre istediniz (veya başka birisi istedi).
+ Yeni bir şifre belirlemek için bu linke tıklayın: %{link}
+ Bu link sadece bir kez kullanılabilir ve %{expires} tarihinde geçersiz olacaktır.
+ Eğer şifrenizi değiştirmek istemiyorsanız, bu mesajı görmezden gelebilirsiniz. Şifreniz henüz değiştirilmedi.
+
+
+ Saygılarımızla, Foodsoft Ekibi!
+ upcoming_tasks:
+ nextweek: 'Gelecek hafta için görevler:'
+ subject: Görevler teslim edilmeli!
+ text0: |
+ Sayın %{user},
+
+ %{task} görevi size atanmıştır. Bu görev yarın (%{when}) teslim edilmelidir!
+ text1: |
+ Görevlerim: %{user_tasks_url}
+
+
+ %{foodcoop} adına saygılarımızla.
+ welcome:
+ subject: "%{foodcoop} Hoş Geldiniz"
+ text0: |
+ Sayın %{user},
+
+ %{foodcoop} için yeni bir Foodsoft hesabı oluşturuldu.
+ text1: |
+ Yeni bir şifre belirlemek için lütfen şu bağlantıyı takip edin: %{link}
+ Bu bağlantı sadece bir kez kullanılabilir ve %{expires} tarihinde geçerliliğini yitirir.
+ Her zaman "Şifrenizi mi unuttunuz?" seçeneğini kullanarak yeni bir bağlantı alabilirsiniz.
+
+
+ %{foodcoop} adına saygılarımızla.
+ messages_mailer:
+ foodsoft_message:
+ footer: |
+ Yanıtla: %{reply_url}
+ Mesajı çevrimiçi görüntüle: %{msg_url}
+ Mesaj seçenekleri: %{profile_url}
+ footer_group: |
+ Gruba gönderildi: %{group}
+ model:
+ delivery:
+ each_stock_article_must_be_unique: Her stok ürünü bir kez listelenmeli.
+ financial_transaction:
+ foodcoop_name: Gıda kooperatifi
+ financial_transaction_type:
+ no_delete_last: En az bir finansal işlem türü bulunmalıdır.
+ group_order:
+ stock_ordergroup_name: Stok (%{user})
+ invoice:
+ invalid_mime: geçersiz bir MIME türüne sahip (%{mime})
+ membership:
+ no_admin_delete: Son kalan yönetici olduğunuz için üyelikten çıkılamaz.
+ order_article:
+ error_price: belirtilmeli ve geçerli bir fiyata sahip olmalıdır
+ user:
+ no_ordergroup: sıfır sipariş grubu
+ group_order_article:
+ order_closed: Sipariş kapatıldı ve değiştirilemez.
+ navigation:
+ admin:
+ config: Konfigürasyon
+ finance: Finans
+ home: Genel Bakış
+ mail_delivery_status: E-posta sorunları
+ ordergroups: Sipariş Grupları
+ title: Yönetim
+ users: Kullanıcılar
+ workgroups: Çalışma Grupları
+ articles:
+ categories: Kategoriler
+ stock: Stok
+ suppliers: Tedarikçiler/ürünler
+ title: Ürünler
+ dashboard: Kontrol Paneli
+ finances:
+ accounts: Hesapları Yönet
+ balancing: Hesap siparişleri
+ bank_accounts: Banka Hesapları
+ home: Genel Bakış
+ invoices: Faturalar
+ title: Finanslar
+ foodcoop: Gıda Kooperatifi
+ members: Üyeler
+ ordergroups: Sipariş Grupları
+ orders:
+ archive: Benim Siparişlerim
+ manage: Siparişleri Yönet
+ ordering: Sipariş Ver!
+ pickups: Teslim Günleri
+ title: Siparişler
+ tasks: Görevler
+ workgroups: Çalışma Grupları
+ number:
+ percentage:
+ format:
+ strip_insignificant_zeros: true
+ order_articles:
+ edit:
+ stock_alert: Stok ürünlerinin fiyatı değiştirilemez!
+ title: Ürünü güncelle
+ new:
+ title: Teslim edilen ürünü siparişe ekle
+ ordergroups:
+ edit:
+ title: Sipariş gruplarını düzenle
+ index:
+ title: Sipariş grupları
+ model:
+ error_single_group: "%{user}, başka bir sipariş grubunun üyesidir"
+ invalid_balance: geçerli bir sayı değil
+ orders:
+ articles:
+ article_count: 'Sipariş edilen ürünler:'
+ prices: Net/brüt fiyatı
+ prices_sum: 'Toplam (net/brüt fiyat):'
+ units_full: Tam birimler
+ units_ordered: Sipariş edilen birimler
+ create:
+ notice: Sipariş oluşturuldu.
+ edit:
+ title: 'Siparişi düzenle: %{name}'
+ edit_amount:
+ field_locked_title: Bu ürünün sipariş grupları arasındaki dağılımı manuel olarak değiştirildi. Bu alan, bu değişiklikleri korumak için kilitlidir. Yeni bir dağılım yapmak ve bu değişiklikleri üzerine yazmak için kilidi açın ve miktarı değiştirin.
+ field_unlocked_title: Bu ürünün sipariş grupları arasındaki dağılımı manuel olarak değiştirildi. Miktarı değiştirirken, bu manuel değişiklikler üzerine yazılacaktır.
+ edit_amounts:
+ no_articles_available: Eklenecek ürün yok.
+ set_all_to_zero: Tümünü sıfıra ayarla
+ fax:
+ amount: Miktar
+ articles: Ürünler
+ delivery_day: Teslim günü
+ heading: "%{name} için sipariş"
+ name: İsim
+ number: Numara
+ to_address: Gönderim adresi
+ finish:
+ notice: Sipariş kapatıldı.
+ form:
+ ignore_warnings: Uyarıları yok say
+ prices: Fiyatlar (net/FC)
+ select_all: Hepsini seç
+ stockit: Stokta
+ title: Ürün
+ index:
+ action_end: Kapat
+ action_receive: Teslim al
+ confirm_delete: Siparişi gerçekten silmek istiyor musunuz?
+ confirm_end: Siparişi gerçekten kapatmak istiyor musunuz %{order}? Geri dönüş yok.
+ new_order: Yeni sipariş oluştur
+ no_open_or_finished_orders: Şu anda açık veya kapalı sipariş yok.
+ orders_finished: Kapatıldı
+ orders_open: Açık
+ orders_settled: Düzenlendi
+ title: Siparişleri yönet
+ model:
+ close_direct_message: Üye hesaplarına ücret yansıtılmadan sipariş kapatıldı.
+ error_boxfill_before_ends: Kutu doldurma tarihi son tarihten önce olmalıdır (veya boş bırakılmalıdır).
+ error_closed: Sipariş zaten kapatılmış
+ error_nosel: En az bir ürün seçilmelidir. Ya da belki siparişi silmek istiyor olabilirsiniz?
+ error_starts_before_boxfill: Başlangıç tarihi kutu doldurma tarihinden sonra olmalıdır (veya boş bırakılmalıdır).
+ error_starts_before_ends: Başlangıç tarihi bitiş tarihinden sonra olmalıdır (veya boş bırakılmalıdır).
+ notice_close: '%{name} siparişi, %{ends} kadar.'
+ stock: Stok
+ warning_ordered: 'Uyarı: Kırmızı olarak işaretlenen ürünler bu açık siparişte zaten sipariş edildi. Burada işaretini kaldırırsanız, tüm bu ürünlerin mevcut siparişleri silinecektir. Devam etmek için aşağıdaki onaylayın.'
+ warning_ordered_stock: 'Uyarı: Kırmızı olarak işaretlenen ürünler bu açık stok siparişinde zaten sipariş edildi/satın alındı. Burada seçimleri kaldırırsanız, tüm bu ürünlerin mevcut siparişleri/satı nalımları silinecek ve bunlar hesaba katılmayacaktır. Devam etmek için aşağıda onay verin.'
+ new:
+ title: Yeni sipariş oluştur
+ receive:
+ add_article: Ürün ekle
+ consider_member_tolerance: toleransı dikkate al
+ notice: '%{msg} siparişi alındı.'
+ notice_none: Teslim alınacak yeni bir ürün yok
+ paragraph: Sipariş edilen ve alınan miktar aynıysa, ilgili alanlar boş bırakılabilir. Yine de tüm alanların girilmesi iyi olur, çünkü bu, tüm ürünlerin kontrol edildiğinin anlaşılmasını sağlar.
+ rest_to_stock: stokta kalanlar
+ submit: Siparişi Al
+ surplus_options: 'Dağıtım Seçenekleri:'
+ title: "%{order} Siparişini Al"
+ send_to_supplier:
+ notice: Sipariş tedarikçiye gönderildi.
+ show:
+ action_end: Kapat!
+ amounts: 'Net/Brüt toplam:'
+ articles: Ürün özeti
+ articles_ordered: 'Sipariş edilen üründür:'
+ comments:
+ title: Yorumlar
+ comments_link: Yorumlar
+ confirm_delete: Siparişi gerçekten silmek istiyor musunuz?
+ confirm_end: |-
+ Siparişi gerçekten kapatmak istiyor musunuz %{order}?
+ Geri dönüşü yok.
+ confirm_send_to_supplier: Sipariş %{when} tarihinde zaten tedarikçiye gönderildi. Yeniden göndermek istiyor musunuz?
+ create_invoice: Fatura Ekle
+ description1_order: "%{who} tarafından açılan %{supplier} siparişi, %{state},"
+ description1_period:
+ pickup: alınabileceği tarih %{pickup}
+ starts: '%{starts} tarihinden itibaren açık'
+ starts_ends: '%{starts} tarihinden %{ends} tarihine kadar açık'
+ description2: "%{ordergroups} %{article_count} adet ürün sipariş verdi, toplam değeri %{net_sum} / %{gross_sum} (net / brüt)."
+ group_orders: 'Grup siparişleri:'
+ search_placeholder:
+ articles: Ürün ara...
+ default: Arama yap...
+ groups: Sipariş grupları ara...
+ search_reset: Aramayı sıfırla
+ send_to_supplier: Tedarikçiye gönder
+ show_invoice: Faturayı göster
+ sort_article: Ürüne göre sırala
+ sort_group: Gruba göre sırala
+ stock_order: Stok Siparişi
+ title: '%{name} Siparişi'
+ warn_not_closed: Uyarı, sipariş henüz kapatılmadı.
+ state:
+ closed: kapatıldı
+ finished: tamamlandı
+ open: açık
+ received: alındı
+ update:
+ notice: Sipariş güncellendi.
+ update_order_amounts:
+ msg1: "%{count} adet (%{units} birim) güncellendi"
+ msg2: "%{count} (%{units}) tolerans kullanılarak güncellendi"
+ msg4: "%{count} (%{units}) fazla kaldı"
+ pickups:
+ document:
+ empty_selection: En az bir sipariş seçmelisiniz.
+ filename: "%{date} Teslimatı"
+ invalid_document: Geçersiz belge türü
+ title: "%{date} Teslimatı"
+ index:
+ article_pdf: Ürün PDF'i
+ group_pdf: Grup PDF'i
+ matrix_pdf: Matris PDF'i
+ title: Teslimat günleri
+ sessions:
+ logged_in: Giriş yapıldı!
+ logged_out: Çıkış yapıldı!
+ login_invalid_email: Geçersiz e-posta adresi veya şifre
+ login_invalid_nick: Geçersiz kullanıcı adı veya şifre
+ new:
+ forgot_password: Şifremi unuttum?
+ login: Giriş Yap
+ nojs: Dikkat, çerezlerin ve javascript'in etkinleştirilmesi gerekiyor! Lütfen %{link} kapatın.
+ noscript: NoScript
+ title: Foodsoft Girişi
+ shared:
+ articles:
+ ordered: Sipariş edilen
+ ordered_desc: Üye tarafından sipariş edilen ürün sayısı (miktar + tolerans)
+ received: Alınan
+ received_desc: Üye tarafından alınan ürün sayısı
+ articles_by:
+ price: Toplam fiyat
+ price_sum: Toplam
+ group:
+ access: Erişim
+ activated: aktifleştirildi
+ apple_limit: Elma puanı sipariş sınırı
+ break: "%{start} - %{end} arası"
+ deactivated: devre dışı bırakıldı
+ group_form_fields:
+ search: Ara ...
+ search_user: Kullanıcı ara
+ user_not_found: Kullanıcı bulunamadı
+ open_orders:
+ no_open_orders: Şu anda açık sipariş yok
+ not_enough_apples: Dikkat! Sipariş grubunuzun yeterli miktarda elma puanı bulunmamaktadır.
+ title: Mevcut siparişler
+ total_sum: Toplam tutar
+ who_ordered: Kim sipariş verdi?
+ order_download_button:
+ article_pdf: Ürün PDF'i
+ download_file: Dosya indir
+ fax_csv: Faks CSV'si
+ fax_pdf: Faks PDF'i
+ fax_txt: Faks metni
+ group_pdf: Grup PDF'i
+ matrix_pdf: Matris PDF'i
+ title: İndir
+ task_list:
+ accept_task: Görevi kabul et
+ done: Tamamlandı
+ done_q: Tamamlandı mı?
+ mark_done: Görevi tamamlandı olarak işaretle
+ reject_task: Görevi reddet
+ who: Kim yapıyor?
+ who_hint: "(Ne kadarı hala gerekiyor?)"
+ user_form_fields:
+ contact_address_hint: Sipariş grubunuzun adresi. Burayı güncellerseniz, diğer üyeler de güncellenir.
+ messagegroups: Mesaj gruplarına katılın veya ayrılın
+ workgroup_members:
+ title: Grup üyelikleri
+ simple_form:
+ error_notification:
+ default_message: Hatalar bulundu. Lütfen formu kontrol edin.
+ hints:
+ article:
+ unit: Örn. KG veya 1L veya 500g
+ article_category:
+ description: İçe aktarım/senkronizasyonda tanınan kategori adlarının virgülle ayrılmış listesi
+ order_article:
+ units_to_order: Teslim edilen toplam birim miktarını değiştirirseniz, ayrı ayrı grup miktarlarını değiştirmek için ürün adına tıklamanız gerekir. Bunlar otomatik olarak yeniden hesaplanmayacağından, sipariş grupları teslim edilmemiş ürünler için borçlu kalabilirler!
+ update_global_price: Ayrıca gelecekteki siparişlerin fiyatını da güncelleyin
+ stock_article:
+ copy:
+ name: Lütfen değiştirin
+ edit_stock_article:
+ price: "
Fiyat değişiklikleri yasaktır.
Gerektiğinde, %{stock_article_copy_link}.
"
+ supplier:
+ min_order_quantity: Sipariş vermek için gerekli minimum miktar sipariş sırasında gösterilir ve sipariş vermenizi teşvik etmelidir.
+ task:
+ duration: Görev ne kadar sürede tamamlanacak, 1-3 saat
+ required_users: Toplam kaç kullanıcıya ihtiyaç var?
+ tax: Yüzde olarak, standart 7,0'dır.
+ labels:
+ settings:
+ notify:
+ negative_balance: Sipariş grubumun negatif bakiyesi olduğunda beni bilgilendir.
+ order_finished: Siparişim tamamlandığında sipariş sonucum hakkında beni bilgilendir.
+ order_received: Teslimat detayları hakkında bilgilendirildiğimden emin ol.
+ upcoming_tasks: Yaklaşan görevler hakkında hatırlatmada bulun.
+ profile:
+ email_is_public: E-postam diğer üyeler tarafından görülebilir.
+ language: Dil
+ name_is_public: Adım diğer üyeler tarafından görülebilir.
+ phone_is_public: Telefon numaram diğer üyeler tarafından görülebilir.
+ settings_group:
+ messages: Mesajlar
+ privacy: Gizlilik
+ 'hayir': 'Hayir'
+ options:
+ settings:
+ profile:
+ language:
+ de: Almanca
+ en: İngilizce
+ es: İspanyolca
+ fr: Fransızca
+ nl: Hollandaca
+ tr: Türkçe
+ required:
+ mark: "*"
+ text: zorunlu
+ 'yes': 'Evet'
+ stock_takings:
+ create:
+ notice: Envanter başarıyla oluşturuldu.
+ edit:
+ title: Envanteri düzenle
+ index:
+ new_inventory: Yeni envanter oluştur
+ title: Envanter genel bakışı
+ new:
+ amount: Miktar
+ create: oluştur
+ stock_articles: Stok ürünleri
+ temp_inventory: geçici envanter
+ text_deviations: "%{inv_link} için tüm fazla sapmaları doldurunuz. Azaltma için negatif bir sayı kullanın."
+ text_need_articles: "Burada kullanmadan önce, şuradan yeni bir stok ürün oluşturmanız gerekiyor: %{create_link}"
+ title: Yeni envanter oluştur
+ show:
+ amount: Miktar
+ article: Ürün
+ confirm_delete: Envateri silmek istediğinize emin misiniz?
+ date: Tarih
+ note: Not
+ overview: Envanter genel bakışı
+ supplier: Tedarikçi
+ title: Envanteri göster
+ unit: Birim
+ stock_takings:
+ confirm_delete: Silmek istediğinize emin misiniz?
+ date: Tarih
+ note: Not
+ update:
+ notice: Envanter güncellendi.
+ stockit:
+ check:
+ not_empty: "%{name} silinemedi, envanter sıfır değil."
+ copy:
+ title: Stok ürünü kopyala
+ create:
+ notice: Yeni stok ürünü "%{name}" oluşturuldu.
+ derive:
+ title: Şablon kullanarak stok ürünü ekle
+ destroy:
+ notice: "%{name} ürünü silindi."
+ edit:
+ title: Stok ürünlerini düzenle
+ form:
+ copy_stock_article: stok ürünü kopyala
+ price_hint: Karmaşayı önlemek için, mevcut stok ürünlerinin fiyatlarını şimdilik düzenlemek mümkün değildir.
+ index:
+ confirm_delete: Silmek istediğinizden emin misiniz?
+ new_delivery: Yeni teslimat ...
+ new_stock_article: Yeni stok ürünü ekle
+ new_stock_taking: Envanter ekle
+ order_online: Stok siparişini çevrimiçi olarak ver
+ show_stock_takings: Envanter genel bakışı
+ stock_count: 'Ürün sayısı:'
+ stock_worth: 'Geçerli stok değeri:'
+ title: Stok (%{article_count})
+ toggle_unavailable: Kullanılamayan ürünleri göster/gizle
+ view_options: Görünüm seçenekleri
+ new:
+ search_text: 'Tüm kataloglarda ürün arayın:'
+ title: Yeni stok ürünü ekle
+ show:
+ change_quantity: Değiştir
+ datetime: Zaman
+ new_quantity: Yeni miktar
+ reason: Sebep
+ stock_changes: Stok miktarı değişiklikleri
+ update:
+ notice: Stok ürünü %{name} kaydedildi.
+ suppliers:
+ create:
+ notice: Tedarikçi oluşturuldu
+ destroy:
+ notice: Tedarikçi silindi
+ edit:
+ title: Tedarikçi düzenle
+ index:
+ action_import: Dış veritabanından tedarikçi içe aktar
+ action_new: Yeni tedarikçi oluştur
+ articles: ürünler (%{count})
+ confirm_del: "%{name} tedarikçisini gerçekten silmek istiyor musunuz?"
+ deliveries: teslimatlar (%{count})
+ stock: stokta (%{count})
+ title: Tedarikçiler
+ new:
+ title: Yeni tedarikçi
+ shared_supplier_methods:
+ all_available: Tüm ürünler (yeni mevcut)
+ all_unavailable: Tüm ürünler (yeni mevcut değil)
+ import: İçe aktarılacak ürünleri seçin
+ shared_supplier_note: Tedarikçi harici veritabanına bağlıdır.
+ shared_suppliers:
+ body: "
Harici veritabanındaki tedarikçiler burada görüntülenir.
Dış tedarikçileri abone olarak içe aktarabilirsiniz (aşağıya bakın).
Yeni bir tedarikçi oluşturulacak ve harici veritabanına bağlanacaktır.