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 || 0) }
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..296c4c17 100644
--- a/app/models/concerns/localize_input.rb
+++ b/app/models/concerns/localize_input.rb
@@ -5,12 +5,12 @@ module LocalizeInput
return input unless input.is_a? String
Rails.logger.debug { "Input: #{input.inspect}" }
- separator = I18n.t("separator", scope: "number.format")
- delimiter = I18n.t("delimiter", scope: "number.format")
- 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
+ separator = I18n.t('separator', scope: 'number.format')
+ delimiter = I18n.t('delimiter', scope: 'number.format')
+ input.gsub!(delimiter, '') if input.match(/\d+#{Regexp.escape(delimiter)}+\d+#{Regexp.escape(separator)}+\d+/) # Remove delimiter
+ input.gsub!(separator, '.') # 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..aed5ba78 100644
--- a/app/models/financial_transaction.rb
+++ b/app/models/financial_transaction.rb
@@ -8,19 +8,25 @@ 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 :note, :user_id, presence: true
+ validates :amount, numericality: { greater_then: -100_000,
+ less_than: 100_000 },
+ allow_nil: -> { payment_amount.present? }
+ validates :payment_amount, :payment_fee, allow_nil: true, numericality: { greater_then: 0, 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) }
localize_input_of :amount
+ after_save :update_ordergroup_balance
+
after_initialize do
initialize_financial_transaction_type
end
@@ -28,24 +34,19 @@ 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
- end
-
- # Use this save method instead of simple save and after callback
- def add_transaction!
- ordergroup.add_financial_transaction! amount, note, user, financial_transaction_type
+ def self.ransackable_associations(_auth_object = nil)
+ %w[] # none, and certainly not user until we've secured that more
end
def revert!(user)
transaction do
update_attribute :financial_link, FinancialLink.new
rt = dup
- rt.amount = -rt.amount
+ rt.amount = rt.amount ? -rt.amount : nil
rt.reverts = self
rt.user = user
rt.save!
@@ -71,4 +72,12 @@ class FinancialTransaction < ApplicationRecord
def initialize_financial_transaction_type
self.financial_transaction_type ||= FinancialTransactionType.default
end
+
+ private
+
+ def update_ordergroup_balance
+ # @todo Make sure this transaction and the ordergroup update is in one database transaction.
+ # It may be possible to use an around filter if needed.
+ ordergroup.update_balance!
+ end
end
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..9c1bf605 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,25 +86,26 @@ 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)
- end
+ NotifyNegativeBalanceJob.perform_later(self, t) if t.amount < 0 && account_balance < 0 && account_balance - t.amount >= 0
t
end
end
+ # Recomputes job statistics from group orders.
def update_stats!
# 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 +117,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,30 +146,34 @@ 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
- financial_transactions.last.try(:created_on) || created_on
+ financial_transactions.last.try(:updated_on) || created_on
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 +185,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..ac17adfa 100644
--- a/app/views/articles/_sync_table.html.haml
+++ b/app/views/articles/_sync_table.html.haml
@@ -49,8 +49,7 @@
.input-prepend
%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 ] },
+ %td= form.select :article_category_id, ArticleCategory.all.map {|a| [ a.name, a.id ] },
{include_blank: true}, class: 'input-small'
- unless changed_article.errors.empty?
%tr.alert
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/financial_transactions/_transactions.html.haml b/app/views/finance/financial_transactions/_transactions.html.haml
index 1a4c22e8..efe3dbb8 100644
--- a/app/views/finance/financial_transactions/_transactions.html.haml
+++ b/app/views/finance/financial_transactions/_transactions.html.haml
@@ -45,7 +45,7 @@
= t.note
- FinancialTransactionClass.sorted.each do |c|
%td.numeric{style: 'width:5em'}
- - if t.financial_transaction_type.financial_transaction_class == c
+ - if t.financial_transaction_type.financial_transaction_class == c && t.amount
= format_currency t.amount
- if with_hidden
%td.actions{style: 'width:1em'}
diff --git a/app/views/finance/index.html.haml b/app/views/finance/index.html.haml
index 50ee822c..9de3eb99 100644
--- a/app/views/finance/index.html.haml
+++ b/app/views/finance/index.html.haml
@@ -36,7 +36,7 @@
%td= format_date(ft.created_on)
%td= ft.ordergroup_name
%td= ft.note
- %td.numeric= format_currency ft.amount
+ %td.numeric= ft.amount ? format_currency(ft.amount) : '-'
.span6
%h2
= t('.open_transactions')
@@ -48,7 +48,7 @@
%th= heading_helper Order, :name
%th= t '.end'
%th.numeric= t('.amount_fc')
- %th
+ %th
%tbody
- @orders.each do |order|
%tr
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..49a12970 100644
--- a/app/views/group_orders/_form.html.haml
+++ b/app/views/group_orders/_form.html.haml
@@ -11,142 +11,171 @@
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'
+.alert.alert-error.alert-block#available_funds_error{style: ('display:none')}
+ = t '.invalid_funds'
.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/home/index.html.haml b/app/views/home/index.html.haml
index 9d1ee444..6dc85031 100644
--- a/app/views/home/index.html.haml
+++ b/app/views/home/index.html.haml
@@ -63,6 +63,7 @@
= link_to my_ordergroup_path do
= t '.my_ordergroup.transactions.view'
%i.icon.icon-chevron-right
+ - ''
%table.table.table-striped
%tr
%th= heading_helper FinancialTransaction, :created_on
@@ -83,7 +84,7 @@
- FinancialTransactionClass.sorted.each do |fc|
%td.numeric{style: 'width:5em'}
- if ft.financial_transaction_type.financial_transaction_class == fc
- = format_currency ft.amount
+ = ft.amount ? format_currency(ft.amount) : '-'
-# placeholder deface to add content using erb[silent]:contains()
- ''
diff --git a/app/views/home/ordergroup.html.haml b/app/views/home/ordergroup.html.haml
index c91e7ae4..76b53993 100644
--- a/app/views/home/ordergroup.html.haml
+++ b/app/views/home/ordergroup.html.haml
@@ -23,6 +23,7 @@
= @ordergroup.memberships.map{|m| show_user m.user}.join(', ')
- unless FoodsoftConfig[:disable_invite]
= link_to t('.invite'), new_invite_path(:id => @ordergroup), :remote => true, class: 'btn btn-primary'
+ - ''
.span8
%h2= t('.account_summary')
.well.well-small
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..6a957ec2 100644
--- a/config/locales/de.yml
+++ b/config/locales/de.yml
@@ -448,6 +448,7 @@ de:
error_denied_sign_in: als ein anderer Benutzer anmelden
error_feature_disabled: Diese Funktion ist derzeit nicht aktiviert.
error_members_only: Diese Aktion ist nur für Mitglieder der Gruppe erlaubt!
+ error_minimum_balance: Ihr Kontostand liegt leider unter dem Minimum von %{min}.
error_token: Zugriff verweigert (ungültiger Token)!
article_categories:
create:
@@ -568,7 +569,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 +656,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
@@ -697,6 +698,7 @@ de:
applications: Apps
foodcoop: Foodcoop
language: Sprache
+ layout: Layout
list: Liste
messages: Nachrichten
others: Sonstiges
@@ -1046,33 +1048,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 +1102,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.
@@ -1147,6 +1134,7 @@ de:
create: Einladung verschicken
tasks:
required_users: "Es fehlen %{count} Mitstreiterinnen!"
+ task_title: "%{name} (%{duration}h)"
home:
apple_bar:
desc: 'Abgebildet ist das Verhältnis von erledigten Aufgaben zu dem Bestellvolumen Deiner Bestellgruppe im Vergleich zum Durchschnitt in der Foodcoop. Konkret: Pro %{amount} Bestellsumme solltest Du eine Aufgabe machen!'
@@ -1231,6 +1219,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: "--"
@@ -1244,6 +1234,7 @@ de:
header:
feedback:
desc: Fehler gefunden? Vorschlag? Idee? Kritik?
+ title: Feedback
help: Hilfe
logout: Abmelden
ordergroup: Meine Bestellgruppe
@@ -1281,6 +1272,7 @@ de:
feedback:
header: "%{user} schrieb am %{date}:"
subject: Feedback zur Foodsoft
+ from_via_foodsoft: "%{name} via Foodsoft"
invite:
subject: Einladung in die Foodcoop
text: |
@@ -1436,6 +1428,7 @@ de:
stock: Lager
suppliers: Lieferanten/Artikel
title: Artikel
+ dashboard: Übersichtsseite
finances:
accounts: Konten verwalten
balancing: Bestellungen abrechnen
@@ -1443,6 +1436,7 @@ de:
home: Übersicht
invoices: Rechnungen
title: Finanzen
+ foodcoop: Foodcoop
members: Mitglieder
ordergroups: Bestellgruppen
orders:
@@ -1480,9 +1474,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:
@@ -1496,6 +1487,7 @@ de:
articles: Artikel
delivery_day: Liefertag
heading: Bestellung für %{name}
+ name: Name
number: Nummer
to_address: Versandaddresse
finish:
@@ -1595,6 +1587,7 @@ de:
index:
article_pdf: Artikel PDF
group_pdf: Gruppen PDF
+ matrix_pdf: Matrix PDF
title: Abholtage
sessions:
logged_in: Angemeldet!
@@ -1605,6 +1598,7 @@ de:
forgot_password: Passwort vergessen?
login: Anmelden
nojs: Achtung, Cookies und Javascript müssen aktiviert sein! %{link} bitte abschalten.
+ noscript: NoScript
title: Foodsoft anmelden
shared:
articles:
@@ -1633,8 +1627,13 @@ de:
who_ordered: Wer hat bestellt?
order_download_button:
article_pdf: Artikel PDF
+ download_file: Datei herunterladen
+ fax_csv: Fax CSV
+ fax_pdf: Fax PDF
fax_txt: Fax Text
group_pdf: Gruppen PDF
+ matrix_pdf: Matrix PDF
+ title: Herunterladen
task_list:
accept_task: Aufgabe übernehmen
done: Erledigt
@@ -1691,9 +1690,11 @@ de:
profile:
language:
de: Deutsch
+ en: Englisch
es: Spanisch
fr: Französisch
nl: Niederländisch
+ tr: Türkisch
required:
mark: "*"
text: benötigt
@@ -1850,6 +1851,7 @@ de:
confirm_delete_single_from_group: Bist Du sicher, dass Du diese Aufgabe löschen möchtest (und in Bezug stehende wiederkehrende Aufgabe behalten möchtest)?
delete_group: Aufgabe und folgende löschen
edit_group: Wiederkehrende ändern
+ hours: "%{count}h"
mark_done: Als erledigt markieren
reject_task: Aufgabe ablehnen
title: Aufgabe anzeigen
@@ -1876,6 +1878,9 @@ de:
delete: Löschen
download: Herunterladen
edit: Bearbeiten
+ marks:
+ close: "×"
+ success:
move: Verschieben
or_cancel: oder abbrechen
please_wait: Bitte warten...
@@ -1885,6 +1890,10 @@ de:
show: Anzeigen
views:
pagination:
+ first: "«"
+ last: "»"
+ next: "›"
+ previous: "‹"
truncate: "..."
workgroups:
edit:
@@ -1895,3 +1904,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..79cf1417 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,38 +1048,23 @@ 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
units_full: Filled units
units_total: Total units
+ invalid_funds: Not enough available funds
index:
closed_orders:
more: more...
@@ -1118,6 +1103,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 +1220,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 +1478,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 +1631,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 +1698,7 @@ en:
es: Spanish
fr: French
nl: Dutch
+ tr: Turkish
required:
mark: "*"
text: required
@@ -1923,3 +1908,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..d722a872 100644
--- a/config/locales/es.yml
+++ b/config/locales/es.yml
@@ -35,9 +35,15 @@ es:
unit_quantity: Cantidad de unidades
bank_account:
balance: Saldo
+ bank_gateway: Pasarela bancaria
description: Descripción
iban: IBAN
name: Nombre
+ bank_gateway:
+ authorization: Cabecera-Autorización
+ name: Nombre
+ unattended_user: Usuario desatendido
+ url: Enlace
bank_transaction:
amount: Cantidad
date: Fecha
@@ -65,6 +71,7 @@ es:
ordergroup: Grupo de pedido
user: Ingresado por
financial_transaction_class:
+ ignore_for_account_balance: Ignorar en el saldo de la cuenta
name: Nombre
financial_transaction_type:
bank_account: Cuenta bancaria
@@ -186,6 +193,11 @@ es:
phone2: teléfono 2
shared_sync_method: Cómo sincronizar
url: Web
+ supplier_category:
+ name: Nombre
+ description: Descripción
+ financial_transaction_class: Clase de transacciones financieras
+ bank_account: Cuenta bancaria
task:
created_by: Creado por
created_on: Creado en
@@ -243,6 +255,8 @@ es:
models:
article: Artículo
article_category: Categoría
+ bank_account: Cuenta bancaria
+ bank_gateway: Pasarela bancaria
bank_transaction: Transacción bancaria
delivery: Entrega
financial_transaction: Transacción financiara
@@ -258,6 +272,7 @@ es:
stock_article: Artículo de stock
stock_taking: Toma de inventario
supplier: Proveedor
+ supplier_category: Categoría del proveedor
task: Tarea
user: Usuario
workgroup: Grupo de trabajo
@@ -268,7 +283,7 @@ es:
all_ordergroups: Todos los grupos de pedido
all_users: Todos los usuarios
all_workgroups: Todos los grupos de trabajo
- created_at: creado
+ created_at: creado
first_paragraph: Aquí puedes administrar grupos y usuarios de Foodsoft.
groupname: nombre del grupo
members: miembros
@@ -281,6 +296,14 @@ es:
title: Administración
type: tipo
username: nombre de usuario
+ bank_accounts:
+ form:
+ title_edit: Editar cuenta bancaria
+ title_new: Añadir nueva cuenta bancaria
+ bank_gateways:
+ form:
+ title_edit: Editar pasarela bancaria
+ title_new: Añadir nueva pasarela bancaria
configs:
list:
key: Clave
@@ -308,6 +331,26 @@ es:
finances:
index:
bank_accounts: Cuentas bancarias
+ first_paragraph: Aquí puede administrar las clases de transacciones financieras y los tipos de transacciones financieras correspondientes. Cada transacción financiera tiene un tipo, que usted tiene que seleccionar en cada transacción, si usted creó más de un tipo. Las clases de transacciones financieras pueden utilizarse para agrupar los tipos de transacciones financieras y se mostrarán como columnas adicionales en el resumen de la cuenta, si se ha creado más de una.
+ new_bank_account: Añadir nueva cuenta bancaria
+ new_financial_transaction_class: Añadir nueva clase de transacción financiera
+ new_bank_gateway: Añadir nueva pasarela bancaria
+ title: Finanzas
+ transaction_types: Tipos de transacciones financieras
+ supplier_categories: Categorías de proveedores
+ new_supplier_category: Nueva categoría de proveedor
+ transaction_types:
+ name: Nombre
+ new_financial_transaction_type: Añadir nuevo tipo de transacción financiera
+ financial_transaction_classes:
+ form:
+ title_edit: Editar clase de transacción financiera
+ title_new: Añadir nueva clase de transacción financiera
+ financial_transaction_types:
+ form:
+ name_short_desc: El nombre corto es obligatorio para los tipos de transacciones financieras que deben ser asignados automáticamente en las transacciones bancarias. Si hay varias cuentas bancarias, se puede seleccionar la cuenta preferida para las transferencias bancarias.
+ title_edit: Editar tipo de transacción financiera
+ title_new: Añadir nuevo tipo de transacción financiera
mail_delivery_status:
destroy_all:
notice: Se han borrado todos los problemas de email
@@ -345,11 +388,15 @@ es:
notice: El usuario/a ha sido borrado
edit:
title: Edita usuario/a
+ form:
+ create_ordergroup: Crear grupo de pedido con el mismo nombre y añadir usuario.
+ send_welcome_mail: Enviar un correo de bienvenida al usuario/a.
index:
first_paragraph: Aquí puedes %{url}, editar y borar usuarios.
new_user: Crea nuevo usuario/a
new_users: crea nuevo
show_deleted: Muestra usuarios borrados
+ title: Usuario/a administrador
new:
title: Crea nuevo usuario
restore:
@@ -390,6 +437,10 @@ es:
workgroups:
members: miembros
name: nombre
+ supplier_categories:
+ form:
+ title_new: Añadir categoría de proveedor
+ title_edit: Editar categoría de proveedor
application:
controller:
error_authn: Es necesaria la autenticación!
@@ -397,6 +448,7 @@ es:
error_denied_sign_in: entra como otro usuario/a
error_feature_disabled: Esta opción está actualmente deshabilitada
error_members_only: Esta acción está sólo disponible para miembros de un grupo.
+ error_minimum_balance: Lo sentimos, el saldo de tu cuenta está por debajo del mínimo de %{min}.
error_token: Acceso denegado (invalid token).
article_categories:
create:
@@ -433,6 +485,7 @@ es:
error_update: 'Ha ocurrido un error miebtras se actualizaba el artículo ''%{article}'': %{msg}'
parse_upload:
no_file: Elige un archivo para subir.
+ notice: "%{count} artículos fueron analizados con éxito."
sync:
notice: El catálogo está actualizado
shared_alert: "%{supplier} no está conectado a una base de datos externa"
@@ -462,6 +515,7 @@ es:
not_found: No se han encontrado articulos
index:
change_supplier: Cambiar proveedor ...
+ download: Descargar artículos
edit_all: Editar todos
ext_db:
import: Importar artículo
@@ -513,19 +567,29 @@ es:
status: Estado (x=saltar)
file_label: Por favor elige un archivo compatible
options:
- convert_units: Mantener unidades actuales, recomputar la cantidad y precio de unidades (como sincronizar).
+ 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
organic: Orgánico
+ supplier_1: Nuttyfarm
+ supplier_2: Brownfields
+ supplier_3: Greenfields
tomato_juice: Jugo de tomate
walnuts: Nogal
submit: Subir archivo
text_1: 'Aquí puedes subir una hoja de cálculo para actualizar los artículos de %{supplier}. Se aceptan los formatos Excel (xls, xlsx) y OpenOffice (ods), al igual que archivos CSV (con columnas separadas por ";" con codificación UTF-8). Solo se importará la primera hoja y las columnas deben estar en el siguiente orden:'
text_2: Las hileras que se muestran aquí son ejemplos. Cuando hay una "x" en la primera columna, el artículo se sacará de la lista. Esto te permite editar la hoja de cálculo y rápidamente sacar muchos artículos a la vez, por ejemplo cuando los artículos ya no están disponibles con el proveedor. La categoría se hará coincidir con tu lista de categorías de Foodsoft (tanto por nombre de categoría como nombre de importación).
title: Subir artículos de %{supplier}
+ bank_account_connector:
+ confirm: Por favor, confirme el código %{code}.
+ fields:
+ email: E-Mail
+ pin: PIN
+ password: Contraseña
+ tan: TAN
+ username: Nombre de Usuario/a
config:
hints:
applepear_url: Web donde se explica el sistema de manzanas y peras.
@@ -547,7 +611,9 @@ es:
order_schedule:
boxfill:
recurr: Programa cuándo la fase de llenado de cajas comienza por defecto.
+ time: Tiempo por defecto cuando comienza la fase de llenado de caja del pedido.
ends:
+ recurr: Programa para la fecha predeterminada de cierre de pedidos.
time: Fecha por defecto cuando se cierran los pedidos.
initial: La agenda comienza en esta fecha.
page_footer: Se muestra en cada página en la parte inferior. Dejar vacío para desactivar el pie de página por completo.
@@ -567,12 +633,15 @@ es:
use_boxfill: Cuando está activado, cerca del cierre de un pedido los miembros no podrán cambiar su pedido a menos que se incremente el valor pedido total. Esto ayudará a llenar las cajas que faltan. Igualmente deberás decidir una fecha de llenado de cajas para los pedidos.
use_iban: Cuando esta opción está habilitada, el proveedor y el usuario pueden guardan también su número de cuenta bancaria internacional (IBAN).
use_nick: Muestra y utiliza apodos en lugar de nombres reales. Cuando activas esto debes chequear que todos los usuarios tengan apodo.
+ use_self_service: Cuando está activado, los miembros pueden usar las funciones de balance seleccionadas por sí mismos.
+ webstats_tracking_code: Código de seguimiento para analíticas web (como Piwik o Google analytics). Dejar en blanco si no usa estas analíticas.
keys:
applepear_url: Enlace de ayuda para el sistema de puntos-manzana
charge_members_manually: Cambia los miembros manualmente
contact:
city: Ciudad
country: País
+ email: E-mail
phone: Teléfono
street: Calle
zip_code: Código postal
@@ -580,7 +649,14 @@ es:
currency_unit: Moneda
custom_css: CSS adicional
default_locale: Idioma por defecto
+ default_role_article_meta: Artículos
+ default_role_finance: Finanzas
+ default_role_invoices: Facturas
+ default_role_orders: Pedidos
+ default_role_pickups: Días de recogida
+ default_role_suppliers: Proveedores
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
@@ -604,6 +680,7 @@ es:
price_markup: Margen de la cooperativa
stop_ordering_under: Puntos-manzana mínimos
tasks_period_days: Periodo
+ tasks_upfront_days: Crear de antemano
tax_default: IVA por defecto
time_zone: Zona horaria
tolerance_is_costly: La tolerancia es prioritaria
@@ -615,8 +692,10 @@ es:
use_boxfill: Fase de llenar las cajas
use_iban: Usar IBAN
use_nick: Usa apodos
+ use_self_service: Usar auto servicio
webstats_tracking_code: Código de seguimiento
tabs:
+ applications: Aplicaciones
foodcoop: Cooperativa
language: Idioma
layout: Disposición
@@ -624,6 +703,7 @@ es:
messages: Mensajes
others: Otro
payment: Finanzas
+ security: Seguridad
tasks: Tareas
deliveries:
add_stock_change:
@@ -683,9 +763,11 @@ es:
- Unidad
- Precio/Unidad
- Subtotal
+ total: Total
order_matrix:
filename: Pedido %{name}-%{date} - matrix para ordenar
heading: Descripción del artículo (%{count})
+ title: 'Matriz de ordenamiento de pedidos: %{name}, cerrada a las %{date}'
errors:
general: Ha ocurrido un problema.
general_again: Ha ocurrido un problema. Por favor inténtalo de nuevo.
@@ -702,6 +784,7 @@ es:
notice: Tus comentarios fueron enviados con éxito. ¡Muchas gracias!
new:
first_paragraph: '¿Encontraste un error? ¿Tienes sugerencias, ideas o comentarios? Nos gustaría recibir tus comentarios.'
+ second_paragraph: Tenga en cuenta que el equipo de Foodsoft es el único responsable del mantenimiento del software. Para preguntas relacionadas con la organización de tu Foodcoop, por favor contacta a la persona de contacto apropiada.
send: Enviar
title: Enviar comentarios
finance:
@@ -709,6 +792,8 @@ es:
close:
alert: 'Ocurrió un error en la contabilidad: %{message}'
notice: El pedido se ha cerrado con éxito, el balance de la cuenta ha sido actualizado.
+ close_all_direct_with_invoice:
+ notice: '%{count} pedidos han sido liquidados.'
close_direct:
alert: 'El pedido no se puede cerrar: %{message}'
notice: El pedido ha sido cerrado
@@ -717,17 +802,23 @@ es:
first_paragraph: 'Cuando el pedido se cierre se actualizarán todas las cuentas del grupo. Las cuentas serán cargadas así:'
or_cancel: o vuelve a contabilidad
title: Cierra el pedido
+ edit_note:
+ title: Editar nota de pedido
edit_results_by_articles:
add_article: Añadir artículo
amount: Importe
+ edit_transport: Editar transporte
gross: Bruto
net: Neto
+ edit_transport:
+ title: Distribuir costes de transporte
group_order_articles:
add_group: Añadir grupo
total: Costes totales
total_fc: Suma (precio al grupo)
units: Unidades
index:
+ close_all_direct_with_invoice: Cerrar todo con factura
title: Pedidos cerrados
invoice:
edit: Editar factura
@@ -778,7 +869,10 @@ es:
with_extra_charge: 'con cargo extra:'
without_extra_charge: 'sin cargo extra:'
bank_accounts:
+ assign_unlinked_transactions:
+ notice: '%{count} transacciones han sido asignadas'
import:
+ notice: '%{count} nuevas transacciones han sido importadas'
no_import_method: Para esta cuenta bancaria no se ha configurado ningún método de importación.
submit: Importar
title: Importar transacciones bancarias para %{name}
@@ -807,12 +901,16 @@ es:
notice: El enlace a la factura ha sido añadido.
create:
notice: Se ha creado un nuevo enlance financiero.
+ create_financial_transaction:
+ notice: La transacción financiera ha sido añadida.
index_bank_transaction:
title: Añadir transacción bancaria
index_financial_transaction:
title: Añadir transacción financiera
index_invoice:
title: Añadir factura
+ new_financial_transaction:
+ title: Añadir transacción financiera
remove_bank_transaction:
notice: Se ha eliminado el enlace a la transacción bancaria.
remove_financial_transaction:
@@ -820,7 +918,15 @@ es:
remove_invoice:
notice: El enlace a la factura ha sido eliminado.
show:
+ add_bank_transaction: Añadir transacción bancaria
+ add_financial_transaction: Añadir transacción financiera
+ add_invoice: Añade factura
+ amount: Cantidad
+ date: Fecha
+ description: Descripción
+ new_financial_transaction: Nueva transacción financiera
title: Enlace financiero %{number}
+ type: Tipo
financial_transactions:
controller:
create:
@@ -829,7 +935,11 @@ es:
alert: 'Ha ocurrido un error: %{error}'
error_note_required: Note se requiere!
notice: Se han guardado todas las transacciones
+ destroy:
+ notice: La transacción ha sido eliminada.
index:
+ balance: 'Saldo de la cuenta: %{balance}'
+ last_updated_at: "(última actualización hace %{when})"
new_transaction: Crea nueva transacción
title: Balance de cuentas para %{name}
index_collection:
@@ -837,16 +947,26 @@ es:
title: Transacciones financieras
new:
paragraph: Aquí puedes poner o quitar dinero del grupo de pedido %{name}.
+ paragraph_foodcoop: Aquí puedes poner y quitar dinero para el foodcoop.
title: Nueva transacción
new_collection:
add_all_ordergroups: Añade todos los grupos de pedido
+ add_all_ordergroups_custom_field: Añadir todos los pedidos de grupo con %{label}
+ create_financial_link: Crear un vínculo financiero común para las nuevas transacciones.
+ create_foodcoop_transaction: Crear una transacción con la suma inversa para el foodcoop (en el caso de "doble entrada de cuenta")
new_ordergroup: Añade nuevo grupo de pedido
save: Guarda transacción
+ set_balance: Ajuste el saldo del grupo de pedido a la cantidad introducida.
sidebar: Aquí puedes actualizar más cuentas al mismo tiempo. Por ejemplo, todas las transferencias del grupo de pedido de un balance de cuenta.
title: Actualizar más cuentas
ordergroup:
remove: Remover
remove_group: Remover grupo
+ transactions:
+ confirm_revert: '¿Estás seguro de que quieres revertir %{name}? En este caso se creará una nueva transacción con una cantidad invertida y en combinación con la transacción original ocultada. Estas transacciones ocultas sólo son visibles a través de la opción ''Mostrar oculto'' y no son visibles para los usuarios normales en absoluto.'
+ revert_title: Revertir la transacción, que la ocultará a los usuarios normales.
+ transactions_search:
+ show_hidden: Mostrar transacciones ocultas
index:
amount_fc: Importe(FC)
end: Fin
@@ -863,6 +983,7 @@ es:
attachment_hint: Sólo se permiten los formatos JPEG y PDF.
index:
action_new: Crea nueva factura
+ show_unpaid: Mostrar facturas no pagadas
title: Facturas
new:
title: Crea nueva factura
@@ -874,8 +995,10 @@ es:
title: Facturas impagas
ordergroups:
index:
+ new_financial_link: Nuevo enlace financiero
new_transaction: Añade nuevas transacciones
show_all: Todas las transacciones
+ show_foodcoop: Transacciones de Foodcoop
title: Maneja los grupos
ordergroups:
account_statement: Balance de cuenta
@@ -889,6 +1012,8 @@ es:
only_active: Sólo grupos activos
only_active_desc: "(han hecho al menos un pedido en los últimos 3 meses)"
title: Grupo de pedido
+ ordergroups:
+ break: "%{start} - %{end}"
users:
index:
body: "
Desde aquí puedes escribir un mensaje a los miembros de tu cooperativa Foodcoop. Recuerda habilitar en %{profile_link} tus detalles de contacto para que sean visibles.
"
@@ -930,7 +1055,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
@@ -988,10 +1112,12 @@ es:
application:
edit_user: Edita usuario
nick_fallback: "(no tiene apodo)"
+ role_admin: Admin
role_article_meta: Artículos
role_finance: Finanzas
role_invoices: Facturas
role_orders: Pedidos
+ role_pickups: Días de recogida
role_suppliers: Proveedores
show_google_maps: Muéstralo en Google maps
sort_by: Ordena por %{text}
@@ -1001,12 +1127,14 @@ es:
orders:
old_price: Precio anterior
option_choose: Elige proveedor/stock
+ option_stock: Existencias
order_pdf: Crea PDF
submit:
invite:
create: envía invitación
tasks:
required_users: "Aún se necesitan %{count} miembros!"
+ task_title: "%{name} (%{duration}h)"
home:
apple_bar:
desc: 'Esto muestra la proporción de tareas completadas respecto al volumen de pedidos de tu grupo de pedido en comparación con el promedio en Foodcoop. En práctica: por cada %{amount} de pedidos totales, tú deberías hacer una tarea!'
@@ -1015,8 +1143,9 @@ es:
warning: Cuidado, si tienes menos de %{threshold} puntos-manzana no puedes hacer un pedido!
changes_saved: Guarda los cambios.
index:
+ due_date_format: "%A %d %B"
my_ordergroup:
- last_update: La última actualización fue hace %{when}
+ last_update: La última actualización fue hace %{when}
title: Mi grupo de pedido
transactions:
title: Últimas transacciones
@@ -1048,12 +1177,21 @@ es:
title: Mi Perfil
user:
since: "(miembro para %{when})"
+ title: "%{user}"
+ reference_calculator:
+ transaction_types_headline: Propósito
+ placeholder: Por favor, introduzca primero las cantidades que desea transferir en cada campo, para ver la referencia que debe utilizar para esa transacción.
+ text0: Por favor transfiera
+ text1: con la referencia
+ text2: a la cuenta bancaria
+ title: Calculador de referencia
start_nav:
admin: Administración
finances:
accounts: Actualizar cuentas
settle: Pedidos de la cuenta
title: Finanzas
+ foodcoop: Foodcoop
members: Miembros
new_ordergroup: Nuevo grupo de pedido
new_user: Nuevo miembro
@@ -1081,19 +1219,31 @@ 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_1_separator: "--"
+ footer_2_foodsoft: 'Foodsoft: %{url}'
+ footer_3_homepage: 'Foodcoop: %{url}'
footer_4_help: 'Ayuda: %{url}'
help: 'Ayuda'
+ foodsoft: Foodsoft
footer:
revision: revisión %{revision}
header:
feedback:
desc: '¿Encontrase algún error? ¿Sugerencias? ¿Ideas?'
+ title: Sugerencias
help: Ayuda
logout: Salir
ordergroup: Mis grupos de pedido
profile: Edita perfil
+ reference_calculator: Calculador de referencia
+ logo: "foodsoft"
+ lib:
+ render_pdf:
+ page: Página %{number} de %{count}
login:
accept_invitation:
body: "
Has sido invitado a formar parte de %{foodcoop} como miembro del grupo %{group}.
Si quieres participar, es necesario que completes este formulario.
Tu información no será compartida con terceros bajo ninguna razón. Puedes decidir qué información personal será visible. 'Todos' hace referencia a todos los miembros de Foodcoop. Sólo los administradores tienen acceso a tu información.
"
@@ -1106,7 +1256,7 @@ es:
error_invite_invalid: Tu invitación no es válida.
error_token_invalid: La sesión ha expirado o no es válida. Prueba de nuevo.
reset_password:
- notice: Si tu email está ya registrado aquí, recibirás un mensaje con un enlace para
+ notice: Si tu email está ya registrado aquí, recibirás un mensaje con un enlace para
update_password:
notice: Tu contraseña ha sido actualizada. Prueba a conectarte ahora.
forgot_password:
@@ -1118,9 +1268,13 @@ es:
submit: Guardar la nueva contraseña
title: Nueva contraseña
mailer:
+ dateformat: "%d %b"
feedback:
header: "%{user} escribió %{date}:"
+ subject: Comentarios para Foodsoft
+ from_via_foodsoft: "%{name} vía Foodsoft"
invite:
+ subject: Invitación al Foodcoop
text: |
Hola!
@@ -1163,6 +1317,8 @@ es:
Queridos miebros de %{ordergroup},
El pedido de "%{order}" ha sido cerrado por %{user} en %{when}.
+ text1: |
+ Puede ser posiblemente recogido en %{pickup}.
text2: |
Los siguientes artículos se han pedido para tu grupo de pedido:
text3: |-
@@ -1172,6 +1328,18 @@ es:
Abrazos %{foodcoop}.
+ order_received:
+ subject: 'Envío de pedido registrado: %{name}'
+ text0: |
+ Estimado %{ordergroup},
+
+ el pedido de "%{order}" ha sido recibido.
+ abundant_articles: Recibido demasiado
+ scarce_articles: Recibido muy poco
+ article_details: |
+ o %{name}:
+ -- Solicitado: %{ordered} x %{unit}
+ -- Recibido: %{received} x %{unit}
order_result_supplier:
subject: Nuevo pedido para %{name}
text: |
@@ -1186,6 +1354,16 @@ es:
%{foodcoop}
reset_password:
subject: Hay tareas que se deben hacer ya!
+ text: |
+ Hola %{user},
+
+ Has (o alguien más) solicitado una nueva contraseña.
+ Para elegir una nueva contraseña, siga este enlace: %{link}
+ Este enlace funciona sólo una vez y expira el %{expires}.
+ Si no quieres cambiar tu contraseña, simplemente ignora este mensaje. Tu contraseña no ha sido cambiada aún.
+
+
+ ¡Saludos, tu equipo de Foodsoft!
upcoming_tasks:
nextweek: 'Tareas para la semana que viene:'
subject: Tareas que hay que hacer ya!
@@ -1198,16 +1376,50 @@ es:
Saludos de %{foodcoop}.
+ welcome:
+ subject: Bienvenido al Foodcoop
+ text0: |
+ Estimado %{user},
+
+ se ha creado una nueva cuenta Foodsoft para ti.
+ text1: |
+ Para elegir una nueva contraseña, siga este enlace: %{link}
+ Este enlace solo funciona una vez y caduca el %{expires}.
+ Siempre puedes usar "¿Olvidaste la contraseña?" para obtener un nuevo enlace.
+
+
+ Saludos de %{foodcoop}.
+ messages_mailer:
+ foodsoft_message:
+ footer: |
+ Respuesta: %{reply_url}
+ Ver mensaje en línea: %{msg_url}
+ Opciones de mensaje: %{profile_url}
+ footer_group: |
+ Enviado al grupo: %{group}
model:
delivery:
each_stock_article_must_be_unique: Los artículos de stock no pueden ser listados más de una vez.
+ financial_transaction:
+ foodcoop_name: Foodcoop
+ financial_transaction_type:
+ no_delete_last: Debe existir al menos un tipo de transacción financiera.
+ group_order:
+ stock_ordergroup_name: Existencias (%{user})
+ invoice:
+ invalid_mime: tiene un tipo de MIME inválido (%{mime})
membership:
no_admin_delete: No te puedes salir de este grupo porque eres el último adimistrador/a.
+ order_article:
+ error_price: debe especificarse y tener un precio actual
user:
no_ordergroup: no hay célula
+ group_order_article:
+ order_closed: El pedido está cerrado y no se puede modificar
navigation:
admin:
config: Configuración
+ finance: Finanzas
home: Resumen
mail_delivery_status: Problemas de email
ordergroups: Grupos de pedido
@@ -1216,12 +1428,14 @@ es:
workgroups: grupos de trabajo
articles:
categories: Categorías
+ stock: Existencias
suppliers: Proveedores/artículos
title: Artículos
dashboard: Escritorio
finances:
accounts: Administrar cuentas
balancing: Pedidos de cuenta
+ bank_accounts: Cuentas bancarias
home: Resumen
invoices: Facturas
title: Finanzas
@@ -1232,6 +1446,7 @@ es:
archive: Mis Pedidos
manage: Gestionar pedidos
ordering: Hacer pedido!
+ pickups: Días de recogida
title: Pedidos
tasks: Tareas
workgroups: Grupos de trabajo
@@ -1262,9 +1477,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:
@@ -1272,6 +1484,7 @@ es:
field_unlocked_title: La distribución de este artículo entre los grupos de pedido se ha cambiado a mano. Cuando cambies las cantidades, esos cambios manuales se perderán.
edit_amounts:
no_articles_available: Ningún artículo para añadir.
+ set_all_to_zero: Poner todo a cero
fax:
amount: Cantidad
articles: Artículos
@@ -1305,7 +1518,9 @@ es:
error_closed: El pedido ya estaba cerrado
error_nosel: Debes seleccionar al menos un artículo. Quizás quieres borrar el pedido?
error_starts_before_boxfill: tiene que ser después de la fecha de comienzo (o estar vacío)
+ error_starts_before_ends: debe ser después de la fecha de inicio (o permanecer vacío)
notice_close: 'Pedido: %{name}, hasta %{ends}'
+ stock: Existencias
warning_ordered: 'Cuidado: los artículos marcados en rojo ya han sido pedidos en este pedido abierto. Si los deseleccionas aquí, todos los pedidos actuales de estos artículos se borrarán. Para proceder, confirma abajo.'
warning_ordered_stock: 'Cuidado: Los artículos marcados en rojo ya han sido pedidos en este pedido de stock. Si los deseleccionas aquí, todos los pedidos y compras de estos artículos se borrarán y no estarán en la contabilidad. Para proceder, confirma abajo.'
new:
@@ -1315,6 +1530,8 @@ es:
consider_member_tolerance: considera la tolerancia
notice: 'Pedido recibido: %{msg}'
notice_none: Ningún nuevo artículo para recibir
+ paragraph: Si el pedido y el importe recibido son los mismos, los campos correspondientes pueden estar vacíos. Sigue siendo buena práctica entrar en todos los campos, ya que esto proporciona una forma fácil de verificar que todos los artículos han sido seleccionados.
+ rest_to_stock: restablecer a valores en existencias
submit: recibe pedido
surplus_options: 'Opciones de distribución:'
title: Recibiendo %{order}
@@ -1328,8 +1545,15 @@ es:
comments:
title: Comentarios
comments_link: Comentarios
+ confirm_delete: '¿Estás seguro/a de que quieres borrar el pedido?'
+ confirm_end: |-
+ ¿Realmente desea cerrar el pedido %{order}?
+ No hay vuelta atrás.
+ confirm_send_to_supplier: El pedido ya ha sido enviado al proveedor el %{when}. ¿Realmente desea enviarlo de nuevo?
create_invoice: Añade factura
+ description1_order: "%{state} pedido de %{supplier} abierto por %{who}"
description1_period:
+ pickup: y puede ser recogido en %{pickup}
starts: abierto desde %{starts}
starts_ends: abierto desde %{starts} hasta %{ends}
description2: "%{ordergroups} ha pedido %{article_count} artículos, con un valor total de %{net_sum} / %{gross_sum} (neto / bruto)."
@@ -1355,14 +1579,30 @@ es:
notice: Se actualizó el pedido.
update_order_amounts:
msg1: "%{count} artículos (%{units} units) actualizados"
+ msg2: "%{count} (%{units}) usando tolerancia"
+ msg4: "%{count} (%{units}) sobra"
+ pickups:
+ document:
+ empty_selection: Debe seleccionar al menos un pedido.
+ filename: Recogida para %{date}
+ invalid_document: Tipo de documento inválido
+ title: Recogida para %{date}
+ index:
+ article_pdf: Artículo PDF
+ group_pdf: Grupo PDF
+ matrix_pdf: Matrix PDF
+ title: Días de recogida
sessions:
logged_in: '¡Te has conectado!'
+ logged_out: '¡Te has desconectado!'
login_invalid_email: Dirección de email o contraseña no válidas
login_invalid_nick: Usuario o contraseña no válidos
new:
forgot_password: '¿Has olvidado la contraseña?'
login: Entra
nojs: Atención, las cookies y el javascript deben ser activados! Por favor desactiva %{link}.
+ noscript: NoScript
+ title: Inicio de sesión Foodsoft
shared:
articles:
ordered: Pedidos
@@ -1391,6 +1631,11 @@ es:
order_download_button:
article_pdf: Artículos PDF
download_file: Descargar archivo
+ fax_csv: Fax CSV
+ fax_pdf: Fax PDF
+ fax_txt: Texto fax
+ group_pdf: Grupo PDF
+ matrix_pdf: Matrix PDF
title: Descargar
task_list:
accept_task: Acepta la tarea
@@ -1406,9 +1651,13 @@ es:
workgroup_members:
title: Membresías de grupo
simple_form:
+ error_notification:
+ default_message: Se han encontrado errores. Por favor, compruebe el formulario.
hints:
article:
unit: por ej. KG o 1L o 500g
+ article_category:
+ description: lista separada por comas de nombres de categorías reconocidos en la importación/sincronización
order_article:
units_to_order: Si cambias la cantidad total de unidades enviadas también tendrás que cambiar los valores individuales de grupo haciendo click en el nombre del artículo. No serán recalculados automáticamente, así que a los otros grupos de pedido se les podrían ser cobrar artículos que no llegarán!
update_global_price: Actualizar el precio para futuros pedidos
@@ -1428,6 +1677,7 @@ es:
notify:
negative_balance: Infórmame cuando mi grupo de pedido tenga un balance negativo.
order_finished: Infórmame acerca del resultado de mi pedido (cuando se cierre).
+ order_received: Infórmame sobre los datos de entrega (después de recibir el pedido).
upcoming_tasks: Recordarme las tareas incompletas.
profile:
email_is_public: El email es visible para otros miembros
@@ -1437,6 +1687,7 @@ es:
settings_group:
messages: Mensajes
privacy: Privacidad
+ 'no': 'No'
options:
settings:
profile:
@@ -1446,7 +1697,9 @@ es:
es: Español
fr: Francés
nl: Neerlandés
+ tr: Turco
required:
+ mark: "*"
text: requerido
'yes': 'Sí'
stock_takings:
@@ -1460,22 +1713,34 @@ es:
new:
amount: Cantidad
create: crea
+ stock_articles: Artículos en existencias
+ temp_inventory: inventario temporal
+ text_deviations: Por favor, rellene todas las desviaciones excedentes del %{inv_link}. Para la reducción, utilice un número negativo.
+ text_need_articles: Tienes que %{create_link} un nuevo artículo de existencias antes de poder usarlo aquí.
+ title: Crear nuevo inventario
show:
amount: Cantidad
article: Artículo
+ confirm_delete: '¿Realmente deseas eliminar el inventario?'
date: Fecha
note: Nota
overview: Inventario
supplier: Proveedor
title: Muestra inventario
unit: Unidad
+ stock_takings:
+ confirm_delete: '¿Estás seguro que quieres borrar esto?'
+ date: Fecha
+ note: Nota
+ update:
+ notice: Inventario actualizado.
stockit:
check:
not_empty: "%{name} no se pudo borrar, el inventario no es cero."
copy:
title: Copia artículo de stock
create:
- notice: Se ha creado el nuevo producto en stock "%{name}"
+ notice: Se ha creado el nuevo producto en stock "%{name}"
derive:
title: Añade un artículo en stock desde plantilla
destroy:
@@ -1494,6 +1759,7 @@ es:
show_stock_takings: Resumen del inventario
stock_count: 'Número de artículos'
stock_worth: 'Valor actual del stock:'
+ title: Existencias (%{article_count})
toggle_unavailable: Muestra/esconde los artículos no disponibles
view_options: Ver opciones
new:
@@ -1501,6 +1767,7 @@ es:
title: Añade mi nuevo artículo de stock
show:
change_quantity: Cambia
+ datetime: Hora
new_quantity: Nueva cantidad
reason: Razón
stock_changes: Cambio de cantidades en stock
@@ -1518,6 +1785,7 @@ es:
action_new: Crea un nuevo proveedor/a
articles: artículos (%{count})
confirm_del: Estas seguro de que quieres borrar al proveedor %{name}?
+ deliveries: entregas (%{count})
stock: en stock (%{count})
title: Proveedores
new:
@@ -1583,9 +1851,10 @@ es:
accept_task: Aceptar tarea
confirm_delete_group: Estás seguro/a de que quieres borrar esta tarea y todas las tareas subsecuentes?
confirm_delete_single: Estás seguro/a de que quieres borrar esta tarea?
- confirm_delete_single_from_group: Estás seguro/a de que quieres borrar esta tarea (y mantener las tareas recurrentes relacionadas)?
+ confirm_delete_single_from_group: Estás seguro/a de que quieres borrar esta tarea (y mantener las tareas recurrentes relacionadas)?
delete_group: Borrar esta tarea y las subsecuentes
edit_group: Edita recurrencia
+ hours: "%{count}h"
mark_done: Marca tarea como hecha
reject_task: Rechaza tarea
title: Muestra tarea
@@ -1606,20 +1875,38 @@ es:
back: Volver
cancel: Cancelar
close: Cerrar
+ confirm_delete: '¿Realmente desea eliminar %{name}?'
+ confirm_restore: '¿Realmente desea restaurar %{name}?'
copy: Copia
delete: Eliminar
download: Descarga
edit: Editar
+ marks:
+ close: "×"
+ success:
+ move: Mover
or_cancel: o cancelar
please_wait: Espera...
restore: Restaura
save: Guardar
search_placeholder: Busca ...
show: Mostrar
+ views:
+ pagination:
+ first: "«"
+ last: "»"
+ next: "›"
+ previous: "‹"
+ truncate: "..."
workgroups:
edit:
title: Edita grupo de trabajo
+ error_last_admin_group: El último grupo con derechos de administrador no debe ser eliminado
+ error_last_admin_role: El rol de administrador del último grupo con derechos de administrador no puede ser retirado
index:
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..dd79dab3 100644
--- a/config/locales/fr.yml
+++ b/config/locales/fr.yml
@@ -14,7 +14,7 @@ fr:
gross_price: Prix TTC
manufacturer: Product-rice-eur
name: Nom
- order_number: Numéro
+ order_number: Numéro
order_number_short: Numéro
origin: Lieu de production
price: Prix HT
@@ -417,6 +417,7 @@ fr:
street: Rue
zip_code: Code postal
currency_unit: Monnaie
+ disable_members_overview: Désactiver la liste des membres
name: Nom
distribution_strategy: Stratégie de distribution
distribution_strategy_options:
@@ -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}'
@@ -862,7 +864,7 @@ fr:
error_invite_invalid: Ton invitation n'est pas ou plus valide.
error_token_invalid: Ton jeton de connexion n'est pas ou plus valide, essaie de cliquer à nouveau sur le lien.
reset_password:
- notice: Tu vas maintenant recevoir un message contenant un lien qui te permettra de réinitialiser ton mot de passe.
+ notice: Tu vas maintenant recevoir un message contenant un lien qui te permettra de réinitialiser ton mot de passe.
update_password:
notice: Ton mot de passe a été mis à jour. Tu peux maintenant de connecter.
forgot_password:
@@ -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:
@@ -1098,7 +1097,7 @@ fr:
closed: décomptée
finished: clôturée
open: en cours
- received: reçu
+ received: reçu
update:
notice: La commande a été mise à jour.
update_order_amounts:
@@ -1201,6 +1200,7 @@ fr:
es: Espagnol
fr: Français
nl: Néerlandais
+ tr: Turc
required:
text: requis
'yes': 'Oui'
@@ -1349,7 +1349,7 @@ fr:
notice: La description du boulot a été mise à jour.
notice_converted: Le boulot a été converti en boulot ordinaire (sans répétition).
user:
- more: Tu t'ennuies en ce moment? Il y aura sûrement du boulot pour toi %{tasks_link}.
+ more: Tu t'ennuies en ce moment? Il y aura sûrement du boulot pour toi %{tasks_link}.
tasks_link: par là-bas
title: Ton boulot
title_accepted: Boulots acceptés
@@ -1374,8 +1374,11 @@ fr:
edit:
title: Modifier l'équipe
error_last_admin_group: Impossible de supprimer la dernière cellule avec privilèges administratrices.
- error_last_admin_role: Les privilèges administratrices ne peuvent pas être retirés à la dernière cellule qui les possède.
+ error_last_admin_role: Les privilèges administratrices ne peuvent pas être retirés à la dernière cellule qui les possède.
index:
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..1faaea62 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,22 +26,28 @@ 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:
balance: Tegoed
+ bank_gateway: Bank gateway
description: Omschrijving
iban: IBAN
name: Naam
+ bank_gateway:
+ authorization: Autorisatiekoptekst
+ name: Naam
+ unattended_user: Gebruiker zonder toezicht
+ url: URL
bank_transaction:
amount: Bedrag
date: Datum
- external_id: Extern ID
+ external_id: Externe ID
financial_link: Financiële link
iban: IBAN
reference: Referentie
@@ -51,26 +57,27 @@ nl:
note: Notitie
supplier: Leverancier
document:
- created_at: Upload op
- created_by: Upload door
- data: Data
+ created_at: Aangemaakt op
+ created_by: Aangemaakt door
+ data: Gegevens
mime: MIME-type
name: Naam
financial_transaction:
amount: Bedrag
created_on: Datum
- financial_transaction_class: Financiële transactie klasse
- financial_transaction_type: Financiële transactie type
+ financial_transaction_class: Financiële-transactieklasse
+ financial_transaction_type: Financiële-transactietype
note: Notitie
ordergroup: Huishouden
- user: Ingevuld door
+ user: Ingevoerd door
financial_transaction_class:
+ ignore_for_account_balance: Negeren voor rekeningsaldo
name: Naam
financial_transaction_type:
bank_account: Bankrekening
name: Naam
- financial_transaction_class: Financiële transactie klasse
- name_short: Verkorte naam
+ financial_transaction_class: Klasse financiële transactie
+ name_short: Korte naam
group_order:
ordergroup: Huishouden
price: Totaal bestelling
@@ -81,16 +88,16 @@ nl:
received: Ontvangen
result: Hoeveelheid
tolerance: Tolerantie
- total_price: Som
+ total_price: Totaal
unit_price: Prijs/Eenheid
invoice:
amount: Bedrag
attachment: Bijlage
- created_at: Gemaakt op
- created_by: Gemaakt door
+ created_at: Aangemaakt op
+ created_by: Aangemaakt door
date: Factuurdatum
- delete_attachment: Verwijder bijlage
- deliveries: Voorraad levering
+ delete_attachment: Bijlage verwijderen
+ deliveries: Voorraadlevering
deposit: Statiegeld in rekening gebracht
deposit_credit: Statiegeld teruggekregen
financial_link: Financiële link
@@ -102,7 +109,7 @@ nl:
supplier: Leverancier
mail_delivery_status:
created_at: Tijd
- email: Email
+ email: E-mail
message: Bericht
order:
boxfill: Dozen vullen na
@@ -111,8 +118,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 +131,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 +148,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
@@ -151,10 +158,10 @@ nl:
contact_address: Adres
contact_person: Contactpersoon
contact_phone: Telefoon
- description: Omschrijving
+ description: Beschrijving
ignore_apple_restriction: Bestelstop vanwege appelpunten negeren
last_order: Laatste bestelling
- last_user_activity: Laatst actief
+ last_user_activity: Laatste activiteit
name: Naam
user_tokens: Leden
stock_article:
@@ -173,7 +180,7 @@ nl:
customer_number: Klantnummer
customer_number_short: Klantnr.
delivery_days: Bezorgdagen
- email: Email
+ email: E-mail
fax: Fax
iban: IBAN
is_subscribed: geabonneerd?
@@ -186,9 +193,14 @@ nl:
phone2: Telefoon 2
shared_sync_method: Hoe synchroniseren
url: Homepage
+ supplier_category:
+ name: Naam
+ description: Beschrijving
+ financial_transaction_class: Financiële-transactieklasse
+ bank_account: Bankrekening
task:
- created_by: Gemaakt door
- created_on: Gemaakt op
+ created_by: Aangemaakt door
+ created_on: Aangemaakt op
description: Beschrijving
done: Gedaan?
due_date: Voor wanneer?
@@ -198,11 +210,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_activity: Laatste activiteit
+ last_login: Laatste aanmelding
last_name: Achternaam
name: Naam
nick: Gebruikersnaam
@@ -214,13 +226,13 @@ nl:
one: Werkgroep
other: Werkgroepen
workgroup:
- description: Omschrijving
+ description: Beschrijving
name: Naam
role_admin: Beheer
role_article_meta: Artikelen
role_finance: Financiën
role_invoices: Facturen
- role_orders: Bestellingen
+ role_orders: Beheer bestellingen
role_pickups: Ophaaldagen
role_suppliers: Leveranciers
user_tokens: Leden
@@ -243,21 +255,24 @@ nl:
models:
article: Artikel
article_category: Categorie
+ bank_account: Bankrekening
+ bank_gateway: Betalingsdienst
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
- other: Huishouden
+ other: Huishoudens
stock_article: Voorraadartikel
stock_taking: Inventaris
supplier: Leverancier
+ supplier_category: Leverancierscategorie
task: Taak
user: Gebruiker
workgroup: Werkgroep
@@ -268,36 +283,44 @@ nl:
all_ordergroups: Alle huishoudens
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
+ created_at: aangemaakt op
+ first_paragraph: Hier kun je de groepen en gebruikers van Foodsoft beheren.
+ groupname: Groepsnaam
members: leden
name: naam
new_ordergroup: Nieuw huishouden
new_user: Nieuwe gebruiker
new_workgroup: Nieuwe werkgroep
- newest_groups: Nieuwste groepen
- newest_users: Nieuwste gebruikers
- title: Administratie
- type: Type
- username: Gebruikersnaam
+ newest_groups: nieuwste groepen
+ newest_users: nieuwste gebruikers
+ title: Beheer
+ type: type
+ username: gebruikersnaam
+ bank_accounts:
+ form:
+ title_edit: Bankrekening bewerken
+ title_new: Nieuwe bankrekening toevoegen
+ bank_gateways:
+ form:
+ title_edit: Betalingsdienst bewerken
+ title_new: Nieuwe betalingsdienst toevoegen
configs:
list:
key: Sleutel
title: Configuratielijst
- value: Inhoud
+ value: Waarde
show:
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 +331,32 @@ 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
+ new_bank_gateway: Nieuwe betalingsdienst toevoegen
title: Financiën
- transaction_types: Financiële transactie typen
+ transaction_types: Typen financiële transacties
+ supplier_categories: Leverancierscategorieën
+ new_supplier_category: Nieuwe leverancierscategorie
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 +368,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 +379,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 +426,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
@@ -411,11 +437,15 @@ nl:
workgroups:
members: leden
name: naam
+ supplier_categories:
+ form:
+ title_new: Leverancierscategorie toevoegen
+ title_edit: Leverancierscategorie bewerken
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 +459,7 @@ nl:
title: Categorie bewerken
index:
new: Nieuwe categorie
- title: Categoriën
+ title: Categorieën
new:
title: Nieuwe categorie maken
update:
@@ -440,9 +470,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 +481,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 +502,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 +514,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 +527,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 +542,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,28 +579,28 @@ 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.
currency_space: Spatie toevoegen na valutasymbool.
currency_unit: Valutasymbool voor het tonen van prijzen.
- custom_css: De layout van deze site kan gewijzigd worden door hier cascading stylesheets (CSS) in te voeren. Laat het leeg voor de standaardstijl.
- email_from: Emails zullen lijken verzonden te zijn vanaf dit email adres. Laat het veld leeg om het contactadres van de foodcoop te gebruiken.
+ custom_css: Om de lay-out van deze site aan te passen, kunt u stijlwijzigingen invoeren met behulp van cascading stylesheets (CSS). Laat leeg voor de standaardstijl.
+ email_from: Het zal lijken alsof e-mails verzonden zijn vanaf dit e-mailadres. Laat het veld leeg om het contactadres van de foodcoop te gebruiken.
email_replyto: Vul dit in als je antwoord op mails van Foodsoft wilt ontvangen op een ander adres dan het bovenstaande.
email_sender: Emails worden verzonden vanaf dit emailadres. Om te voorkomen dat emails als spam worden tegengehouden, is het te adviseren het adres van de webserver op te nemen in het SPF record van het email domein.
help_url: Documentatie website.
@@ -626,12 +655,13 @@ nl:
default_role_orders: Bestellingen
default_role_pickups: Ophaaldagen
default_role_suppliers: Leveranciers
- disable_invite: Uitnodigingen deactiveren
- email_from: From adres
- email_replyto: Reply-to adres
- email_sender: Sender adres
- help_url: Documentatie URL
- homepage: Homepage
+ disable_invite: Uitnodigingen uitschakelen
+ disable_members_overview: Ledenlijst deactiveren
+ email_from: Adres afzender
+ email_replyto: Antwoord-adres
+ email_sender: Adres afzender
+ help_url: URL documentatie
+ homepage: Hoofdpagina
ignore_browser_locale: Browsertaal negeren
minimum_balance: Minimum tegoed
name: Naam
@@ -1018,7 +1048,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 +1055,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 +1102,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 +1219,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: "--"
@@ -1310,11 +1340,11 @@ nl:
order_result_supplier:
subject: Nieuwe bestelling voor %{name}
text: |
- Beste mijnheer/mevrouw,
+ Goeiedag,
- Foodcoop %{foodcoop} wil graag een bestelling plaatsen.
+ %{foodcoop} wil graag een bestelling plaatsen.
- Een PDF en spreadsheet vind u meegestuurd.
+ Een PDF en spreadsheet vindt u in bijlage.
Met vriendelijke groet,
%{user}
@@ -1442,9 +1472,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 +1692,7 @@ nl:
es: Spaans
fr: Frans
nl: Nederlands
+ tr: Turks
required:
mark: "*"
text: verplicht
@@ -1874,3 +1902,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.
"
+ else
+ redirect_to new_message_url, alert: I18n.t('messages.new.error_private')
end
end
@@ -33,18 +33,18 @@ class MessagesController < ApplicationController
@message = @current_user.send_messages.new(params[:message])
if @message.save
DeliverMessageJob.perform_later(@message)
- redirect_to messages_url, :notice => I18n.t('messages.create.notice')
+ redirect_to messages_url, notice: I18n.t('messages.create.notice')
else
- render :action => 'new'
+ render action: 'new'
end
end
# Shows a single message.
def show
@message = Message.find(params[:id])
- unless @message.is_readable_for?(current_user)
- redirect_to messages_url, alert: I18n.t('messages.new.error_private')
- end
+ return if @message.is_readable_for?(current_user)
+
+ redirect_to messages_url, alert: I18n.t('messages.new.error_private')
end
def toggle_private
diff --git a/plugins/messages/app/helpers/messages_helper.rb b/plugins/messages/app/helpers/messages_helper.rb
index d386e6df..c385a17f 100644
--- a/plugins/messages/app/helpers/messages_helper.rb
+++ b/plugins/messages/app/helpers/messages_helper.rb
@@ -1,11 +1,11 @@
module MessagesHelper
def format_subject(message, length)
if message.subject.length > length
- subject = truncate(message.subject, :length => length)
- body = ""
+ subject = truncate(message.subject, length: length)
+ body = ''
else
subject = message.subject
- body = truncate(message.body.to_plain_text, :length => length - subject.length)
+ body = truncate(message.body.to_plain_text, length: length - subject.length)
end
"#{link_to(h(subject), message)}#{h(body)}".html_safe
end
diff --git a/plugins/messages/app/mail_receivers/messages_mail_receiver.rb b/plugins/messages/app/mail_receivers/messages_mail_receiver.rb
index e9ca99f3..006c3f8d 100644
--- a/plugins/messages/app/mail_receivers/messages_mail_receiver.rb
+++ b/plugins/messages/app/mail_receivers/messages_mail_receiver.rb
@@ -1,4 +1,4 @@
-require "email_reply_trimmer"
+require 'email_reply_trimmer'
class MessagesMailReceiver
def self.regexp
@@ -9,29 +9,25 @@ class MessagesMailReceiver
@message = Message.find_by_id(match[:message_id])
@user = User.find_by_id(match[:user_id])
- raise "Message could not be found" if @message.nil?
- raise "User could not be found" if @user.nil?
+ raise 'Message could not be found' if @message.nil?
+ raise 'User could not be found' if @user.nil?
hash = @message.mail_hash_for_user(@user)
- raise "Hash does not match expectations" unless hash.casecmp(match[:hash]) == 0
+ raise 'Hash does not match expectations' unless hash.casecmp(match[:hash]) == 0
end
def received(data)
mail = Mail.new data
mail_part = get_mail_part(mail)
- raise "No valid content could be found" if mail_part.nil?
+ raise 'No valid content could be found' if mail_part.nil?
body = mail_part.body.decoded
- unless mail_part.content_type_parameters.nil?
- body = body.force_encoding mail_part.content_type_parameters[:charset]
- end
+ body = body.force_encoding mail_part.content_type_parameters[:charset] unless mail_part.content_type_parameters.nil?
- if MIME::Type.simplified(mail_part.content_type) == "text/html"
- body = Nokogiri::HTML(body).text
- end
+ body = Nokogiri::HTML(body).text if MIME::Type.simplified(mail_part.content_type) == 'text/html'
- body.encode!(Encoding::default_internal)
+ body.encode!(Encoding.default_internal)
body = EmailReplyTrimmer.trim(body)
raise BlankBodyException if body.empty?
@@ -39,16 +35,16 @@ class MessagesMailReceiver
group: @message.group,
private: @message.private,
received_email: data
- if @message.reply_to
- message.reply_to_message = @message.reply_to_message
- else
- message.reply_to_message = @message
- end
- if mail.subject
- message.subject = mail.subject.gsub("[#{FoodsoftConfig[:name]}] ", "")
- else
- message.subject = I18n.t('messages.model.reply_subject', subject: message.reply_to_message.subject)
- end
+ message.reply_to_message = if @message.reply_to
+ @message.reply_to_message
+ else
+ @message
+ end
+ message.subject = if mail.subject
+ mail.subject.gsub("[#{FoodsoftConfig[:name]}] ", '')
+ else
+ I18n.t('messages.model.reply_subject', subject: message.reply_to_message.subject)
+ end
message.add_recipients [@message.sender_id]
message.save!
@@ -64,9 +60,7 @@ class MessagesMailReceiver
for part in mail.parts
part = get_mail_part(part)
content_type = MIME::Type.simplified(part.content_type)
- if content_type == "text/plain" || !mail_part && content_type == "text/html"
- mail_part = part
- end
+ mail_part = part if content_type == 'text/plain' || (!mail_part && content_type == 'text/html')
end
mail_part
end
diff --git a/plugins/messages/app/models/message.rb b/plugins/messages/app/models/message.rb
index b5087d0d..0dd1db19 100644
--- a/plugins/messages/app/models/message.rb
+++ b/plugins/messages/app/models/message.rb
@@ -1,17 +1,17 @@
-require "base32"
+require 'base32'
class Message < ApplicationRecord
- belongs_to :sender, class_name: 'User', foreign_key: 'sender_id'
- belongs_to :group, optional: true, class_name: 'Group', foreign_key: 'group_id'
+ belongs_to :sender, class_name: 'User'
+ belongs_to :group, optional: true, class_name: 'Group'
belongs_to :reply_to_message, optional: true, class_name: 'Message', foreign_key: 'reply_to'
has_many :message_recipients, dependent: :destroy
has_many :recipients, through: :message_recipients, source: :user
attr_accessor :send_method, :recipient_tokens, :order_id
- scope :threads, -> { where(:reply_to => nil) }
- scope :thread, ->(id) { where("id = ? OR reply_to = ?", id, id) }
- scope :readable_for, ->(user) {
+ scope :threads, -> { where(reply_to: nil) }
+ scope :thread, ->(id) { where('id = ? OR reply_to = ?', id, id) }
+ scope :readable_for, lambda { |user|
user_id = user.try(&:id)
joins(:message_recipients)
@@ -20,7 +20,7 @@ class Message < ApplicationRecord
}
validates_presence_of :message_recipients, :subject, :body
- validates_length_of :subject, :in => 1..255
+ validates_length_of :subject, in: 1..255
has_rich_text :body
@@ -35,7 +35,7 @@ class Message < ApplicationRecord
def create_message_recipients
user_ids = @recipients_ids
user_ids += User.undeleted.pluck(:id) if send_method == 'all'
- user_ids += Group.find(group_id).users.pluck(:id) unless group_id.blank?
+ user_ids += Group.find(group_id).users.pluck(:id) if group_id.present?
user_ids += Order.find(order_id).users_ordered.pluck(:id) if send_method == 'order'
user_ids.uniq.each do |user_id|
@@ -49,7 +49,7 @@ class Message < ApplicationRecord
end
def group_id=(group_id)
- group = Group.find(group_id) unless group_id.blank?
+ group = Group.find(group_id) if group_id.present?
if group
@send_method = 'workgroup' if group.type == 'Workgroup'
@send_method = 'ordergroup' if group.type == 'Ordergroup'
@@ -98,29 +98,29 @@ class Message < ApplicationRecord
def mail_hash_for_user(user)
digest = Digest::SHA1.new
- digest.update self.id.to_s
- digest.update ":"
+ digest.update id.to_s
+ digest.update ':'
digest.update salt
- digest.update ":"
+ digest.update ':'
digest.update user.id.to_s
Base32.encode digest.digest
end
# Returns true if this message is a system message, i.e. was sent automatically by Foodsoft itself.
def system_message?
- self.sender_id.nil?
+ sender_id.nil?
end
def sender_name
- system_message? ? I18n.t('layouts.foodsoft') : sender.display rescue "?"
+ system_message? ? I18n.t('layouts.foodsoft') : sender.display
+ rescue StandardError
+ '?'
end
- def recipients_ids
- @recipients_ids
- end
+ attr_reader :recipients_ids
def last_reply
- Message.where(reply_to: self.id).order(:created_at).last
+ Message.where(reply_to: id).order(:created_at).last
end
def is_readable_for?(user)
@@ -137,6 +137,6 @@ class Message < ApplicationRecord
private
def create_salt
- self.salt = [Array.new(6) { rand(256).chr }.join].pack("m").chomp
+ self.salt = [Array.new(6) { rand(256).chr }.join].pack('m').chomp
end
end
diff --git a/plugins/messages/app/models/message_recipient.rb b/plugins/messages/app/models/message_recipient.rb
index e205ea5b..671b557d 100644
--- a/plugins/messages/app/models/message_recipient.rb
+++ b/plugins/messages/app/models/message_recipient.rb
@@ -2,5 +2,5 @@ class MessageRecipient < ActiveRecord::Base
belongs_to :message
belongs_to :user
- enum email_state: [:pending, :sent, :skipped]
+ enum email_state: %i[pending sent skipped]
end
diff --git a/plugins/messages/app/models/messagegroup.rb b/plugins/messages/app/models/messagegroup.rb
index 7c7f6c03..93666dd5 100644
--- a/plugins/messages/app/models/messagegroup.rb
+++ b/plugins/messages/app/models/messagegroup.rb
@@ -1,5 +1,3 @@
class Messagegroup < Group
validates_uniqueness_of :name
-
- protected
end
diff --git a/plugins/messages/config/locales/de.yml b/plugins/messages/config/locales/de.yml
index eb8cff21..2f423dc1 100644
--- a/plugins/messages/config/locales/de.yml
+++ b/plugins/messages/config/locales/de.yml
@@ -20,6 +20,7 @@ de:
workgroup_id: Arbeitsgruppe
messagegroup:
description: Beschreibung
+ name: Name
user_tokens: Mitglieder
models:
message: Nachricht
@@ -84,6 +85,7 @@ de:
model:
reply_header: ! '%{user} schrieb am %{when}:'
reply_indent: ! '> %{line}'
+ reply_subject: ! 'Re: %{subject}'
new:
error_private: Nachricht ist privat!
hint_private: Nachricht erscheint nicht im Foodsoft Posteingang
diff --git a/plugins/messages/config/locales/es.yml b/plugins/messages/config/locales/es.yml
index 3b505e79..81a9a206 100644
--- a/plugins/messages/config/locales/es.yml
+++ b/plugins/messages/config/locales/es.yml
@@ -59,6 +59,7 @@ es:
write_message: Escribir un mensaje
messagegroups:
index:
+ body: 'Un grupo de mensajes es como una lista de correo: puedes unirte (o salir) a cualquiera de ellos para recibir las actualizaciones enviadas a ese grupo.'
title: Grupos de mensaje
join:
error: 'No pudo unirse al grupo de mensaje: %{error}'
@@ -72,27 +73,38 @@ es:
messages:
actionbar:
message_threads: Muestra como hilos
+ messagegroups: Suscribirse a este grupo
messages: Muestra como lista
new: Nuevo mensaje
+ create:
+ notice: El mensaje ha sido guardado y será enviado.
index:
title: Mensajes
messages:
reply: Responde
+ model:
+ reply_header: ! '%{user} escribió en %{when}:'
+ reply_indent: ! '> %{line}'
+ reply_subject: ! 'Re: %{subject}'
new:
error_private: Lo siento, este mensaje es privado.
+ hint_private: El mensaje no se muestra en el buzón de correo Foodsoft
list:
desc: ! 'Envía mensajes a todos los miembros a través de la lista de correo: %{list}'
mail: por ejemplo con un email a %{email}.
subscribe: Puedes leer más sobre la lista de correos en %{link}.
subscribe_msg: Quizás tengas que suscribirte a la lista primero.
+ wiki: Wiki (lista de correo de páginas)
message: mensaje
no_user_found: No se ha encontrado el usuario
+ order_item: "%{supplier_name} (Recoger: %{pickup})"
reply_to: Este mensaje es una respuesta a otro %{link}.
search: Busca ...
search_user: Busca usuario
title: Nuevo mensaje
show:
all_messages: Todos los mensajes
+ change_visibility: 'Cambiar'
from: ! 'De:'
group: 'Grupo:'
reply: Responde
@@ -101,19 +113,35 @@ es:
subject: ! 'Asunto:'
title: Muestra mensaje
to: 'A:'
+ visibility: 'Visibilidad:'
+ visibility_private: 'Privado'
+ visibility_public: 'Público'
thread:
all_message_threads: Todos los hilos de mensaje
reply: Responde
+ toggle_private:
+ not_allowed: No puede cambiar la visibilidad del mensaje.
message_threads:
groupmessage_threads:
show_message_threads: muestra todos
index:
+ general: General
title: Hilos de mensaje
message_threads:
last_reply_at: Última respuesta el
- last_reply_by: Última respuesta de
+ last_reply_by: Última respuesta de
started_at: Comenzado el
started_by: Comenzado por
+ show:
+ general: General
+ messages_mailer:
+ foodsoft_message:
+ footer: |
+ Respuesta: %{reply_url}
+ Ver mensaje en línea: %{msg_url}
+ Opciones de mensaje: %{profile_url}
+ footer_group: |
+ Enviado al grupo: %{group}
navigation:
admin:
messagegroups: Grupos de mensaje
diff --git a/plugins/messages/config/locales/tr.yml b/plugins/messages/config/locales/tr.yml
new file mode 100644
index 00000000..002d1c9b
--- /dev/null
+++ b/plugins/messages/config/locales/tr.yml
@@ -0,0 +1,156 @@
+tr:
+ activerecord:
+ attributes:
+ message:
+ body: Mesaj İçeriği
+ messagegroup_id: Mesaj Grubu
+ order_id: Sipariş
+ ordergroup_id: Sipariş Grubu
+ private: Özel
+ recipient_tokens: (Ek) alıcılar
+ send_method:
+ all: Tüm üyelere gönder
+ recipients: Belirli üyelere gönder
+ order: Bir siparişe katılan üyelere gönder
+ ordergroup: Bir sipariş grubunun üyelerine gönder
+ messagegroup: Bir mesaj grubunun üyelerine gönder
+ workgroup: Bir iş grubunun üyelerine gönder
+ send_to_all: Tüm üyelere gönder
+ subject: Konu
+ workgroup_id: İş Grubu
+ messagegroup:
+ description: Açıklama
+ name: Ad
+ user_tokens: Üyeler
+ models:
+ message: Mesaj
+ messagegroup: Mesaj grubu
+ admin:
+ ordergroups:
+ show:
+ send_message: Mesaj gönder
+ users:
+ show:
+ send_message: Mesaj gönder
+ config:
+ hints:
+ mailing_list: Tüm üyelere için mesajlaşma sistemi yerine kullanılabilecek posta listesi e-posta adresi.
+ mailing_list_subscribe: Üyelerin abone olmak için bir e-posta gönderebileceği e-posta adresi.
+ use_messages: Üyelerin Foodsoft içinde birbirleriyle iletişim kurmasına izin ver.
+ keys:
+ use_messages: Mesajlar
+ mailing_list: Posta Listesi
+ mailing_list_subscribe: Posta Listesi Aboneliği
+ helpers:
+ messages:
+ write_message: Mesaj yaz
+ submit:
+ message:
+ create: Mesaj gönder
+ home:
+ index:
+ messages:
+ title: En yeni mesajlar
+ view_all:
+ text: '%{messages} veya %{threads} göster'
+ messages: tüm mesajlar
+ threads: konular
+ start_nav:
+ write_message: Mesaj yaz
+ messagegroups:
+ index:
+ body: 'Bir mesaj grubu, bir posta listesi gibi: o gruba üye olabilir (veya çıkabilir) ve o gruba gönderilen güncellemeleri alabilirsiniz.'
+ title: Mesaj grupları
+ join:
+ error: 'Mesaj grubuna katılamadı: %{error}'
+ notice: Mesaj grubuna katıldınız
+ leave:
+ error: 'Mesaj grubu terk edilemedi: %{error}'
+ notice: Mesaj grubundan ayrıldınız
+ messagegroup:
+ join: Mesaj grubuna katıl
+ leave: Mesaj grubundan ayrıl
+ messages:
+ actionbar:
+ message_threads: Konu olarak göster
+ messagegroups: Gruplara abone ol
+ messages: Liste olarak göster
+ new: Yeni mesaj
+ create:
+ notice: Mesaj kaydedildi ve gönderilecek.
+ index:
+ title: Mesajlar
+ messages:
+ reply: Yanıtla
+ model:
+ reply_header: ! '%{user} %{when} tarihinde yazdı:'
+ reply_indent: ! '> %{line}'
+ reply_subject: ! 'Yanıt: %{subject}'
+ new:
+ error_private: Üzgünüz, bu mesaj özel.
+ hint_private: Mesaj Foodsoft posta kutusunda gösterilmez.
+ list:
+ desc: ! 'Lütfen tüm mesajları şu mailing-liste gönderin: %{list}'
+ mail: örneğin %{email} adresine bir e-posta ile.
+ subscribe: 'E-posta listesi hakkında daha fazla bilgi edinebilirsiniz: %{link}.'
+ subscribe_msg: Önce e-posta listesine kaydolmanız gerekebilir.
+ wiki: Wiki (page Posta-listesi)
+ message: mesaj
+ no_user_found: Kullanıcı bulunamadı.
+ order_item: "%{supplier_name} (Pickup: %{pickup})"
+ reply_to: Bu mesaj, başka bir %{link} yanıtıdır.
+ search: Ara ...
+ search_user: Kullanıcı ara
+ title: Yeni mesaj
+ show:
+ all_messages: Tüm mesajlar
+ change_visibility: 'Değiştir'
+ from: ! 'Kimden:'
+ group: 'Grup:'
+ reply: Yanıtla
+ reply_to: 'Yanıtla:'
+ sent_on: ! 'Gönderildi:'
+ subject: ! 'Konu:'
+ title: Mesajı Göster
+ to: 'Kime:'
+ visibility: 'Görünürlük:'
+ visibility_private: 'Özel'
+ visibility_public: 'Genel'
+ thread:
+ all_message_threads: Tüm mesaj konuları
+ reply: Yanıtla
+ toggle_private:
+ not_allowed: Mesajın görünürlüğünü değiştiremezsiniz.
+ message_threads:
+ groupmessage_threads:
+ show_message_threads: tümünü göster
+ index:
+ general: Genel
+ title: Mesaj Konuları
+ message_threads:
+ last_reply_at: Son yanıt tarihi
+ last_reply_by: Son yanıtlayan
+ started_at: Başlangıç tarihi
+ started_by: Başlatan
+ show:
+ general: Genel
+ messages_mailer:
+ foodsoft_message:
+ footer: |
+ Yanıt: %{reply_url}
+ Mesajı çevrimiçi görüntüle: %{msg_url}
+ Mesajlaşma seçenekleri:: %{profile_url}
+ footer_group: |
+ Gruba gönderildi: %{group}
+ navigation:
+ admin:
+ messagegroups: Mesaj grupları
+ messages: Mesajlar
+ shared:
+ user_form_fields:
+ messagegroups: Mesaj gruplarına katıl veya ayrıl
+ simple_form:
+ labels:
+ settings:
+ messages:
+ send_as_email: Mesajları e-posta olarak al
diff --git a/plugins/messages/config/routes.rb b/plugins/messages/config/routes.rb
index d66eebdd..6d276428 100644
--- a/plugins/messages/config/routes.rb
+++ b/plugins/messages/config/routes.rb
@@ -1,13 +1,13 @@
Rails.application.routes.draw do
scope '/:foodcoop' do
- resources :messages, :only => [:index, :show, :new, :create] do
+ resources :messages, only: %i[index show new create] do
member do
get :thread
post :toggle_private
end
end
- resources :message_threads, :only => [:index, :show]
+ resources :message_threads, only: %i[index show]
resources :messagegroups, only: [:index] do
member do
diff --git a/plugins/messages/db/migrate/20160226000000_add_email_to_message.rb b/plugins/messages/db/migrate/20160226000000_add_email_to_message.rb
index 411600c7..034b023b 100644
--- a/plugins/messages/db/migrate/20160226000000_add_email_to_message.rb
+++ b/plugins/messages/db/migrate/20160226000000_add_email_to_message.rb
@@ -1,6 +1,6 @@
class AddEmailToMessage < ActiveRecord::Migration[4.2]
def change
add_column :messages, :salt, :string
- add_column :messages, :received_email, :binary, :limit => 1.megabyte
+ add_column :messages, :received_email, :binary, limit: 1.megabyte
end
end
diff --git a/plugins/messages/foodsoft_messages.gemspec b/plugins/messages/foodsoft_messages.gemspec
index 0dfc7163..e7967191 100644
--- a/plugins/messages/foodsoft_messages.gemspec
+++ b/plugins/messages/foodsoft_messages.gemspec
@@ -1,25 +1,26 @@
-$:.push File.expand_path("../lib", __FILE__)
+$:.push File.expand_path('lib', __dir__)
# Maintain your gem's version:
-require "foodsoft_messages/version"
+require 'foodsoft_messages/version'
# Describe your gem and declare its dependencies:
Gem::Specification.new do |s|
- s.name = "foodsoft_messages"
+ s.name = 'foodsoft_messages'
s.version = FoodsoftMessages::VERSION
- s.authors = ["robwa"]
- s.email = ["foodsoft-messages@ini.tiative.net"]
- s.homepage = "https://github.com/foodcoops/foodsoft"
- s.summary = "Messaging plugin for foodsoft."
- s.description = "Adds the ability to exchange messages to foodsoft."
+ s.authors = ['robwa']
+ s.email = ['foodsoft-messages@ini.tiative.net']
+ s.homepage = 'https://github.com/foodcoops/foodsoft'
+ s.summary = 'Messaging plugin for foodsoft.'
+ s.description = 'Adds the ability to exchange messages to foodsoft.'
- s.files = Dir["{app,config,db,lib}/**/*"] + ["Rakefile", "README.md"]
+ s.files = Dir['{app,config,db,lib}/**/*'] + ['Rakefile', 'README.md']
- s.add_dependency "rails"
- s.add_dependency "base32"
- s.add_dependency "deface", "~> 1.0"
- s.add_dependency "email_reply_trimmer"
- s.add_dependency "mail"
+ s.add_dependency 'rails'
+ s.add_dependency 'base32'
+ s.add_dependency 'deface', '~> 1.0'
+ s.add_dependency 'email_reply_trimmer'
+ s.add_dependency 'mail'
- s.add_development_dependency "sqlite3"
+ s.add_development_dependency 'sqlite3'
+ s.metadata['rubygems_mfa_required'] = 'true'
end
diff --git a/plugins/messages/lib/foodsoft_messages.rb b/plugins/messages/lib/foodsoft_messages.rb
index b457c8f1..9fc71928 100644
--- a/plugins/messages/lib/foodsoft_messages.rb
+++ b/plugins/messages/lib/foodsoft_messages.rb
@@ -1,7 +1,7 @@
-require "foodsoft_messages/engine"
-require "foodsoft_messages/mail_receiver"
-require "foodsoft_messages/user_link"
-require "deface"
+require 'foodsoft_messages/engine'
+require 'foodsoft_messages/mail_receiver'
+require 'foodsoft_messages/user_link'
+require 'deface'
module FoodsoftMessages
# Return whether messages are used or not.
diff --git a/plugins/messages/lib/foodsoft_messages/engine.rb b/plugins/messages/lib/foodsoft_messages/engine.rb
index 0f67abb7..f054ada6 100644
--- a/plugins/messages/lib/foodsoft_messages/engine.rb
+++ b/plugins/messages/lib/foodsoft_messages/engine.rb
@@ -12,15 +12,16 @@ module FoodsoftMessages
sub_nav.items.insert(i, sub_nav.items.delete_at(-1))
end
end
- unless primary[:admin].nil?
- sub_nav = primary[:admin].sub_navigation
- sub_nav.items <<
- SimpleNavigation::Item.new(primary, :messagegroups, I18n.t('navigation.admin.messagegroups'), context.admin_messagegroups_path)
- # move to right before config item
- if i = sub_nav.items.index(sub_nav[:config])
- sub_nav.items.insert(i, sub_nav.items.delete_at(-1))
- end
- end
+ return if primary[:admin].nil?
+
+ sub_nav = primary[:admin].sub_navigation
+ sub_nav.items <<
+ SimpleNavigation::Item.new(primary, :messagegroups, I18n.t('navigation.admin.messagegroups'),
+ context.admin_messagegroups_path)
+ # move to right before config item
+ return unless i = sub_nav.items.index(sub_nav[:config])
+
+ sub_nav.items.insert(i, sub_nav.items.delete_at(-1))
end
def default_foodsoft_config(cfg)
diff --git a/plugins/messages/lib/foodsoft_messages/user_link.rb b/plugins/messages/lib/foodsoft_messages/user_link.rb
index bfab42b6..6fcf99c4 100644
--- a/plugins/messages/lib/foodsoft_messages/user_link.rb
+++ b/plugins/messages/lib/foodsoft_messages/user_link.rb
@@ -8,7 +8,7 @@ module FoodsoftMessages
show_user user
else
link_to show_user(user), new_message_path('message[mail_to]' => user.id),
- :title => I18n.t('helpers.messages.write_message')
+ title: I18n.t('helpers.messages.write_message')
end
end
end
@@ -18,5 +18,5 @@ end
# modify existing helper
ActiveSupport.on_load(:after_initialize) do
- ApplicationHelper.send :include, FoodsoftMessages::UserLink
+ ApplicationHelper.include FoodsoftMessages::UserLink
end
diff --git a/plugins/messages/lib/foodsoft_messages/version.rb b/plugins/messages/lib/foodsoft_messages/version.rb
index 2da75575..6209100d 100644
--- a/plugins/messages/lib/foodsoft_messages/version.rb
+++ b/plugins/messages/lib/foodsoft_messages/version.rb
@@ -1,3 +1,3 @@
module FoodsoftMessages
- VERSION = "0.0.1"
+ VERSION = '0.0.1'
end
diff --git a/plugins/mollie/.gitignore b/plugins/mollie/.gitignore
new file mode 100644
index 00000000..1dfe31e6
--- /dev/null
+++ b/plugins/mollie/.gitignore
@@ -0,0 +1,7 @@
+.bundle/
+log/*.log
+pkg/
+test/dummy/db/*.sqlite3
+test/dummy/log/*.log
+test/dummy/tmp/
+test/dummy/.sass-cache
diff --git a/plugins/mollie/Gemfile b/plugins/mollie/Gemfile
new file mode 100644
index 00000000..65f6a440
--- /dev/null
+++ b/plugins/mollie/Gemfile
@@ -0,0 +1,6 @@
+source "http://rubygems.org"
+
+# Declare your gem's dependencies in foodsoft_mollie.gemspec.
+# Bundler will treat runtime dependencies like base dependencies, and
+# development dependencies will be added by default to the :development group.
+gemspec
diff --git a/plugins/mollie/LICENSE b/plugins/mollie/LICENSE
new file mode 100644
index 00000000..d70e2797
--- /dev/null
+++ b/plugins/mollie/LICENSE
@@ -0,0 +1,635 @@
+FoodSoft - a webbased foodcoop management software
+Copyright (C) 2013 wvengen
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc.
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
diff --git a/plugins/mollie/README.md b/plugins/mollie/README.md
new file mode 100644
index 00000000..0663feb5
--- /dev/null
+++ b/plugins/mollie/README.md
@@ -0,0 +1,37 @@
+FoodsoftMollie
+==============
+
+This project adds support for iDEAL payments using Mollie to Foodsoft.
+
+* Make sure the gem is uncommented in foodsoft's `Gemfile`
+* Enter your Mollie account details in `config/app_config.yml`
+
+```yaml
+ # Mollie payment settings
+ mollie:
+ # API key for account: 1234567, website profile: FooInc
+ api_key: test_1234567890abcdef1234567890abcd
+ # Transaction fee per payment method, fixed rate and/or percentage.
+ # This is substracted from the amount actually credited to the ordergroup's account balance.
+ fee:
+ # example fees from May 2014 incl. 21% VAT (verify before using!)
+ ideal: 1.20
+ banktransfer: 0.30
+ creditcard: 3.39% + 0.05
+ paypal: 0.18 + 0.35 + 3.4%
+```
+
+The transaction fee is sub will be added on each payment when set; it is not set by default,
+meaning that the foodcoop will pay any transaction costs (out of the margin).
+
+To initiate a payment, redirect to `new_payments_mollie_path` at `/:foodcoop/payments/mollie/new`.
+The following url parameters are recognised:
+* ''amount'' - default amount to charge (optional)
+* ''fixed'' - when "true", the amount cannot be changed (optional)
+* ''title'' - page title (optional)
+* ''label'' - label for amount (optional)
+* ''min'' - minimum amount accepted (optional)
+
+This plugin also introduces the foodcoop config option `use_mollie`, which can
+be set to `false` to disable this plugin's functionality. May be useful in
+multicoop deployments.
diff --git a/plugins/mollie/Rakefile b/plugins/mollie/Rakefile
new file mode 100755
index 00000000..05eca61d
--- /dev/null
+++ b/plugins/mollie/Rakefile
@@ -0,0 +1,26 @@
+#!/usr/bin/env rake
+begin
+ require 'bundler/setup'
+rescue LoadError
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
+end
+begin
+ require 'rdoc/task'
+rescue LoadError
+ require 'rdoc/rdoc'
+ require 'rake/rdoctask'
+ RDoc::Task = Rake::RDocTask
+end
+
+RDoc::Task.new(:rdoc) do |rdoc|
+ rdoc.rdoc_dir = 'rdoc'
+ rdoc.title = 'FoodsoftMollie'
+ rdoc.options << '--line-numbers'
+ rdoc.rdoc_files.include('README.rdoc')
+ rdoc.rdoc_files.include('lib/**/*.rb')
+end
+
+# APP_RAKEFILE = File.expand_path("../../../Rakefile", __FILE__)
+# load 'rails/tasks/engine.rake'
+
+Bundler::GemHelper.install_tasks
diff --git a/plugins/mollie/app/controllers/payments/mollie_ideal_controller.rb b/plugins/mollie/app/controllers/payments/mollie_ideal_controller.rb
new file mode 100644
index 00000000..c53d667c
--- /dev/null
+++ b/plugins/mollie/app/controllers/payments/mollie_ideal_controller.rb
@@ -0,0 +1,160 @@
+# Mollie payment page
+class Payments::MollieIdealController < ApplicationController
+ before_action -> { require_plugin_enabled FoodsoftMollie }
+ skip_before_action :authenticate, :only => [:check]
+ skip_before_action :verify_authenticity_token, :only => [:check]
+ before_action :accept_return_to, only: [:new]
+ before_action :ordergroup, only: [:new, :create, :result]
+ before_action :transaction, only: [:result]
+ before_action :configure_api_key
+
+ def new
+ @amount = (params[:amount] or [10, -@ordergroup.get_available_funds].max)
+ @amount = [params[:min], params[:amount]].max if params[:min]
+ end
+
+ def create
+ # store parameters so we can redirect to original form on problems
+ session[:mollie_params] = params.select { |k, _| %w[amount label title fixed min text].include?(k) }.to_h
+
+ amount = params[:amount].to_f
+ amount = [params[:min].to_f, amount].max if params[:min]
+
+ redirect_to new_payments_mollie_path(session[:mollie_params]), alert: t('.invalid_amount') and return if amount <= 0
+
+ ft_type = FinancialTransactionType.find_by_id(FoodsoftConfig[:mollie][:financial_transaction_type]) || FinancialTransactionType.first
+
+ @transaction = FinancialTransaction.create!(
+ amount: nil,
+ ordergroup: @ordergroup,
+ user: @current_user,
+ payment_plugin: 'mollie',
+ payment_amount: amount,
+ # @todo payment_currency
+ payment_state: 'created',
+ financial_transaction_type_id: ft_type.id,
+ note: t('.controller.transaction_note', method: nil)
+ )
+
+ payment = Mollie::Payment.create(
+ amount: {
+ value: format('%.2f', amount),
+ currency: 'EUR' # @todo payment_currency
+ },
+ description: "#{@transaction.id}, #{@ordergroup.id}, #{FoodsoftConfig[:name]}",
+ redirectUrl: result_payments_mollie_url(id: @transaction.id),
+ webhookUrl: (request.local? ? check_payments_mollie_url : 'https://example.com'), # Mollie doesn't accept localhost here
+ metadata: {
+ scope: FoodsoftConfig.scope,
+ transaction_id: @transaction.id,
+ user: @current_user.id,
+ ordergroup: @ordergroup.id
+ }
+ )
+ @transaction.update payment_id: payment.id, payment_state: 'pending'
+
+ logger.info "Mollie start: #{amount} for ##{@current_user.id} (#{@current_user.display})"
+
+ redirect_to payment.checkout_url, allow_other_host: true
+ rescue Mollie::Exception => e
+ Rails.logger.info "Mollie create warning: #{e}"
+ redirect_to new_payments_mollie_path(session[:mollie_params]), :alert => t('errors.general_msg', msg: e.message)
+ end
+
+ # Endpoint that Mollie calls when a payment status changes.
+ def check
+ logger.info "Mollie check: #{params[:id]}"
+ @transaction = FinancialTransaction.find_by_payment_plugin_and_payment_id!('mollie', params[:id])
+ logger.debug " financial transaction: #{@transaction.inspect}"
+ render plain: update_transaction(@transaction)
+ rescue StandardError => e
+ Rails.logger.error "Mollie check error: #{e}"
+ render plain: "Error: #{e.message}"
+ end
+
+ # User is redirect here after payment
+ def result
+ update_transaction @transaction # @todo if request.local? # so localhost works too
+ logger.info "Mollie result: transaction #{@transaction.id} (#{@transaction.payment_id}) is #{@transaction.payment_state}"
+ case @transaction.payment_state
+ when 'paid'
+ redirect_to_return_or root_path, :notice => t('.controller.result.notice', amount: @transaction.amount, fee: @transaction.payment_fee)
+ when 'pending'
+ redirect_to_return_or root_path, :notice => t('.controller.result.wait')
+ else
+ pms = { foodcoop: FoodsoftConfig.scope }.merge((session[:mollie_params] or {}))
+ session[:mollie_params] = nil
+ redirect_to new_payments_mollie_path(pms), :alert => t('.controller.result.failed')
+ end
+ end
+
+ def cancel
+ redirect_to_return_or root_path
+ end
+
+ protected
+
+ def ordergroup
+ @ordergroup = current_user.ordergroup
+ redirect_to root_path, alert: t('.no_ordergroup') and return if @ordergroup.nil?
+ end
+
+ def transaction
+ @transaction = @ordergroup.financial_transactions.find(params[:id])
+ end
+
+ # @todo move this to ApplicationController, use it in SessionController too
+ # @todo use a stack of return_to urls
+ def accept_return_to
+ session[:return_to] = nil # or else an unfollowed previous return_to may interfere
+ return if params[:return_to].blank?
+
+ return unless params[:return_to].starts_with?(root_path) || params[:return_to].starts_with?(root_url)
+
+ session[:return_to] = params[:return_to]
+ end
+
+ def redirect_to_return_or(fallback_url, options = {})
+ if session[:return_to].present?
+ redirect_to_url = session[:return_to]
+ session[:return_to] = nil
+ else
+ redirect_to_url = fallback_url
+ end
+ redirect_to redirect_to_url, options
+ end
+
+ # Query Mollie status and update financial transaction
+ def update_transaction(transaction)
+ payment = Mollie::Payment.get transaction.payment_id
+ logger.debug "Mollie update_transaction: #{payment.inspect}"
+ update_transaction_details(transaction, payment)
+ update_transaction_amount(transaction, payment)
+ payment.status
+ end
+
+ def update_transaction_amount(transaction, payment)
+ if payment.status == 'paid'
+ payment_fee = FoodsoftMollie.payment_fee payment.amount.value, transaction.payment_method
+ amount = payment.amount.value.to_f - payment_fee.to_f
+ end
+ transaction.update payment_state: payment.status, amount: amount || 0, payment_fee: payment_fee || nil
+ end
+
+ def update_transaction_details(transaction, payment)
+ if payment.details
+ transaction.payment_acct_number = payment.details.consumerAccount
+ transaction.payment_acct_name = payment.details.consumerName
+ end
+ transaction.payment_method = payment.method
+ transaction.note = t('.controller.transaction_note', method: payment.method)
+ end
+
+ private
+
+ def configure_api_key
+ Mollie::Client.configure do |config|
+ config.api_key = FoodsoftConfig[:mollie]['api_key']
+ end
+ end
+end
diff --git a/plugins/mollie/app/overrides/admin/configs/_tab_others/add_config.html.haml.deface b/plugins/mollie/app/overrides/admin/configs/_tab_others/add_config.html.haml.deface
new file mode 100644
index 00000000..532fd27d
--- /dev/null
+++ b/plugins/mollie/app/overrides/admin/configs/_tab_others/add_config.html.haml.deface
@@ -0,0 +1,12 @@
+/ insert_after 'erb:contains(":webstats_tracking_code")'
+%h4= 'Mollie'
+= config_input form, :use_mollie, as: :boolean
+= form.fields_for :mollie do |fields|
+ = config_input fields, :api_key, input_html: {class: 'input-xlarge'}
+ = config_input fields, :financial_transaction_type, :as => :select, :collection => FinancialTransactionType.order(:name).map { |t| [ t.name, t.id ] }
+ %h5= 'Fee'
+ = fields.fields_for :fee do |fields|
+ = config_input fields, :ideal, input_html: {class: 'input-xlarge'}
+ = config_input fields, :banktransfer, input_html: {class: 'input-xlarge'}
+ = config_input fields, :creditcard, input_html: {class: 'input-xlarge'}
+ = config_input fields, :paypal, input_html: {class: 'input-xlarge'}
\ No newline at end of file
diff --git a/plugins/mollie/app/overrides/home/index/new_payment_link.html.haml.deface b/plugins/mollie/app/overrides/home/index/new_payment_link.html.haml.deface
new file mode 100644
index 00000000..7ece816d
--- /dev/null
+++ b/plugins/mollie/app/overrides/home/index/new_payment_link.html.haml.deface
@@ -0,0 +1,4 @@
+/ insert_after 'erb[silent]:contains("")'
+= link_to new_payments_mollie_path do
+ = t '.credit_your_account'
+ %i.icon.icon-chevron-right
diff --git a/plugins/mollie/app/overrides/home/ordergroup/new_payment_button.html.haml.deface b/plugins/mollie/app/overrides/home/ordergroup/new_payment_button.html.haml.deface
new file mode 100644
index 00000000..68d441c4
--- /dev/null
+++ b/plugins/mollie/app/overrides/home/ordergroup/new_payment_button.html.haml.deface
@@ -0,0 +1,2 @@
+/ insert_after 'erb[silent]:contains("")'
+= link_to t('.credit_your_account'), new_payments_mollie_path, class: 'btn btn-secondary'
diff --git a/plugins/mollie/app/views/payments/mollie_ideal/_form.html.haml b/plugins/mollie/app/views/payments/mollie_ideal/_form.html.haml
new file mode 100644
index 00000000..cf415b5e
--- /dev/null
+++ b/plugins/mollie/app/views/payments/mollie_ideal/_form.html.haml
@@ -0,0 +1,60 @@
+- content_for :javascript do
+ :javascript
+ // @todo code duplication of foodsoft_mollie.rb
+ function paymentFee(amount, feeSpec) {
+ if (typeof feeSpec === 'number') {
+ return feeSpec;
+ }
+
+ return feeSpec.split('+').reduce((sum, c) => {
+ const parsed = c.trim().match(/^(.*)\s*%\s*$/);
+ if (parsed) {
+ return sum + (parseFloat(parsed[1]) / 100 * parseFloat(amount));
+ } else {
+ return sum + parseFloat(c);
+ }
+ }, 0).toFixed(2);
+ }
+
+ function handleInputAmount(){
+ var amount = parseFloat($('#amount').val());
+ var isError = false;
+ $('#fee_list').children('#fee').each(function(){
+ var fee = $(this).data('fee');
+ if (amount){
+ $(this).text(I18n.l("currency", paymentFee(amount, fee)));
+ } else {
+ $(this).text(fee);
+ }
+ });
+ }
+
+ $('#amount').on('keyup', handleInputAmount);
+ $(document).ready(handleInputAmount);
+
+%h5= t '.fee'
+%dl.dl-horizontal#fee_list
+ - FoodsoftConfig[:mollie][:fee].each do |k, v|
+ %dt= k
+ %dd{id: "fee", data: { fee: v}}"
+= form_tag payments_mollie_path, method: :post do
+ - if params[:text]
+ .well= params[:text]
+ .control-group
+ .control-label
+ = label_tag 'amount', ((params[:label] or t('.amount_pay')))
+ .controls
+ .input-prepend
+ %span.add-on= t 'number.currency.format.unit'
+ = text_field_tag 'amount', @amount, readonly: (params[:fixed]=='true'), class: 'input-mini'
+ - if params[:min]
+ .help-inline{style: 'margin-bottom: 10px'}
+ = "(min #{number_to_currency params[:min], precision: 0})"
+ .control-group
+ .controls
+ = submit_tag t('.submit')
+ = link_to t('ui.or_cancel'), cancel_payments_mollie_path
+
+-# pass through options to allow reusing on error
+- %w(label title fixed min text).each do |k|
+ = hidden_field_tag k, params[k] if params[k]
diff --git a/plugins/mollie/app/views/payments/mollie_ideal/new.html.haml b/plugins/mollie/app/views/payments/mollie_ideal/new.html.haml
new file mode 100644
index 00000000..b00bfe3f
--- /dev/null
+++ b/plugins/mollie/app/views/payments/mollie_ideal/new.html.haml
@@ -0,0 +1,2 @@
+- title (params[:title] or t('.title'))
+= render :partial => 'form'
diff --git a/plugins/mollie/config/locales/en.yml b/plugins/mollie/config/locales/en.yml
new file mode 100644
index 00000000..81b3fbf1
--- /dev/null
+++ b/plugins/mollie/config/locales/en.yml
@@ -0,0 +1,35 @@
+en:
+ activerecord:
+ attributes:
+ home:
+ credit_your_account: 'Credit your Account'
+ payments:
+ mollie_ideal:
+ new:
+ title: 'Credit your account'
+ no_ordergroup: 'You need to be member of an ordergroup'
+ create:
+ invalid_amount: 'Invalid amount'
+ form:
+ amount_pay: 'Amount to pay'
+ method: 'Pay using'
+ submit: 'Pay at your bank'
+ financial_transaction_type: 'Financial Transaction Type'
+ fee: 'The transaction fee depends on your payment method'
+ controller:
+ result:
+ notice: 'Your account was credited %{amount} (transaction fee of %{fee}).'
+ failed: 'Payment failed.'
+ wait: 'Your account will be credited when the payment is received.'
+ transaction_note: '%{method} payment'
+ config:
+ keys:
+ use_mollie: 'Use Mollie'
+ mollie:
+ api_key: 'API key'
+ financial_transaction_type: 'Transaction type'
+ fee:
+ ideal: 'Ideal'
+ banktransfer: 'banktransfer'
+ creditcard: 'creditcard'
+ paypal: 'paypal'
\ No newline at end of file
diff --git a/plugins/mollie/config/locales/nl.yml b/plugins/mollie/config/locales/nl.yml
new file mode 100644
index 00000000..93427675
--- /dev/null
+++ b/plugins/mollie/config/locales/nl.yml
@@ -0,0 +1,33 @@
+nl:
+ activerecord:
+ attributes:
+ home:
+ credit_your_account: 'Crediteer uw account'
+ payments:
+ mollie_ideal:
+ new:
+ title: 'Betalen'
+ no_ordergroup: 'U dient lid te zijn van een ordergroep'
+ create:
+ invalid_amount: 'Ongeldig bedrag'
+ form:
+ amount_pay: 'Te betalen bedrag'
+ method: 'Hoe te betalen'
+ submit: 'Betalen'
+ financial_transaction_type: 'Financiële-transactietype'
+ fee: 'De transactiekosten van uw betalingsmiddel zijn'
+ controller:
+ result:
+ notice: ' Er is %{amount} bijgeschreven op uw account (transactiekosten van ${fee}).'
+ failed: 'Betaling mislukt.'
+ config:
+ keys:
+ use_mollie: 'Gebruik Mollie'
+ mollie:
+ api_key: 'API key'
+ financial_transaction_type: 'Transactie type'
+ fee:
+ ideal: 'Ideal'
+ banktransfer: 'banktransfer'
+ creditcard: 'creditcard'
+ paypal: 'paypal'
\ No newline at end of file
diff --git a/plugins/mollie/config/routes.rb b/plugins/mollie/config/routes.rb
new file mode 100644
index 00000000..0f645c3d
--- /dev/null
+++ b/plugins/mollie/config/routes.rb
@@ -0,0 +1,11 @@
+Rails.application.routes.draw do
+ scope '/:foodcoop' do
+ namespace :payments do
+ resource :mollie, controller: 'mollie_ideal', only: [:new, :create] do
+ post :check
+ get :result
+ get :cancel
+ end
+ end
+ end
+end
diff --git a/plugins/mollie/foodsoft_mollie.gemspec b/plugins/mollie/foodsoft_mollie.gemspec
new file mode 100644
index 00000000..394476c5
--- /dev/null
+++ b/plugins/mollie/foodsoft_mollie.gemspec
@@ -0,0 +1,22 @@
+$:.push File.expand_path('lib', __dir__)
+
+# Maintain your gem's version:
+require "foodsoft_mollie/version"
+
+# Describe your gem and declare its dependencies:
+Gem::Specification.new do |s|
+ s.name = "foodsoft_mollie"
+ s.version = FoodsoftMollie::VERSION
+ s.authors = ["wvengen", "yksflip"]
+ s.email = ["dev-foodsoft@willem.engen.nl", "foodsoft@yksflip.de"]
+ s.homepage = "https://github.com/foodcoops/foodsoft"
+ s.summary = "Mollie payment plugin for foodsoft."
+ s.description = "Integration with Mollie payments."
+
+ s.files = Dir["{app,config,db,lib}/**/*"] + ["LICENSE", "Rakefile", "README.md"]
+
+ s.add_dependency "rails"
+ s.add_dependency "mollie-api-ruby"
+ s.metadata['rubygems_mfa_required'] = 'true'
+ s.required_ruby_version = '>= 2.7'
+end
diff --git a/plugins/mollie/lib/foodsoft_mollie.rb b/plugins/mollie/lib/foodsoft_mollie.rb
new file mode 100644
index 00000000..15e36f76
--- /dev/null
+++ b/plugins/mollie/lib/foodsoft_mollie.rb
@@ -0,0 +1,35 @@
+# require 'Mollie/API/Client'
+require 'mollie-api-ruby'
+require 'foodsoft_mollie/engine'
+
+module FoodsoftMollie
+ # Enabled when configured, but can still be disabled by +use_mollie+ option.
+ def self.enabled?
+ FoodsoftConfig[:use_mollie] != false and FoodsoftConfig[:mollie]
+ end
+
+ # Compute payment transaction fee.
+ #
+ # Transaction fee is specified in foodcoop config under +mollie+, +fee+ as a
+ # hash of fee per payment method, e.g. as "0.30" for a fixed flat fee, "5%"
+ # for a percentage, or "0.30 + 5%" for both. Multiple flat fees and percentages
+ # can appear in a single line, so "0.12 + 2% + 0.56 + 3% + 1%" is valid, e.g.
+ # when multiple payment providers add different fees.
+ #
+ # @param amount [Number] Amount payed
+ # @param method [String] Payment method used
+ # @return [Number] Transaction fee for payment, or +nil+ if no fee details known.
+ def self.payment_fee(amount, method)
+ spec = FoodsoftConfig[:mollie]['fee'] or return
+ unless spec = spec[method]
+ Rails.logger.warn "Mollie: transaction fee for method #{method} not configured."
+ return
+ end
+ # parse
+ return spec if spec.is_a? Numeric
+
+ spec.split('+').inject(0) do |sum, c|
+ sum + (c =~ /^(.*)\s*%\s*$/ ? (::Regexp.last_match(1).to_f / 100 * amount.to_f) : c.to_f)
+ end
+ end
+end
diff --git a/plugins/mollie/lib/foodsoft_mollie/engine.rb b/plugins/mollie/lib/foodsoft_mollie/engine.rb
new file mode 100644
index 00000000..2074c2d5
--- /dev/null
+++ b/plugins/mollie/lib/foodsoft_mollie/engine.rb
@@ -0,0 +1,4 @@
+module FoodsoftMollie
+ class Engine < ::Rails::Engine
+ end
+end
diff --git a/plugins/mollie/lib/foodsoft_mollie/version.rb b/plugins/mollie/lib/foodsoft_mollie/version.rb
new file mode 100644
index 00000000..f138fd96
--- /dev/null
+++ b/plugins/mollie/lib/foodsoft_mollie/version.rb
@@ -0,0 +1,3 @@
+module FoodsoftMollie
+ VERSION = "0.0.1"
+end
diff --git a/plugins/mollie/script/rails b/plugins/mollie/script/rails
new file mode 100755
index 00000000..817042f6
--- /dev/null
+++ b/plugins/mollie/script/rails
@@ -0,0 +1,8 @@
+#!/usr/bin/env ruby
+# This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application.
+
+ENGINE_ROOT = File.expand_path('..', __dir_)
+ENGINE_PATH = File.expand_path('../lib/foodsoft_mollie/engine', __dir__)
+
+require 'rails/all'
+require 'rails/engine/commands'
diff --git a/plugins/polls/Rakefile b/plugins/polls/Rakefile
index 2834c5f3..861a530a 100755
--- a/plugins/polls/Rakefile
+++ b/plugins/polls/Rakefile
@@ -20,7 +20,7 @@ RDoc::Task.new(:rdoc) do |rdoc|
rdoc.rdoc_files.include('lib/**/*.rb')
end
-APP_RAKEFILE = File.expand_path("../test/dummy/Rakefile", __FILE__)
+APP_RAKEFILE = File.expand_path('test/dummy/Rakefile', __dir__)
load 'rails/tasks/engine.rake'
Bundler::GemHelper.install_tasks
@@ -34,4 +34,4 @@ Rake::TestTask.new(:test) do |t|
t.verbose = false
end
-task :default => :test
+task default: :test
diff --git a/plugins/polls/app/controllers/polls_controller.rb b/plugins/polls/app/controllers/polls_controller.rb
index b0c1a9eb..110c4d3f 100644
--- a/plugins/polls/app/controllers/polls_controller.rb
+++ b/plugins/polls/app/controllers/polls_controller.rb
@@ -27,9 +27,9 @@ class PollsController < ApplicationController
def edit
@poll = Poll.find(params[:id])
- if user_has_no_right
- redirect_to polls_path, alert: t('.no_right')
- end
+ return unless user_has_no_right
+
+ redirect_to polls_path, alert: t('.no_right')
end
def update
@@ -53,8 +53,8 @@ class PollsController < ApplicationController
@poll.destroy
redirect_to polls_path, notice: t('.notice')
end
- rescue => error
- redirect_to polls_path, alert: t('.error', error: error.message)
+ rescue StandardError => e
+ redirect_to polls_path, alert: t('.error', error: e.message)
end
def vote
@@ -73,25 +73,25 @@ class PollsController < ApplicationController
@poll_vote = @poll.poll_votes.where(attributes).first_or_initialize
- if request.post?
- @poll_vote.update!(note: params[:note], user: current_user)
+ return unless request.post?
- if @poll.single_select?
- choices = {}
- choice = params[:choice]
- choices[choice] = '1' if choice
- else
- choices = params[:choices].try(:to_h) || {}
- end
+ @poll_vote.update!(note: params[:note], user: current_user)
- @poll_vote.poll_choices = choices.map do |choice, value|
- poll_choice = @poll_vote.poll_choices.where(choice: choice).first_or_initialize
- poll_choice.update!(value: value)
- poll_choice
- end
-
- redirect_to @poll
+ if @poll.single_select?
+ choices = {}
+ choice = params[:choice]
+ choices[choice] = '1' if choice
+ else
+ choices = params[:choices].try(:to_h) || {}
end
+
+ @poll_vote.poll_choices = choices.map do |choice, value|
+ poll_choice = @poll_vote.poll_choices.where(choice: choice).first_or_initialize
+ poll_choice.update!(value: value)
+ poll_choice
+ end
+
+ redirect_to @poll
end
private
diff --git a/plugins/polls/config/locales/tr.yml b/plugins/polls/config/locales/tr.yml
new file mode 100644
index 00000000..ed2ea4c0
--- /dev/null
+++ b/plugins/polls/config/locales/tr.yml
@@ -0,0 +1,67 @@
+tr:
+activerecord:
+ attributes:
+ poll:
+ choices: Seçenekler
+ created_at: Oluşturulma tarihi
+ created_by: Oluşturan
+ description: Açıklama
+ ends: Bitiş tarihi
+ name: Adı
+ max_points: Maksimum puan
+ min_points: Minimum puan
+ multi_select_count: Maksimum seçim sayısı
+ one_vote_per_ordergroup: Sadece bir oylama her sipariş grubu için
+ starts: Başlangıç tarihi
+ voting_method: Oylama yöntemi
+ voting_methods:
+ event: Etkinlik
+ single_select: Tek seçim
+ multi_select: Birden fazla seçim
+ points: Puanlar
+ resistance_points: Direniş puanları
+ poll_vote:
+ name: Adı
+ note: Not
+ updated_at: Son güncelleme
+ models:
+ poll: Oylama
+config:
+ hints:
+ use_polls: Basit anketleri etkinleştirin.
+ keys:
+ use_polls: Anketleri etkinleştirin
+navigation:
+ polls: Anketler
+polls:
+ choice:
+ remove: Sil
+ create:
+ error: 'Anket oluşturulamadı: %{error}'
+ notice: Anket oluşturuldu
+ edit:
+ title: Anketi düzenle
+ form:
+ already_voted: Oylama yapıldığından seçenekler değiştirilemez.
+ new_choice: Yeni seçenek
+ required_ordergroup_custom_field: 'Sipariş grubunun ''%{label}'' alanı boş olamaz.'
+ required_user_custom_field: 'Kullanıcının ''%{label}'' alanı boş olamaz.'
+ destroy:
+ error: 'Anket silinemedi: %{error}'
+ no_right: Bu anketi silme izniniz yok
+ notice: Anket silindi
+ index:
+ new_poll: Yeni anket
+ title: Anketler
+ new:
+ title: Yeni anket
+ polls:
+ vote: Oyla
+ show:
+ vote: Oyla
+ update:
+ error: 'Anket güncellenemedi: %{error}'
+ notice: Anket güncellendi
+ vote:
+ submit: Oyla
+ no_right: Bu ankete katılamazsınız
diff --git a/plugins/polls/db/migrate/20181110000000_create_polls.rb b/plugins/polls/db/migrate/20181110000000_create_polls.rb
index 990e75f0..120b7eef 100644
--- a/plugins/polls/db/migrate/20181110000000_create_polls.rb
+++ b/plugins/polls/db/migrate/20181110000000_create_polls.rb
@@ -24,14 +24,14 @@ class CreatePolls < ActiveRecord::Migration[4.2]
t.references :ordergroup
t.text :note
t.timestamps
- t.index [:poll_id, :user_id, :ordergroup_id], unique: true
+ t.index %i[poll_id user_id ordergroup_id], unique: true
end
create_table :poll_choices do |t|
t.references :poll_vote, null: false
t.integer :choice, null: false
t.integer :value, null: false
- t.index [:poll_vote_id, :choice], unique: true
+ t.index %i[poll_vote_id choice], unique: true
end
end
end
diff --git a/plugins/polls/db/migrate/20181120000000_increase_choices_size.rb b/plugins/polls/db/migrate/20181120000000_increase_choices_size.rb
index d809e3ea..621863dd 100644
--- a/plugins/polls/db/migrate/20181120000000_increase_choices_size.rb
+++ b/plugins/polls/db/migrate/20181120000000_increase_choices_size.rb
@@ -1,5 +1,5 @@
class IncreaseChoicesSize < ActiveRecord::Migration[4.2]
def up
- change_column :polls, :choices, :text, limit: 65535
+ change_column :polls, :choices, :text, limit: 65_535
end
end
diff --git a/plugins/polls/foodsoft_polls.gemspec b/plugins/polls/foodsoft_polls.gemspec
index 63e7db29..607a1276 100644
--- a/plugins/polls/foodsoft_polls.gemspec
+++ b/plugins/polls/foodsoft_polls.gemspec
@@ -1,20 +1,21 @@
-$:.push File.expand_path("../lib", __FILE__)
+$:.push File.expand_path('lib', __dir__)
# Maintain your gem's version:
-require "foodsoft_polls/version"
+require 'foodsoft_polls/version'
# Describe your gem and declare its dependencies:
Gem::Specification.new do |s|
- s.name = "foodsoft_polls"
+ s.name = 'foodsoft_polls'
s.version = FoodsoftPolls::VERSION
- s.authors = ["paroga"]
- s.email = ["paroga@paroga.com"]
- s.homepage = "https://github.com/foodcoops/foodsoft"
- s.summary = "Polls plugin for foodsoft."
- s.description = "Adds possibility to do polls with foodsoft."
+ s.authors = ['paroga']
+ s.email = ['paroga@paroga.com']
+ s.homepage = 'https://github.com/foodcoops/foodsoft'
+ s.summary = 'Polls plugin for foodsoft.'
+ s.description = 'Adds possibility to do polls with foodsoft.'
- s.files = Dir["{app,config,db,lib}/**/*"] + ["Rakefile", "README.md"]
+ s.files = Dir['{app,config,db,lib}/**/*'] + ['Rakefile', 'README.md']
- s.add_dependency "rails"
- s.add_dependency "deface", "~> 1.0"
+ s.add_dependency 'rails'
+ s.add_dependency 'deface', '~> 1.0'
+ s.metadata['rubygems_mfa_required'] = 'true'
end
diff --git a/plugins/polls/lib/foodsoft_polls/engine.rb b/plugins/polls/lib/foodsoft_polls/engine.rb
index a76399f0..e4812345 100644
--- a/plugins/polls/lib/foodsoft_polls/engine.rb
+++ b/plugins/polls/lib/foodsoft_polls/engine.rb
@@ -8,9 +8,9 @@ module FoodsoftPolls
sub_nav.items <<
SimpleNavigation::Item.new(primary, :polls, I18n.t('navigation.polls'), context.polls_path)
# move to right before tasks item
- if i = sub_nav.items.index(sub_nav[:tasks])
- sub_nav.items.insert(i, sub_nav.items.delete_at(-1))
- end
+ return unless i = sub_nav.items.index(sub_nav[:tasks])
+
+ sub_nav.items.insert(i, sub_nav.items.delete_at(-1))
end
end
end
diff --git a/plugins/polls/lib/foodsoft_polls/version.rb b/plugins/polls/lib/foodsoft_polls/version.rb
index 5f3fb96d..84369283 100644
--- a/plugins/polls/lib/foodsoft_polls/version.rb
+++ b/plugins/polls/lib/foodsoft_polls/version.rb
@@ -1,3 +1,3 @@
module FoodsoftPolls
- VERSION = "0.0.1"
+ VERSION = '0.0.1'
end
diff --git a/plugins/printer/Rakefile b/plugins/printer/Rakefile
index 1c9d9839..fbf50e1d 100755
--- a/plugins/printer/Rakefile
+++ b/plugins/printer/Rakefile
@@ -20,7 +20,7 @@ RDoc::Task.new(:rdoc) do |rdoc|
rdoc.rdoc_files.include('lib/**/*.rb')
end
-APP_RAKEFILE = File.expand_path("../test/dummy/Rakefile", __FILE__)
+APP_RAKEFILE = File.expand_path('test/dummy/Rakefile', __dir__)
load 'rails/tasks/engine.rake'
Bundler::GemHelper.install_tasks
@@ -34,4 +34,4 @@ Rake::TestTask.new(:test) do |t|
t.verbose = false
end
-task :default => :test
+task default: :test
diff --git a/plugins/printer/app/controllers/printer_controller.rb b/plugins/printer/app/controllers/printer_controller.rb
index 178787da..78f13377 100644
--- a/plugins/printer/app/controllers/printer_controller.rb
+++ b/plugins/printer/app/controllers/printer_controller.rb
@@ -37,9 +37,7 @@ class PrinterController < ApplicationController
job = PrinterJob.unfinished.find_by_id(json[:id])
return unless job
- if json[:state]
- job.add_update! json[:state], json[:message]
- end
+ job.add_update! json[:state], json[:message] if json[:state]
job.finish! if json[:finish]
end
diff --git a/plugins/printer/app/controllers/printer_jobs_controller.rb b/plugins/printer/app/controllers/printer_jobs_controller.rb
index 37c864e9..4ba13803 100644
--- a/plugins/printer/app/controllers/printer_jobs_controller.rb
+++ b/plugins/printer/app/controllers/printer_jobs_controller.rb
@@ -15,7 +15,7 @@ class PrinterJobsController < ApplicationController
state = order.open? ? 'queued' : 'ready'
count = 0
PrinterJob.transaction do
- %w(articles fax groups matrix).each do |document|
+ %w[articles fax groups matrix].each do |document|
next unless FoodsoftConfig["printer_print_order_#{document}"]
job = PrinterJob.create! order: order, document: document, created_by: current_user
@@ -47,7 +47,7 @@ class PrinterJobsController < ApplicationController
job = PrinterJob.find(params[:id])
job.finish! current_user
redirect_to printer_jobs_path, notice: t('.notice')
- rescue => error
- redirect_to printer_jobs_path, t('errors.general_msg', msg: error.message)
+ rescue StandardError => e
+ redirect_to printer_jobs_path, t('errors.general_msg', msg: e.message)
end
end
diff --git a/plugins/printer/config/locales/tr.yml b/plugins/printer/config/locales/tr.yml
new file mode 100644
index 00000000..93346360
--- /dev/null
+++ b/plugins/printer/config/locales/tr.yml
@@ -0,0 +1,32 @@
+tr:
+ config:
+ keys:
+ printer_print_order_articles: Sipariş makbuzu PDF'lerini yazdır
+ printer_print_order_fax: Fax PDF'lerini yazdır
+ printer_print_order_groups: Grup PDF'lerini yazdır
+ printer_print_order_matrix: Matris PDF'lerini yazdır
+ printer_token: Gizli token
+ use_printer: Yazıcı kullan
+ helpers:
+ submit:
+ printer_job:
+ create: Yazıcı görevi oluştur
+ navigation:
+ orders:
+ printer_jobs: Yazıcı görevleri
+ orders:
+ show:
+ confirm_create_printer_job: Bu sipariş için bir yazıcı görevi zaten oluşturuldu. Yeni bir tane oluşturmak istiyor musunuz?
+ printer_jobs:
+ create:
+ notice: '%{count} yazıcı görevi oluşturuldu.'
+ destroy:
+ notice: Yazıcı görevi silindi.
+ index:
+ finished: Tamamlandı
+ pending: Beklemede
+ queued: Siparişin kapatılması bekleniyor
+ requeued: Yeniden sıraya konuldu
+ title: Yazıcı görevleri
+ show:
+ title: Yazıcı görevi %{id}
diff --git a/plugins/printer/config/routes.rb b/plugins/printer/config/routes.rb
index c81fc786..298ddfea 100644
--- a/plugins/printer/config/routes.rb
+++ b/plugins/printer/config/routes.rb
@@ -4,7 +4,7 @@ Rails.application.routes.draw do
get :socket, on: :collection
end
- resources :printer_jobs, only: [:index, :create, :show, :destroy] do
+ resources :printer_jobs, only: %i[index create show destroy] do
post :requeue, on: :member
get :document, on: :member
end
diff --git a/plugins/printer/db/migrate/20181201000000_create_printer_jobs.rb b/plugins/printer/db/migrate/20181201000000_create_printer_jobs.rb
index ee7665e4..36d175c5 100644
--- a/plugins/printer/db/migrate/20181201000000_create_printer_jobs.rb
+++ b/plugins/printer/db/migrate/20181201000000_create_printer_jobs.rb
@@ -15,6 +15,6 @@ class CreatePrinterJobs < ActiveRecord::Migration[4.2]
t.text :message
end
- add_index :printer_job_updates, [:printer_job_id, :created_at]
+ add_index :printer_job_updates, %i[printer_job_id created_at]
end
end
diff --git a/plugins/printer/foodsoft_printer.gemspec b/plugins/printer/foodsoft_printer.gemspec
index d0eea89a..a6e54455 100644
--- a/plugins/printer/foodsoft_printer.gemspec
+++ b/plugins/printer/foodsoft_printer.gemspec
@@ -1,21 +1,22 @@
-$:.push File.expand_path("../lib", __FILE__)
+$:.push File.expand_path('lib', __dir__)
# Maintain your gem's version:
-require "foodsoft_printer/version"
+require 'foodsoft_printer/version'
# Describe your gem and declare its dependencies:
Gem::Specification.new do |s|
- s.name = "foodsoft_printer"
+ s.name = 'foodsoft_printer'
s.version = FoodsoftPrinter::VERSION
- s.authors = ["paroga"]
- s.email = ["paroga@paroga.com"]
- s.homepage = "https://github.com/foodcoops/foodsoft"
- s.summary = "Printer plugin for foodsoft."
- s.description = "Add a printer queue to foodsoft."
+ s.authors = ['paroga']
+ s.email = ['paroga@paroga.com']
+ s.homepage = 'https://github.com/foodcoops/foodsoft'
+ s.summary = 'Printer plugin for foodsoft.'
+ s.description = 'Add a printer queue to foodsoft.'
- s.files = Dir["{app,config,db,lib}/**/*"] + ["Rakefile", "README.md"]
+ s.files = Dir['{app,config,db,lib}/**/*'] + ['Rakefile', 'README.md']
- s.add_dependency "rails"
- s.add_dependency "deface", "~> 1.0"
- s.add_dependency "tubesock"
+ s.add_dependency 'rails'
+ s.add_dependency 'deface', '~> 1.0'
+ s.add_dependency 'tubesock'
+ s.metadata['rubygems_mfa_required'] = 'true'
end
diff --git a/plugins/printer/lib/foodsoft_printer/engine.rb b/plugins/printer/lib/foodsoft_printer/engine.rb
index 22144e30..8f1f00cc 100644
--- a/plugins/printer/lib/foodsoft_printer/engine.rb
+++ b/plugins/printer/lib/foodsoft_printer/engine.rb
@@ -3,18 +3,19 @@ module FoodsoftPrinter
def navigation(primary, context)
return unless FoodsoftPrinter.enabled?
- unless primary[:orders].nil?
- sub_nav = primary[:orders].sub_navigation
- sub_nav.items <<
- SimpleNavigation::Item.new(primary, :printer_jobs, I18n.t('navigation.orders.printer_jobs'), context.printer_jobs_path)
- end
+ return if primary[:orders].nil?
+
+ sub_nav = primary[:orders].sub_navigation
+ sub_nav.items <<
+ SimpleNavigation::Item.new(primary, :printer_jobs, I18n.t('navigation.orders.printer_jobs'),
+ context.printer_jobs_path)
end
def default_foodsoft_config(cfg)
cfg[:use_printer] = false
end
- initializer 'foodsoft_printer.order_printer_jobs' do |app|
+ initializer 'foodsoft_printer.order_printer_jobs' do |_app|
if Rails.configuration.cache_classes
OrderPrinterJobs.install
else
diff --git a/plugins/printer/lib/foodsoft_printer/order_printer_jobs.rb b/plugins/printer/lib/foodsoft_printer/order_printer_jobs.rb
index 7501a69e..4c7eeeaa 100644
--- a/plugins/printer/lib/foodsoft_printer/order_printer_jobs.rb
+++ b/plugins/printer/lib/foodsoft_printer/order_printer_jobs.rb
@@ -4,14 +4,14 @@ module FoodsoftPrinter
base.class_eval do
has_many :printer_jobs, dependent: :destroy
- alias foodsoft_printer_orig_finish! finish!
+ alias_method :foodsoft_printer_orig_finish!, :finish!
def finish!(user)
foodsoft_printer_orig_finish!(user)
- unless finished?
- printer_jobs.unfinished.each do |job|
- job.add_update! 'ready'
- end
+ return if finished?
+
+ printer_jobs.unfinished.each do |job|
+ job.add_update! 'ready'
end
end
end
diff --git a/plugins/printer/lib/foodsoft_printer/version.rb b/plugins/printer/lib/foodsoft_printer/version.rb
index 17bd39cb..e9d2ad84 100644
--- a/plugins/printer/lib/foodsoft_printer/version.rb
+++ b/plugins/printer/lib/foodsoft_printer/version.rb
@@ -1,3 +1,3 @@
module FoodsoftPrinter
- VERSION = "0.0.1"
+ VERSION = '0.0.1'
end
diff --git a/plugins/uservoice/foodsoft_uservoice.gemspec b/plugins/uservoice/foodsoft_uservoice.gemspec
index f33760fb..4defe395 100644
--- a/plugins/uservoice/foodsoft_uservoice.gemspec
+++ b/plugins/uservoice/foodsoft_uservoice.gemspec
@@ -1,20 +1,21 @@
-$:.push File.expand_path("../lib", __FILE__)
+$:.push File.expand_path('lib', __dir__)
# Maintain your gem's version:
-require "foodsoft_uservoice/version"
+require 'foodsoft_uservoice/version'
# Describe your gem and declare its dependencies:
Gem::Specification.new do |s|
- s.name = "foodsoft_uservoice"
+ s.name = 'foodsoft_uservoice'
s.version = FoodsoftUservoice::VERSION
- s.authors = ["wvengen"]
- s.email = ["dev-foodsoft@willem.engen.nl"]
- s.homepage = "https://github.com/foodcoops/foodsoft"
- s.summary = "Uservoice plugin for foodsoft."
- s.description = "Adds a uservoice feedback button to foodsoft."
+ s.authors = ['wvengen']
+ s.email = ['dev-foodsoft@willem.engen.nl']
+ s.homepage = 'https://github.com/foodcoops/foodsoft'
+ s.summary = 'Uservoice plugin for foodsoft.'
+ s.description = 'Adds a uservoice feedback button to foodsoft.'
- s.files = Dir["{app,config,db,lib}/**/*"] + ["README.md"]
+ s.files = Dir['{app,config,db,lib}/**/*'] + ['README.md']
- s.add_dependency "rails"
- s.add_dependency "content_for_in_controllers"
+ s.add_dependency 'rails'
+ s.add_dependency 'content_for_in_controllers'
+ s.metadata['rubygems_mfa_required'] = 'true'
end
diff --git a/plugins/uservoice/lib/foodsoft_uservoice.rb b/plugins/uservoice/lib/foodsoft_uservoice.rb
index b4718445..2d5b764b 100644
--- a/plugins/uservoice/lib/foodsoft_uservoice.rb
+++ b/plugins/uservoice/lib/foodsoft_uservoice.rb
@@ -1,5 +1,5 @@
-require "content_for_in_controllers"
-require "foodsoft_uservoice/engine"
+require 'content_for_in_controllers'
+require 'foodsoft_uservoice/engine'
module FoodsoftUservoice
# enabled when configured, but can still be disabled by use_uservoice option
@@ -19,11 +19,11 @@ module FoodsoftUservoice
# include uservoice javascript
api_key = FoodsoftConfig[:uservoice]['api_key']
- js_pre = "UserVoice=window.UserVoice||[];"
+ js_pre = 'UserVoice=window.UserVoice||[];'
js_load = "var uv=document.createElement('script');uv.type='text/javascript';uv.async=true;uv.src='//widget.uservoice.com/#{view_context.j api_key}.js';var s=document.getElementsByTagName('script')[0];s.parentNode.insertBefore(uv,s);"
# configuration
- sections = FoodsoftConfig[:uservoice].reject { |k, v| k == 'api_key' }
+ sections = FoodsoftConfig[:uservoice].except('api_key')
sections.each_pair do |k, v|
if k == 'identify'
v['id'] = current_user.try(:id) if v.include?('id')
@@ -48,5 +48,5 @@ module FoodsoftUservoice
end
ActiveSupport.on_load(:after_initialize) do
- ApplicationController.send :include, FoodsoftUservoice::LoadUservoice
+ ApplicationController.include FoodsoftUservoice::LoadUservoice
end
diff --git a/plugins/uservoice/lib/foodsoft_uservoice/version.rb b/plugins/uservoice/lib/foodsoft_uservoice/version.rb
index 8d78e3de..e806ff1d 100644
--- a/plugins/uservoice/lib/foodsoft_uservoice/version.rb
+++ b/plugins/uservoice/lib/foodsoft_uservoice/version.rb
@@ -1,3 +1,3 @@
module FoodsoftUservoice
- VERSION = "0.0.1"
+ VERSION = '0.0.1'
end
diff --git a/plugins/wiki/Rakefile b/plugins/wiki/Rakefile
index 5d2e31db..dd14bed8 100755
--- a/plugins/wiki/Rakefile
+++ b/plugins/wiki/Rakefile
@@ -20,7 +20,7 @@ RDoc::Task.new(:rdoc) do |rdoc|
rdoc.rdoc_files.include('lib/**/*.rb')
end
-APP_RAKEFILE = File.expand_path("../test/dummy/Rakefile", __FILE__)
+APP_RAKEFILE = File.expand_path('test/dummy/Rakefile', __dir__)
load 'rails/tasks/engine.rake'
Bundler::GemHelper.install_tasks
@@ -34,4 +34,4 @@ Rake::TestTask.new(:test) do |t|
t.verbose = false
end
-task :default => :test
+task default: :test
diff --git a/plugins/wiki/app/controllers/pages_controller.rb b/plugins/wiki/app/controllers/pages_controller.rb
index c065abe7..0e28e2d5 100644
--- a/plugins/wiki/app/controllers/pages_controller.rb
+++ b/plugins/wiki/app/controllers/pages_controller.rb
@@ -1,20 +1,20 @@
class PagesController < ApplicationController
before_action -> { require_plugin_enabled FoodsoftWiki }
- before_action :catch_special_pages, only: [:show, :new]
+ before_action :catch_special_pages, only: %i[show new]
- skip_before_action :authenticate, :only => :all
- before_action :only => :all do
- authenticate_or_token(['wiki', 'all'])
+ skip_before_action :authenticate, only: :all
+ before_action only: :all do
+ authenticate_or_token(%w[wiki all])
end
before_action do
content_for :head, view_context.rss_meta_tag
end
def index
- @page = Page.find_by_permalink "Home"
+ @page = Page.find_by_permalink 'Home'
if @page
- render :action => 'show'
+ render action: 'show'
else
redirect_to all_pages_path
end
@@ -34,11 +34,11 @@ class PagesController < ApplicationController
end
if @page.nil?
- redirect_to new_page_path(:title => params[:permalink])
+ redirect_to new_page_path(title: params[:permalink])
elsif @page.redirect?
page = Page.find_by_id(@page.redirect)
unless page.nil?
- flash[:notice] = I18n.t('pages.cshow.redirect_notice', :page => @page.title)
+ flash[:notice] = I18n.t('pages.cshow.redirect_notice', page: @page.title)
redirect_to wiki_page_path(page.permalink)
end
end
@@ -46,12 +46,12 @@ class PagesController < ApplicationController
def new
@page = Page.new
- @page.title = params[:title].gsub("_", " ") if params[:title]
+ @page.title = params[:title].gsub('_', ' ') if params[:title]
@page.parent = Page.find_by_permalink(params[:parent]) if params[:parent]
respond_to do |format|
format.html # new.html.erb
- format.xml { render :xml => @page }
+ format.xml { render xml: @page }
end
end
@@ -60,36 +60,32 @@ class PagesController < ApplicationController
end
def create
- @page = Page.new(params[:page].merge({ :user => current_user }))
+ @page = Page.new(params[:page].merge({ user: current_user }))
if params[:preview]
- render :action => 'new'
+ render action: 'new'
+ elsif @page.save
+ flash[:notice] = I18n.t('pages.create.notice')
+ redirect_to(wiki_page_path(@page.permalink))
else
- if @page.save
- flash[:notice] = I18n.t('pages.create.notice')
- redirect_to(wiki_page_path(@page.permalink))
- else
- render :action => "new"
- end
+ render action: 'new'
end
end
def update
@page = Page.find(params[:id])
- @page.attributes = params[:page].merge({ :user => current_user })
+ @page.attributes = params[:page].merge({ user: current_user })
if params[:preview]
@page.attributes = params[:page]
- render :action => 'edit'
+ render action: 'edit'
+ elsif @page.save
+ @page.parent_id = parent_id if params[:parent_id].present? \
+ && params[:parent_id] != @page_id
+ flash[:notice] = I18n.t('pages.update.notice')
+ redirect_to wiki_page_path(@page.permalink)
else
- if @page.save
- @page.parent_id = parent_id if (!params[:parent_id].blank? \
- && params[:parent_id] != @page_id)
- flash[:notice] = I18n.t('pages.update.notice')
- redirect_to wiki_page_path(@page.permalink)
- else
- render :action => "edit"
- end
+ render action: 'edit'
end
rescue ActiveRecord::StaleObjectError
flash[:error] = I18n.t('pages.error_stale_object')
@@ -100,7 +96,7 @@ class PagesController < ApplicationController
@page = Page.find(params[:id])
@page.destroy
- flash[:notice] = I18n.t('pages.destroy.notice', :page => @page.title)
+ flash[:notice] = I18n.t('pages.destroy.notice', page: @page.title)
redirect_to wiki_path
end
@@ -109,23 +105,23 @@ class PagesController < ApplicationController
@partial = params[:view] || 'site_map'
if params[:name]
- @pages = @pages.where("title LIKE ?", "%#{params[:name]}%").limit(20)
+ @pages = @pages.where('title LIKE ?', "%#{params[:name]}%").limit(20)
@partial = 'title_list'
end
- if params[:sort]
- sort = case params[:sort]
- when "title" then "title"
- when "title_reverse" then "title DESC"
- when "last_updated" then "updated_at DESC"
- when "last_updated_reverse" then "updated_at"
+ sort = if params[:sort]
+ case params[:sort]
+ when 'title' then 'title'
+ when 'title_reverse' then 'title DESC'
+ when 'last_updated' then 'updated_at DESC'
+ when 'last_updated_reverse' then 'updated_at'
end
- else
- sort = "title"
- end
+ else
+ 'title'
+ end
@pages = @pages.order(sort)
respond_to do |format|
format.html
- format.rss { render :layout => false }
+ format.rss { render layout: false }
end
end
@@ -150,15 +146,15 @@ class PagesController < ApplicationController
def variables
keys = Foodsoft::ExpansionVariables.variables.keys
- @variables = Hash[keys.map { |k| [k, Foodsoft::ExpansionVariables.get(k)] }]
+ @variables = keys.index_with { |k| Foodsoft::ExpansionVariables.get(k) }
render 'variables'
end
private
def catch_special_pages
- if params[:id] == 'Help:Foodsoft_variables'
- variables
- end
+ return unless params[:id] == 'Help:Foodsoft_variables'
+
+ variables
end
end
diff --git a/plugins/wiki/app/helpers/pages_helper.rb b/plugins/wiki/app/helpers/pages_helper.rb
index 2c1479f3..869f59d1 100644
--- a/plugins/wiki/app/helpers/pages_helper.rb
+++ b/plugins/wiki/app/helpers/pages_helper.rb
@@ -2,70 +2,70 @@ module PagesHelper
include WikiCloth
def rss_meta_tag
- tag.link(rel: "alternate", type: "application/rss+xml", title: "RSS", href: all_pages_rss_url).html_safe
+ tag.link(rel: 'alternate', type: 'application/rss+xml', title: 'RSS', href: all_pages_rss_url).html_safe
end
def wikified_body(body, title = nil)
FoodsoftWiki::WikiParser.new(data: body + "\n", params: { referer: title }).to_html(noedit: true).html_safe
- rescue => e
+ rescue StandardError => e
# try the following with line breaks: === one === == two == = three =
content_tag :span, class: 'alert alert-error' do
- I18n.t '.wikicloth_exception', :msg => e
+ I18n.t '.wikicloth_exception', msg: e
end.html_safe
end
def link_to_wikipage(page, text = nil)
- if text == nil
- link_to page.title, wiki_page_path(:permalink => page.permalink)
+ if text.nil?
+ link_to page.title, wiki_page_path(permalink: page.permalink)
else
- link_to text, wiki_page_path(:permalink => page.permalink)
+ link_to text, wiki_page_path(permalink: page.permalink)
end
end
def link_to_wikipage_by_permalink(permalink, text = nil)
- unless permalink.blank?
- page = Page.find_by_permalink(permalink)
- if page.nil?
- if text.nil?
- link_to permalink, new_page_path(:title => permalink)
- else
- link_to text, new_page_path(:title => permalink)
- end
+ return if permalink.blank?
+
+ page = Page.find_by_permalink(permalink)
+ if page.nil?
+ if text.nil?
+ link_to permalink, new_page_path(title: permalink)
else
- link_to_wikipage(page, text)
+ link_to text, new_page_path(title: permalink)
end
+ else
+ link_to_wikipage(page, text)
end
end
def generate_toc(body)
toc = String.new
- body.gsub(/^([=]{1,6})\s*(.*?)\s*(\1)/) do
- number = $1.length - 1
- name = $2
+ body.gsub(/^(={1,6})\s*(.*?)\s*(\1)/) do
+ number = ::Regexp.last_match(1).length - 1
+ name = ::Regexp.last_match(2)
- toc << "*" * number + " #{name}\n"
+ toc << (('*' * number) + " #{name}\n")
end
- unless toc.blank?
- FoodsoftWiki::WikiParser.new(data: toc).to_html.gsub(/
([^<>\n]*)/) do
- name = $1
- anchor = name.gsub(/\s/, '_').gsub(/[^a-zA-Z_]/, '')
- "
#{name.truncate(20)}"
- end.html_safe
- end
+ return if toc.blank?
+
+ FoodsoftWiki::WikiParser.new(data: toc).to_html.gsub(/
([^<>\n]*)/) do
+ name = ::Regexp.last_match(1)
+ anchor = name.gsub(/\s/, '_').gsub(/[^a-zA-Z_]/, '')
+ "
#{name.truncate(20)}"
+ end.html_safe
end
def parent_pages_to_select(current_page)
- unless current_page.homepage? # Homepage is the page trees root!
+ if current_page.homepage?
+ []
+ else # Homepage is the page trees root!
Page.non_redirected.reject { |p| p == current_page || p.ancestors.include?(current_page) }
- else
- Array.new
end
end
# return url for all_pages rss feed
def all_pages_rss_url(options = {})
- token = TokenVerifier.new(['wiki', 'all']).generate
- all_pages_url({ :format => 'rss', :token => token }.merge(options))
+ token = TokenVerifier.new(%w[wiki all]).generate
+ all_pages_url({ format: 'rss', token: token }.merge(options))
end
end
diff --git a/plugins/wiki/app/models/page.rb b/plugins/wiki/app/models/page.rb
index e773afa7..26d2393d 100644
--- a/plugins/wiki/app/models/page.rb
+++ b/plugins/wiki/app/models/page.rb
@@ -1,61 +1,62 @@
class Page < ApplicationRecord
include ActsAsTree
- belongs_to :user, :foreign_key => 'updated_by'
+ belongs_to :user, foreign_key: 'updated_by'
acts_as_versioned version_column: :lock_version
- self.non_versioned_columns += %w(permalink created_at title)
+ self.non_versioned_columns += %w[permalink created_at title]
- acts_as_tree :order => "title"
+ acts_as_tree order: 'title'
attr_accessor :old_title # Save title to create redirect page when editing title
validates_presence_of :title, :body
validates_uniqueness_of :permalink, :title
- before_validation :set_permalink, :on => :create
- before_validation :update_permalink, :on => :update
+ before_validation :set_permalink, on: :create
+ before_validation :update_permalink, on: :update
after_update :create_redirect
- scope :non_redirected, -> { where(:redirect => nil) }
- scope :no_parent, -> { where(:parent_id => nil) }
+ scope :non_redirected, -> { where(redirect: nil) }
+ scope :no_parent, -> { where(parent_id: nil) }
def self.permalink(title)
- title.gsub(/[\/\.,;@\s]/, "_").gsub(/[\"\']/, "")
+ title.gsub(%r{[/.,;@\s]}, '_').gsub(/["']/, '')
end
def homepage?
- permalink == "Home"
+ permalink == 'Home'
end
def self.dashboard
- where(permalink: "Dashboard").first
+ where(permalink: 'Dashboard').first
end
def self.public_front_page
- where(permalink: "Public_frontpage").first
+ where(permalink: 'Public_frontpage').first
end
def self.welcome_mail
- where(permalink: "Welcome_mail").first
+ where(permalink: 'Welcome_mail').first
end
def set_permalink
- unless title.blank?
- self.permalink = Page.count == 0 ? "Home" : Page.permalink(title)
- end
+ return if title.blank?
+
+ self.permalink = Page.count == 0 ? 'Home' : Page.permalink(title)
end
def diff
current = versions.latest
- old = versions.where(["page_id = ? and lock_version < ?", current.page_id, current.lock_version]).order('lock_version DESC').first
+ old = versions.where(['page_id = ? and lock_version < ?', current.page_id,
+ current.lock_version]).order('lock_version DESC').first
if old
o = ''
Diffy::Diff.new(old.body, current.body).each do |line|
case line
- when /^\+/ then o += "#{line.chomp} " unless line.chomp == "+"
- when /^-/ then o += "#{line.chomp} " unless line.chomp == "-"
+ when /^\+/ then o += "#{line.chomp} " unless line.chomp == '+'
+ when /^-/ then o += "#{line.chomp} " unless line.chomp == '-'
end
end
o
@@ -67,19 +68,19 @@ class Page < ApplicationRecord
protected
def update_permalink
- if changed.include?("title")
- set_permalink
- self.old_title = changes["title"].first # Save title for creating redirect
- end
+ return unless changed.include?('title')
+
+ set_permalink
+ self.old_title = changes['title'].first # Save title for creating redirect
end
def create_redirect
- unless old_title.blank?
- Page.create :redirect => id,
- :title => old_title,
- :body => I18n.t('model.page.redirect', :title => title),
- :permalink => Page.permalink(old_title),
- :updated_by => updated_by
- end
+ return if old_title.blank?
+
+ Page.create redirect: id,
+ title: old_title,
+ body: I18n.t('model.page.redirect', title: title),
+ permalink: Page.permalink(old_title),
+ updated_by: updated_by
end
end
diff --git a/plugins/wiki/app/views/pages/all.rss.builder b/plugins/wiki/app/views/pages/all.rss.builder
index f7194763..7f0b4e10 100644
--- a/plugins/wiki/app/views/pages/all.rss.builder
+++ b/plugins/wiki/app/views/pages/all.rss.builder
@@ -1,16 +1,16 @@
-xml.instruct! :xml, :version => "1.0"
-xml.rss :version => "2.0" do
+xml.instruct! :xml, version: '1.0'
+xml.rss version: '2.0' do
xml.channel do
- xml.title FoodsoftConfig[:name] + " Wiki"
- xml.description ""
+ xml.title FoodsoftConfig[:name] + ' Wiki'
+ xml.description ''
xml.link FoodsoftConfig[:homepage]
for page in @pages
xml.item do
xml.title page.title
- xml.description page.diff, :type => "html"
+ xml.description page.diff, type: 'html'
xml.author User.find_by_id(page.updated_by).try(:display)
- xml.pubDate page.updated_at.to_s(:rfc822)
+ xml.pubDate page.updated_at.to_fs(:rfc822)
xml.link wiki_page_path(page.permalink)
xml.guid page.updated_at.to_i
end
diff --git a/plugins/wiki/config/locales/de.yml b/plugins/wiki/config/locales/de.yml
index cb02e461..dfdf8da4 100644
--- a/plugins/wiki/config/locales/de.yml
+++ b/plugins/wiki/config/locales/de.yml
@@ -17,6 +17,7 @@ de:
wiki:
all_pages: Alle Seiten
home: Startseite
+ title: Wiki
pages:
all:
new_page: Neue Seite anlegen
@@ -67,6 +68,7 @@ de:
section_table: Tabellenformatierung
see_tables: siehe %{tables_link}
tables_link: Tabellen
+ text: Text
title: Schnelle Formatierungshilfe
unordered_list: Listen mit Punkten
wiki_link_ex: Foodsoft Wiki Seite
@@ -94,9 +96,11 @@ de:
description: Variablen geben Informationen wieder, die an anderer Stelle definiert wurden. Wenn Du die Variable benutzt, wird sie mit ihrem Wert ersetzt, wenn sie angezeigt wird. Foodsoft hat eine Reihe von vordefinierten Variablen, wie zum Beispiel Name und Adresse deiner Foodcoop, Softwareversion und die Anzahl der Mitglieder und Lieferanten. In der Tabelle unten sind alle Variablen aufgeführt. Du kannst diese in Wiki-Seiten und der Fusszeile (in den Einstellungen) nutzen.
title: Foodsoft-Variablen
value: Aktueller Wert
+ variable: Variable
version:
author: ! 'Autor: %{user}'
date_format: ! '%a, %d.%m.%Y, %H:%M Uhr'
revert: Auf diese Version zurücksetzen
title: ! '%{title} - Version %{version}'
+ title_version: Version
view_current: Aktuelle Version sehen
diff --git a/plugins/wiki/config/locales/es.yml b/plugins/wiki/config/locales/es.yml
index 71761e80..a7391e94 100644
--- a/plugins/wiki/config/locales/es.yml
+++ b/plugins/wiki/config/locales/es.yml
@@ -16,24 +16,36 @@ es:
navigation:
wiki:
all_pages: Todas las páginas
+ home: Inicio
+ title: Wiki
pages:
all:
new_page: Crea nueva página
recent_changes: Cambios recientes
search:
action: Busca
+ placeholder: Título de página ..
+ site_map: Mapa web
+ title: Todas las páginas Wiki
title_list: Lista de páginas
body:
title_toc: Contenido
+ wikicloth_exception: 'Sentimos informar de que ha ocurrido un error al interpretar la página wiki: %{msg}. Por favor, intenta arreglarla y guarda la página de nuevo.'
create:
notice: La página ha sido creada
cshow:
error_noexist: La página no existe
+ redirect_notice: Redirigido desde %{page}...
+ destroy:
+ notice: La página '%{page}' y todas las subpáginas se han eliminado correctamente.
+ diff:
+ title: "%{title} - cambios de versión %{old} a %{new}"
edit:
title: Editar página
error_stale_object: Cuidado, la página ha sido editada por otra persona. Por favor, intenta de nuevo.
form:
help:
+ bold: negrita
external_link_ex: Enlace externo
external_links: Externo
heading: nivel %{level}
@@ -41,18 +53,54 @@ es:
image_link_title: Título de la imagen
image_links: Imágenes
italic: itálicas
+ link_lists: Más en listas
+ link_table: Formato de tabla
+ link_templates: Plantillas
+ link_variables: Variables Foodsoft
+ list_item_1: Primer elemento de lista
+ list_item_2: Segundo elemento de lista
+ noformat: Sin Formato
ordered_list: Lista numerada
section_block: Estilo del párrafo
section_character: Estilo de las letras
section_link: Estilo de los enlaces
section_more: Más temas
+ section_table: Formato de tabla
+ see_tables: ver %{tables_link}
+ tables_link: Tablas
+ text: texto
+ title: Ayuda de formato rápido
+ unordered_list: Lista de artículos
+ wiki_link_ex: Página Wiki de Foodsoft
+ wiki_links: Enlaces Wiki
preview: Previsualizar
+ last_updated: Última actualización
new:
title: Crear una nueva página en la wiki
+ page_list_item:
+ date_format: ! '%a, %d %B %Y %H:%M:%S'
show:
+ date_format: ! '%d-%m-%y %H:%M'
delete: Eliminar página
+ delete_confirm: ! 'Advertencia: todas las subpáginas serán eliminadas también. ¿Estás seguro?'
+ diff: Comparar versiones
+ edit: Editar página
+ last_updated: Última actualización por %{user} el %{when}
+ subpages: subpáginas
+ title_versions: Versiones
+ versions: Versiones (%{count})
title: Título
+ update:
+ notice: La página fue actualizada
+ variables:
+ description: Las variables devuelven información de otro lugar. Cuando utilice la variable, se reemplazará por su valor cuando se muestre. Foodsoft tiene un número de variables predefinidas, como el nombre y la dirección de tu cooperativa, la versión del software, y el número de miembros y proveedores. Vea la siguiente tabla para todas las variables. Puede usarlas en páginas wiki así como en el pie de página (desde la pantalla de configuración).
+ title: Variables Foodsoft
+ value: Valor actual
+ variable: Variable
version:
author: ! 'Autor/a: %{user}'
+ date_format: ! '%a, %d-%m-%Y, %H:%M'
+ revert: Revertir a esta versión
+ title: ! '%{title} - versión %{version}'
title_version: Versión
view_current: Ver versión actual
diff --git a/plugins/wiki/config/locales/tr.yml b/plugins/wiki/config/locales/tr.yml
new file mode 100644
index 00000000..077c08e1
--- /dev/null
+++ b/plugins/wiki/config/locales/tr.yml
@@ -0,0 +1,107 @@
+tr:
+ activerecord:
+ attributes:
+ page:
+ body: İçerik
+ parent_id: Üst sayfa
+ title: Başlık
+ config:
+ hints:
+ use_wiki: Düzenlenebilir wiki sayfalarını etkinleştirin.
+ keys:
+ use_wiki: Wiki'yi etkinleştir
+ model:
+ page:
+ redirect: '[[%{title}]] sayfasına yönlendiriliyor...'
+ navigation:
+ wiki:
+ all_pages: Tüm Sayfalar
+ home: Ana Sayfa
+ title: Wiki
+ pages:
+ all:
+ new_page: Yeni sayfa oluştur
+ recent_changes: Son değişiklikler
+ search:
+ action: Ara
+ placeholder: Sayfa başlığı ..
+ site_map: Site Haritası
+ title: Tüm Wiki sayfaları
+ title_list: Sayfa listesi
+ body:
+ title_toc: İçindekiler
+ wikicloth_exception: 'Üzgünüm, wiki sayfasını yorumlarken bir hata oluştu: %{msg}. Lütfen düzeltin ve sayfayı tekrar kaydedin.'
+ create:
+ notice: Sayfa oluşturuldu.
+ cshow:
+ error_noexist: Sayfa mevcut değil!
+ redirect_notice: '%{page} sayfasından yönlendirildi ...'
+ destroy:
+ notice: Sayfa '%{page}' ve tüm alt sayfaları başarıyla silindi.
+ diff:
+ title: "%{title} - %{old} versiyonundan %{new} versiyonuna değişiklikler"
+ edit:
+ title: Sayfayı düzenle
+ error_stale_object: Uyarı, sayfa başka biri tarafından düzenlendi. Lütfen tekrar deneyin.
+ form:
+ help:
+ bold: kalın
+ external_link_ex: Dış bağlantı
+ external_links: Dış
+ heading: '%{level}. düzey'
+ headings: Başlık
+ image_link_title: Resim başlığı
+ image_links: Resimler
+ italic: italik
+ link_lists: Liste hakkında daha fazlası
+ link_table: Tablo biçimlendirmesi
+ link_templates: Şablonlar
+ link_variables: Foodsoft değişkenleri
+ list_item_1: İlk liste maddesi
+ list_item_2: İkinci liste maddesi
+ noformat: Biçimlendirme yok
+ ordered_list: Numaralı liste
+ section_block: Blok biçimlendirmesi
+ section_character: Karakter biçimlendirmesi
+ section_link: Bağlantı biçimlendirmesi
+ section_more: Daha fazla konu
+ section_table: Tablo biçimlendirmesi
+ see_tables: '%{tables_link} göz atın'
+ tables_link: Tablolar
+ text: metin
+ title: Hızlı biçimlendirme yardımı
+ unordered_list: Madde listesi
+ wiki_link_ex: Foodsoft Wiki Sayfası
+ wiki_links: Wiki bağlantıları
+ preview: Önizleme
+ last_updated: Son güncelleme
+ new:
+ title: Yeni bir wiki sayfası oluşturun
+ page_list_item:
+ date_format: ! '%d %B %Y, %H:%M:%S'
+ show:
+ date_format: ! '%d-%m-%Y %H:%M'
+ delete: Sayfayı sil
+ delete_confirm: Tüm alt sayfaların da silineceği uyarısını dikkate alarak devam etmek istediğinizden emin misiniz?
+ diff: Versiyonları karşılaştır
+ edit: Sayfayı düzenle
+ last_updated: Son güncelleme %{when} tarihinde %{user} tarafından yapıldı
+ subpages: alt sayfalar
+ title_versions: Versiyonlar
+ versions: Versiyonlar (%{count})
+ title: Başlık
+ update:
+ notice: Sayfa güncellendi
+ variables:
+ description: Değişkenler bilgiyi başka bir yerden getirir. Değişkeni kullandığınızda, görüntülendiğinde değeriyle değiştirilir. Foodsoft'un adınız, adresiniz, yazılım sürümü ve üye ve tedarikçi sayısı gibi birçok önceden tanımlanmış değişkeni vardır. Tüm değişkenler için aşağıdaki tabloya bakın. Bunları wiki sayfalarında ve ayak kısımlarında (yapılandırma ekranından) kullanabilirsiniz.
+ title: Foodsoft değişkenleri
+ value: Güncel değer
+ variable: Değişken
+ version:
+ author: 'Yazar: %{user}'
+ date_format: ! '%a, %d-%m-%Y, %H:%M'
+ revert: Bu sürüme geri dön
+ title: ! '%{title} - sürüm %{version}'
+ title_version: Sürüm
+ view_current: Şu anki sürümü gör
+
diff --git a/plugins/wiki/config/routes.rb b/plugins/wiki/config/routes.rb
index 4ebad572..ad713366 100644
--- a/plugins/wiki/config/routes.rb
+++ b/plugins/wiki/config/routes.rb
@@ -1,12 +1,12 @@
Rails.application.routes.draw do
scope '/:foodcoop' do
resources :pages do
- get :all, :on => :collection
- get :version, :on => :member
- get :revert, :on => :member
- get :diff, :on => :member
+ get :all, on: :collection
+ get :version, on: :member
+ get :revert, on: :member
+ get :diff, on: :member
end
get '/wiki/:permalink' => 'pages#show', :as => 'wiki_page' # , :constraints => {:permalink => /[^\s]+/}
- get '/wiki' => 'pages#show', :defaults => { :permalink => 'Home' }, :as => 'wiki'
+ get '/wiki' => 'pages#show', :defaults => { permalink: 'Home' }, :as => 'wiki'
end
end
diff --git a/plugins/wiki/db/migrate/20090325175756_create_pages.rb b/plugins/wiki/db/migrate/20090325175756_create_pages.rb
index 846decf8..cdd00e2b 100644
--- a/plugins/wiki/db/migrate/20090325175756_create_pages.rb
+++ b/plugins/wiki/db/migrate/20090325175756_create_pages.rb
@@ -4,7 +4,7 @@ class CreatePages < ActiveRecord::Migration[4.2]
t.string :title
t.text :body
t.string :permalink
- t.integer :lock_version, :default => 0
+ t.integer :lock_version, default: 0
t.integer :updated_by
t.integer :redirect
t.integer :parent_id
diff --git a/plugins/wiki/foodsoft_wiki.gemspec b/plugins/wiki/foodsoft_wiki.gemspec
index 371872c5..58be331d 100644
--- a/plugins/wiki/foodsoft_wiki.gemspec
+++ b/plugins/wiki/foodsoft_wiki.gemspec
@@ -1,26 +1,27 @@
-$:.push File.expand_path("../lib", __FILE__)
+$:.push File.expand_path('lib', __dir__)
# Maintain your gem's version:
-require "foodsoft_wiki/version"
+require 'foodsoft_wiki/version'
# Describe your gem and declare its dependencies:
Gem::Specification.new do |s|
- s.name = "foodsoft_wiki"
+ s.name = 'foodsoft_wiki'
s.version = FoodsoftWiki::VERSION
- s.authors = ["wvengen"]
- s.email = ["dev-foodsoft@willem.engen.nl"]
- s.homepage = "https://github.com/foodcoops/foodsoft"
- s.summary = "Wiki plugin for foodsoft."
- s.description = "Adds a wiki to foodsoft."
+ s.authors = ['wvengen']
+ s.email = ['dev-foodsoft@willem.engen.nl']
+ s.homepage = 'https://github.com/foodcoops/foodsoft'
+ s.summary = 'Wiki plugin for foodsoft.'
+ s.description = 'Adds a wiki to foodsoft.'
- s.files = Dir["{app,config,db,lib}/**/*"] + ["Rakefile", "README.md"]
+ s.files = Dir['{app,config,db,lib}/**/*'] + ['Rakefile', 'README.md']
- s.add_dependency "rails"
+ s.add_dependency 'rails'
s.add_dependency 'wikicloth'
s.add_dependency 'twitter-text', '~> 1.14' # wikicloth doesn't support version 2
s.add_dependency 'acts_as_versioned' # need git version, make sure that is included in foodsoft's Gemfile
- s.add_dependency "deface", "~> 1.0"
+ s.add_dependency 'deface', '~> 1.0'
s.add_dependency 'diffy'
s.add_dependency 'content_for_in_controllers'
- s.add_development_dependency "sqlite3"
+ s.add_development_dependency 'sqlite3'
+ s.metadata['rubygems_mfa_required'] = 'true'
end
diff --git a/plugins/wiki/lib/foodsoft_wiki/engine.rb b/plugins/wiki/lib/foodsoft_wiki/engine.rb
index 4cc20f6a..ae2ce462 100644
--- a/plugins/wiki/lib/foodsoft_wiki/engine.rb
+++ b/plugins/wiki/lib/foodsoft_wiki/engine.rb
@@ -8,17 +8,17 @@ module FoodsoftWiki
subnav.item :all_pages, I18n.t('navigation.wiki.all_pages'), ctx.all_pages_path, id: nil
end
# move this last added item to just after the foodcoop menu
- if i = primary.items.index(primary[:foodcoop])
- primary.items.insert(i + 1, primary.items.delete_at(-1))
- end
+ return unless i = primary.items.index(primary[:foodcoop])
+
+ primary.items.insert(i + 1, primary.items.delete_at(-1))
end
def default_foodsoft_config(cfg)
cfg[:use_wiki] = true
end
- initializer "foodsoft_wiki.assets.precompile" do |app|
- app.config.assets.precompile += %w(icons/feed-icon-14x14.png)
+ initializer 'foodsoft_wiki.assets.precompile' do |app|
+ app.config.assets.precompile += %w[icons/feed-icon-14x14.png]
end
end
end
diff --git a/plugins/wiki/lib/foodsoft_wiki/mailer.rb b/plugins/wiki/lib/foodsoft_wiki/mailer.rb
index 83a110f1..4b7a892d 100644
--- a/plugins/wiki/lib/foodsoft_wiki/mailer.rb
+++ b/plugins/wiki/lib/foodsoft_wiki/mailer.rb
@@ -3,10 +3,10 @@ module FoodsoftWiki
def self.included(base) # :nodoc:
base.class_eval do
# modify user presentation link to writing a message for the user
- def additonal_welcome_text(user)
- if FoodsoftWiki.enabled? && (page = Page.welcome_mail)
- page.body
- end
+ def additonal_welcome_text(_user)
+ return unless FoodsoftWiki.enabled? && (page = Page.welcome_mail)
+
+ page.body
end
end
end
@@ -15,5 +15,5 @@ end
# modify existing helper
ActiveSupport.on_load(:after_initialize) do
- Mailer.send :include, FoodsoftWiki::Mailer
+ Mailer.include FoodsoftWiki::Mailer
end
diff --git a/plugins/wiki/lib/foodsoft_wiki/version.rb b/plugins/wiki/lib/foodsoft_wiki/version.rb
index 2a67a94e..580ee3ed 100644
--- a/plugins/wiki/lib/foodsoft_wiki/version.rb
+++ b/plugins/wiki/lib/foodsoft_wiki/version.rb
@@ -1,3 +1,3 @@
module FoodsoftWiki
- VERSION = "0.0.1"
+ VERSION = '0.0.1'
end
diff --git a/plugins/wiki/lib/foodsoft_wiki/wiki_parser.rb b/plugins/wiki/lib/foodsoft_wiki/wiki_parser.rb
index 37e58465..6e14d2a8 100644
--- a/plugins/wiki/lib/foodsoft_wiki/wiki_parser.rb
+++ b/plugins/wiki/lib/foodsoft_wiki/wiki_parser.rb
@@ -10,7 +10,7 @@ module FoodsoftWiki
link_attributes_for do |page|
permalink = Page.permalink(page)
- if Page.exists?(:permalink => permalink)
+ if Page.exists?(permalink: permalink)
{ href: url_for(:wiki_page_path, permalink: permalink) }
elsif page.include? '#'
# If "Foo#Bar" does not exist then consider "Foo" with anchor.
@@ -20,8 +20,8 @@ module FoodsoftWiki
end
end
- section_link do |section|
- ""
+ section_link do |_section|
+ ''
end
def to_html(render_options = {})
@@ -41,7 +41,7 @@ module FoodsoftWiki
return { href: '#' + anchor } if page.empty?
permalink = Page.permalink(page)
- if Page.exists?(:permalink => permalink)
+ if Page.exists?(permalink: permalink)
{ href: url_for(:wiki_page_path, permalink: permalink, anchor: anchor) }
else
# Do not suggest to use number signs in the title.
diff --git a/script/rails b/script/rails
index bd79dce5..3c234a25 100755
--- a/script/rails
+++ b/script/rails
@@ -1,6 +1,6 @@
#!/usr/bin/env ruby
# This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application.
-APP_PATH = File.expand_path('../../config/application', __FILE__)
-require File.expand_path('../../config/boot', __FILE__)
+APP_PATH = File.expand_path('../config/application', __dir__)
+require File.expand_path('../config/boot', __dir__)
require 'rails/commands'
diff --git a/spec/controllers/application_controller_spec.rb b/spec/controllers/application_controller_spec.rb
deleted file mode 100644
index 35db7574..00000000
--- a/spec/controllers/application_controller_spec.rb
+++ /dev/null
@@ -1,12 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-describe ApplicationController, type: :controller do
- describe 'current' do
- it 'returns current ApplicationController' do
- described_class.new.send(:store_controller)
- expect(described_class.current).to be_instance_of described_class
- end
- end
-end
diff --git a/spec/controllers/articles_controller_spec.rb b/spec/controllers/articles_controller_spec.rb
deleted file mode 100644
index e2940f48..00000000
--- a/spec/controllers/articles_controller_spec.rb
+++ /dev/null
@@ -1,348 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-describe ArticlesController, type: :controller do
- let(:user) { create :user, :role_article_meta }
- let(:article_category_a) { create :article_category, name: "AAAA" }
- let(:article_category_b) { create :article_category, name: "BBBB" }
- let(:article_category_c) { create :article_category, name: "CCCC" }
- let(:supplier) { create :supplier}
- let(:article_a) { create :article, name: 'AAAA', note: "ZZZZ", unit: '750 g', article_category: article_category_b, availability: false, supplier_id: supplier.id }
- let(:article_b) { create :article, name: 'BBBB', note: "XXXX", unit: '500 g', article_category: article_category_a, availability: true, supplier_id: supplier.id }
- let(:article_c) { create :article, name: 'CCCC', note: "YYYY", unit: '250 g', article_category: article_category_c, availability: true, supplier_id: supplier.id }
- let(:article_no_supplier) { create :article, name: 'no_supplier', note: "no_supplier", unit: '100 g', article_category: article_category_b, availability: true }
-
- let(:order) { create :order }
- let(:order2) { create :order }
-
- def get_with_supplier(action, params: {}, xhr: false, format: nil)
- params['supplier_id'] = supplier.id
- get_with_defaults(action, params: params, xhr: xhr, format: format)
- end
-
- def post_with_supplier(action, params: {}, xhr: false, format: nil)
- params['supplier_id'] = supplier.id
- post_with_defaults(action, params: params, xhr: xhr, format: format)
- end
-
- before { login user }
-
- describe 'GET index' do
- before do
- supplier
- article_a
- article_b
- article_c
- supplier.reload
- end
- it 'assigns sorting on articles' do
- sortings = [
- ['name', [article_a, article_b, article_c]],
- ['name_reverse', [article_c, article_b, article_a]],
- ['note', [article_b, article_c, article_a]],
- ['note_reverse', [article_a, article_c, article_b]],
- ['unit', [article_c, article_b, article_a]],
- ['unit_reverse', [article_a, article_b, article_c]],
- ['article_category', [article_b, article_a, article_c]],
- ['article_category_reverse', [article_c, article_a, article_b]],
- ['availability', [article_a, article_b, article_c]],
- ['availability_reverse', [article_b, article_c, article_a]]
- ]
- sortings.each do |sorting|
- get_with_supplier :index, params: { sort: sorting[0] }
- expect(response).to have_http_status(:success)
- expect(assigns(:articles).to_a).to eq(sorting[1])
- end
- end
-
- it 'triggers an article csv' do
- get_with_supplier :index, format: :csv
- expect(response.header['Content-Type']).to include('text/csv')
- expect(response.body).to include(article_a.unit, article_b.unit)
- end
- end
-
- describe 'new' do
- it 'renders form for a new article' do
- get_with_supplier :new, xhr: true
- expect(response).to have_http_status(:success)
- end
- end
-
- describe 'copy' do
- it 'renders form with copy of an article' do
- get_with_supplier :copy, params: { article_id: article_a.id }, xhr: true
- expect(assigns(:article).attributes).to eq(article_a.dup.attributes)
- expect(response).to have_http_status(:success)
- end
- end
-
- describe '#create' do
- it 'creates a new article' do
- valid_attributes = article_a.attributes.except('id')
- valid_attributes['name'] = 'ABAB'
- get_with_supplier :create, params: { article: valid_attributes }, xhr: true
- expect(response).to have_http_status(:success)
- end
-
- it 'fails to create a new article and renders #new' do
- get_with_supplier :create, params: { article: { id: nil } }, xhr: true
- expect(response).to have_http_status(:success)
- expect(response).to render_template('articles/new')
- end
- end
-
- describe 'edit' do
- it 'opens form to edit article attributes' do
- get_with_supplier :edit, params: { id: article_a.id }, xhr: true
- expect(response).to have_http_status(:success)
- expect(response).to render_template('articles/new')
- end
- end
-
- describe '#edit all' do
- it 'renders edit_all' do
- get_with_supplier :edit_all, xhr: true
- expect(response).to have_http_status(:success)
- expect(response).to render_template('articles/edit_all')
- end
- end
-
- describe '#update' do
- it 'updates article attributes' do
- get_with_supplier :update, params: { id: article_a.id, article: { unit: '300 g' } }, xhr: true
- expect(assigns(:article).unit).to eq('300 g')
- expect(response).to have_http_status(:success)
- end
-
- it 'updates article with empty name attribute' do
- get_with_supplier :update, params: { id: article_a.id, article: { name: nil } }, xhr: true
- expect(response).to render_template('articles/new')
- end
- end
-
- describe '#update_all' do
- it 'updates all articles' do
- get_with_supplier :update_all, params: { articles: { "#{article_a.id}": attributes_for(:article), "#{article_b.id}": attributes_for(:article) } }
- expect(response).to have_http_status(:redirect)
- end
-
- it 'fails on updating all articles' do
- get_with_supplier :update_all, params: { articles: { "#{article_a.id}": attributes_for(:article, name: 'ab') } }
- expect(response).to have_http_status(:success)
- expect(response).to render_template('articles/edit_all')
- end
- end
-
- describe '#update_selected' do
- let(:order_article) { create :order_article, order: order, article: article_no_supplier }
-
- before do
- order_article
- end
-
- it 'updates selected articles' do
- get_with_supplier :update_selected, params: { selected_articles: [article_a.id, article_b.id] }
- expect(response).to have_http_status(:redirect)
- end
-
- it 'destroys selected articles' do
- get_with_supplier :update_selected, params: { selected_articles: [article_a.id, article_b.id], selected_action: 'destroy' }
- article_a.reload
- article_b.reload
- expect(article_a).to be_deleted
- expect(article_b).to be_deleted
- expect(response).to have_http_status(:redirect)
- end
-
- it 'sets availability false on selected articles' do
- get_with_supplier :update_selected, params: { selected_articles: [article_a.id, article_b.id], selected_action: 'setNotAvailable' }
- article_a.reload
- article_b.reload
- expect(article_a).not_to be_availability
- expect(article_b).not_to be_availability
- expect(response).to have_http_status(:redirect)
- end
-
- it 'sets availability true on selected articles' do
- get_with_supplier :update_selected, params: { selected_articles: [article_a.id, article_b.id], selected_action: 'setAvailable' }
- article_a.reload
- article_b.reload
- expect(article_a).to be_availability
- expect(article_b).to be_availability
- expect(response).to have_http_status(:redirect)
- end
-
- it 'fails deletion if one article is in open order' do
- get_with_supplier :update_selected, params: { selected_articles: [article_a.id, article_no_supplier.id], selected_action: 'destroy' }
- article_a.reload
- article_no_supplier.reload
- expect(article_a).not_to be_deleted
- expect(article_no_supplier).not_to be_deleted
- expect(response).to have_http_status(:redirect)
- end
- end
-
- describe '#parse_upload' do
- let(:file) { Rack::Test::UploadedFile.new(Rails.root.join('spec/fixtures/files/upload_test.csv'), original_filename: 'upload_test.csv') }
-
- it 'updates articles from spreadsheet' do
- post_with_supplier :parse_upload, params: { articles: { file: file, outlist_absent: '1', convert_units: '1', type: 'foodsoft' } }
- expect(response).to have_http_status(:success)
- end
-
- it 'missing file not updates particles from spreadsheet' do
- post_with_supplier :parse_upload, params: { articles: { file: nil, outlist_absent: '1', convert_units: '1' } }
- expect(response).to have_http_status(:redirect)
- expect(flash[:alert]).to match(I18n.t('errors.general_msg', msg: "undefined method `original_filename' for \"\":String").to_s)
- end
- end
-
- describe '#sync' do
- # TODO: double render error in controller
- it 'throws double render error' do
- expect do
- post :sync, params: { foodcoop: FoodsoftConfig[:default_scope], supplier_id: supplier.id }
- end.to raise_error(AbstractController::DoubleRenderError)
- end
-
- xit 'updates particles from spreadsheet' do
- post :sync, params: { foodcoop: FoodsoftConfig[:default_scope], supplier_id: supplier.id, articles: { '#{article_a.id}': attributes_for(:article), '#{article_b.id}': attributes_for(:article) } }
- expect(response).to have_http_status(:redirect)
- end
- end
-
- describe '#destroy' do
- let(:order_article) { create :order_article, order: order, article: article_no_supplier }
-
- before do
- order_article
- end
-
- it 'does not delete article if order open' do
- get_with_supplier :destroy, params: { id: article_no_supplier.id }, xhr: true
- expect(assigns(:article)).not_to be_deleted
- expect(response).to have_http_status(:success)
- expect(response).to render_template('articles/destroy')
- end
-
- it 'deletes article if order closed' do
- get_with_supplier :destroy, params: { id: article_b.id }, xhr: true
- expect(assigns(:article)).to be_deleted
- expect(response).to have_http_status(:success)
- expect(response).to render_template('articles/destroy')
- end
- end
-
- describe '#update_synchronized' do
- let(:order_article) { create :order_article, order: order, article: article_no_supplier }
-
- before do
- order_article
- article_a
- article_b
- article_no_supplier
- end
-
- it 'deletes articles' do
- # TODO: double render error in controller
- get_with_supplier :update_synchronized, params: { outlisted_articles: { article_a.id => article_a, article_b.id => article_b } }
- article_a.reload
- article_b.reload
- expect(article_a).to be_deleted
- expect(article_b).to be_deleted
- expect(response).to have_http_status(:redirect)
- end
-
- it 'updates articles' do
- get_with_supplier :update_synchronized, params: { articles: { article_a.id => { name: 'NewNameA' }, article_b.id => { name: 'NewNameB' } } }
- expect(assigns(:updated_articles).first.name).to eq 'NewNameA'
- expect(response).to have_http_status(:redirect)
- end
-
- it 'does not update articles if article with same name exists' do
- get_with_supplier :update_synchronized, params: { articles: { article_a.id => { unit: '2000 g' }, article_b.id => { name: 'AAAA' } } }
- error_array = [assigns(:updated_articles).first.errors.first, assigns(:updated_articles).last.errors.first]
- expect(error_array).to include(ActiveModel::Error)
- expect(response).to have_http_status(:success)
- end
-
- it 'does update articles if article with same name was deleted before' do
- get_with_supplier :update_synchronized, params: {
- outlisted_articles: { article_a.id => article_a },
- articles: {
- article_a.id => { name: 'NewName' },
- article_b.id => { name: 'AAAA' }
- }
- }
- error_array = [assigns(:updated_articles).first.errors.first, assigns(:updated_articles).last.errors.first]
- expect(error_array).not_to be_any
- expect(response).to have_http_status(:redirect)
- end
-
- it 'does not delete articles in open order' do
- get_with_supplier :update_synchronized, params: { outlisted_articles: { article_no_supplier.id => article_no_supplier } }
- article_no_supplier.reload
- expect(article_no_supplier).not_to be_deleted
- expect(response).to have_http_status(:success)
- end
-
- it 'assigns updated article_pairs on error' do
- get_with_supplier :update_synchronized, params: {
- articles: { article_a.id => { name: 'EEEE' } },
- outlisted_articles: { article_no_supplier.id => article_no_supplier }
- }
- expect(assigns(:updated_article_pairs).first).to eq([article_a, { name: 'EEEE' }])
- article_no_supplier.reload
- expect(article_no_supplier).not_to be_deleted
- expect(response).to have_http_status(:success)
- end
-
- it 'updates articles in open order' do
- get_with_supplier :update_synchronized, params: { articles: { article_no_supplier.id => { name: 'EEEE' } } }
- article_no_supplier.reload
- expect(article_no_supplier.name).to eq 'EEEE'
- expect(response).to have_http_status(:redirect)
- end
- end
-
- describe '#shared' do
- let(:shared_supplier) { create :shared_supplier, shared_articles: [shared_article] }
- let(:shared_article) { create :shared_article, name: 'shared' }
- let(:article_s) { create :article, name: 'SSSS', note: 'AAAA', unit: '250 g', article_category: article_category_a, availability: false }
-
- let(:supplier_with_shared) { create :supplier, shared_supplier: shared_supplier }
-
- it 'renders view with articles' do
- get_with_defaults :shared, params: { supplier_id: supplier_with_shared.id, name_cont_all_joined: 'shared' }, xhr: true
- expect(assigns(:supplier).shared_supplier.shared_articles).to be_any
- expect(assigns(:articles)).to be_any
- expect(response).to have_http_status(:success)
- end
- end
-
- describe '#import' do
- let(:shared_supplier) { create :shared_supplier, shared_articles: [shared_article] }
- let(:shared_article) { create :shared_article, name: 'shared' }
-
- before do
- shared_article
- article_category_a
- end
-
- it 'fills form with article details' do
- get_with_supplier :import, params: { article_category_id: article_category_b.id, direct: 'true', shared_article_id: shared_article.id }, xhr: true
- expect(assigns(:article)).not_to be_nil
- expect(response).to have_http_status(:success)
- expect(response).to render_template(:create)
- end
-
- it 'does redirect to :new if param :direct not set' do
- get_with_supplier :import, params: { article_category_id: article_category_b.id, shared_article_id: shared_article.id }, xhr: true
- expect(assigns(:article)).not_to be_nil
- expect(response).to have_http_status(:success)
- expect(response).to render_template(:new)
- end
- end
-end
diff --git a/spec/controllers/concerns/auth_concern_spec.rb b/spec/controllers/concerns/auth_concern_spec.rb
deleted file mode 100644
index 10bf8ec7..00000000
--- a/spec/controllers/concerns/auth_concern_spec.rb
+++ /dev/null
@@ -1,212 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-class DummyAuthController < ApplicationController; end
-
-describe 'Auth concern', type: :controller do
- controller DummyAuthController do
- # Defining a dummy action for an anynomous controller which inherits from the described class.
- def authenticate_blank
- authenticate
- end
-
- def authenticate_unknown_group
- authenticate('nooby')
- end
-
- def authenticate_pickups
- authenticate('pickups')
- head :ok unless performed?
- end
-
- def authenticate_finance_or_orders
- authenticate('finance_or_orders')
- head :ok unless performed?
- end
-
- def try_authenticate_membership_or_admin
- authenticate_membership_or_admin
- end
-
- def try_authenticate_or_token
- authenticate_or_token('xyz')
- head :ok unless performed?
- end
-
- def call_deny_access
- deny_access
- end
-
- def call_current_user
- current_user
- end
-
- def call_login_and_redirect_to_return_to
- user = User.find(params[:user_id])
- login_and_redirect_to_return_to(user)
- end
-
- def call_login
- user = User.find(params[:user_id])
- login(user)
- end
- end
-
- # unit testing protected/private methods
- describe 'protected/private methods' do
- let(:user) { create :user }
- let(:wrong_user) { create :user }
-
- describe '#current_user' do
- before do
- login user
- routes.draw { get 'call_current_user' => 'dummy_auth#call_current_user' }
- end
-
- describe 'with valid session' do
- it 'returns current_user' do
- get_with_defaults :call_current_user, params: { user_id: user.id }, format: JSON
- expect(assigns(:current_user)).to eq user
- end
- end
-
- describe 'with invalid session' do
- it 'not returns current_user' do
- session[:user_id] = nil
- get_with_defaults :call_current_user, params: { user_id: nil }, format: JSON
- expect(assigns(:current_user)).to be_nil
- end
- end
- end
-
- describe '#deny_access' do
- it 'redirects to root_url' do
- login user
- routes.draw { get 'deny_access' => 'dummy_auth#call_deny_access' }
- get_with_defaults :call_deny_access
- expect(response).to redirect_to(root_url)
- end
- end
-
- describe '#login' do
- before do
- routes.draw { get 'call_login' => 'dummy_auth#call_login' }
- end
-
- it 'sets user in session' do
- login wrong_user
- get_with_defaults :call_login, params: { user_id: user.id }, format: JSON
- expect(session[:user_id]).to eq user.id
- expect(session[:scope]).to eq FoodsoftConfig.scope
- expect(session[:locale]).to eq user.locale
- end
- end
-
- describe '#login_and_redirect_to_return_to' do
- it 'redirects to already set target' do
- login user
- session[:return_to] = my_profile_url
- routes.draw { get 'call_login_and_redirect_to_return_to' => 'dummy_auth#call_login_and_redirect_to_return_to' }
- get_with_defaults :call_login_and_redirect_to_return_to, params: { user_id: user.id }
- expect(session[:return_to]).to be_nil
- end
- end
- end
-
- describe 'authenticate' do
- describe 'not logged in' do
- it 'does not authenticate' do
- routes.draw { get 'authenticate_blank' => 'dummy_auth#authenticate_blank' }
- get_with_defaults :authenticate_blank
- expect(response).to have_http_status(:redirect)
- expect(response).to redirect_to(login_path)
- expect(flash[:alert]).to match(I18n.t('application.controller.error_authn'))
- end
- end
-
- describe 'logged in' do
- let(:user) { create :user }
- let(:pickups_user) { create :user, :role_pickups }
- let(:finance_user) { create :user, :role_finance }
- let(:orders_user) { create :user, :role_orders }
-
- it 'does not authenticate with unknown group' do
- login user
- routes.draw { get 'authenticate_unknown_group' => 'dummy_auth#authenticate_unknown_group' }
- get_with_defaults :authenticate_unknown_group
- expect(response).to have_http_status(:redirect)
- expect(response).to redirect_to(root_path)
- expect(flash[:alert]).to match(I18n.t('application.controller.error_denied', sign_in: ActionController::Base.helpers.link_to(I18n.t('application.controller.error_denied_sign_in'), login_path)))
- end
-
- it 'does not authenticate with pickups group' do
- login pickups_user
- routes.draw { get 'authenticate_pickups' => 'dummy_auth#authenticate_pickups' }
- get_with_defaults :authenticate_pickups
- expect(response).to have_http_status(:success)
- end
-
- it 'does not authenticate with finance group' do
- login finance_user
- routes.draw { get 'authenticate_finance_or_orders' => 'dummy_auth#authenticate_finance_or_orders' }
- get_with_defaults :authenticate_finance_or_orders
- expect(response).to have_http_status(:success)
- end
-
- it 'does not authenticate with orders group' do
- login orders_user
- routes.draw { get 'authenticate_finance_or_orders' => 'dummy_auth#authenticate_finance_or_orders' }
- get_with_defaults :authenticate_finance_or_orders
- expect(response).to have_http_status(:success)
- end
- end
- end
-
- describe 'authenticate_membership_or_admin' do
- describe 'logged in' do
- let(:pickups_user) { create :user, :role_pickups }
- let(:workgroup) { create :workgroup }
-
- it 'redirects with not permitted group' do
- group_id = workgroup.id
- login pickups_user
- routes.draw { get 'try_authenticate_membership_or_admin' => 'dummy_auth#try_authenticate_membership_or_admin' }
- get_with_defaults :try_authenticate_membership_or_admin, params: { id: group_id }
- expect(response).to have_http_status(:redirect)
- expect(response).to redirect_to(root_path)
- expect(flash[:alert]).to match(I18n.t('application.controller.error_members_only'))
- end
- end
- end
-
- describe 'authenticate_or_token' do
- describe 'logged in' do
- let(:token_verifier) { TokenVerifier.new('xyz') }
- let(:token_msg) { token_verifier.generate }
- let(:user) { create :user }
-
- before { login user }
-
- it 'authenticates token' do
- routes.draw { get 'try_authenticate_or_token' => 'dummy_auth#try_authenticate_or_token' }
- get_with_defaults :try_authenticate_or_token, params: { token: token_msg }
- expect(response).not_to have_http_status(:redirect)
- end
-
- it 'redirects on faulty token' do
- routes.draw { get 'try_authenticate_or_token' => 'dummy_auth#try_authenticate_or_token' }
- get_with_defaults :try_authenticate_or_token, params: { token: 'abc' }
- expect(response).to have_http_status(:redirect)
- expect(response).to redirect_to(root_path)
- expect(flash[:alert]).to match(I18n.t('application.controller.error_token'))
- end
-
- it 'authenticates current user on empty token' do
- routes.draw { get 'try_authenticate_or_token' => 'dummy_auth#try_authenticate_or_token' }
- get_with_defaults :try_authenticate_or_token
- expect(response).to have_http_status(:success)
- end
- end
- end
-end
diff --git a/spec/controllers/finance/balancing_controller_spec.rb b/spec/controllers/finance/balancing_controller_spec.rb
deleted file mode 100644
index d62b9974..00000000
--- a/spec/controllers/finance/balancing_controller_spec.rb
+++ /dev/null
@@ -1,211 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-describe Finance::BalancingController, type: :controller do
- let(:user) { create :user, :role_finance, :role_orders, groups: [create(:ordergroup)] }
-
- before { login user }
-
- describe 'GET index' do
- let(:order) { create :order }
-
- it 'renders index page' do
- get_with_defaults :index
- expect(response).to have_http_status(:success)
- expect(response).to render_template('finance/balancing/index')
- end
- end
-
- describe 'new balancing' do
- let(:supplier) { create :supplier }
- let(:article1) { create :article, name: 'AAAA', supplier: supplier, unit_quantity: 1 }
- let(:article2) { create :article, name: 'AAAB', supplier: supplier, unit_quantity: 1 }
-
- let(:order) { create :order, supplier: supplier, article_ids: [article1.id, article2.id] }
-
- let(:go1) { create :group_order, order: order }
- let(:go2) { create :group_order, order: order }
- let(:oa1) { order.order_articles.find_by_article_id(article1.id) }
- let(:oa2) { order.order_articles.find_by_article_id(article2.id) }
- let(:oa3) { order2.order_articles.find_by_article_id(article2.id) }
- let(:goa1) { create :group_order_article, group_order: go1, order_article: oa1 }
- let(:goa2) { create :group_order_article, group_order: go1, order_article: oa2 }
-
- before do
- goa1.update_quantities(3, 0)
- goa2.update_quantities(1, 0)
- oa1.update_results!
- oa2.update_results!
- end
-
- it 'renders new order page' do
- get_with_defaults :new, params: { order_id: order.id }
- expect(response).to have_http_status(:success)
- expect(response).to render_template('finance/balancing/new')
- end
-
- it 'assigns sorting on articles' do
- sortings = [
- ['name', [oa1, oa2]],
- ['name_reverse', [oa2, oa1]],
- ['order_number', [oa1, oa2]],
- ['order_number_reverse', [oa1, oa2]] # just one order
- ]
- sortings.each do |sorting|
- get_with_defaults :new, params: { order_id: order.id, sort: sorting[0] }
- expect(response).to have_http_status(:success)
- expect(assigns(:articles).to_a).to eq(sorting[1])
- end
- end
- end
-
- describe 'update summary' do
- let(:order) { create(:order) }
-
- it 'shows the summary view' do
- get_with_defaults :update_summary, params: { id: order.id }, xhr: true
- expect(response).to have_http_status(:success)
- expect(response).to render_template('finance/balancing/update_summary')
- end
- end
-
- describe 'new_on_order' do
- let(:order) { create(:order) }
- let(:order_article) { order.order_articles.first }
-
- it 'calls article update' do
- get_with_defaults :new_on_order_article_update, params: { id: order.id, order_article_id: order_article.id }, xhr: true
- expect(response).not_to render_template(layout: 'application')
- expect(response).to render_template('finance/balancing/new_on_order_article_update')
- end
-
- it 'calls article create' do
- get_with_defaults :new_on_order_article_create, params: { id: order.id, order_article_id: order_article.id }, xhr: true
- expect(response).not_to render_template(layout: 'application')
- expect(response).to render_template('finance/balancing/new_on_order_article_create')
- end
- end
-
- describe 'edit_note' do
- let(:order) { create(:order) }
-
- it 'updates order note' do
- get_with_defaults :edit_note, params: { id: order.id, order: { note: 'Hello' } }, xhr: true
- expect(response).to have_http_status(:success)
- expect(response).to render_template('finance/balancing/edit_note')
- end
- end
-
- describe 'update_note' do
- let(:order) { create(:order) }
-
- it 'updates order note' do
- get_with_defaults :update_note, params: { id: order.id, order: { note: 'Hello' } }, xhr: true
- expect(response).to have_http_status(:success)
- end
-
- it 'redirects to edit note on failed update' do
- get_with_defaults :update_note, params: { id: order.id, order: { article_ids: nil } }, xhr: true
- expect(response).to have_http_status(:success)
- expect(response).to render_template('finance/balancing/edit_note')
- end
- end
-
- describe 'transport' do
- let(:order) { create(:order) }
-
- it 'calls the edit transport view' do
- get_with_defaults :edit_transport, params: { id: order.id }, xhr: true
- expect(response).to have_http_status(:success)
- expect(response).to render_template('finance/balancing/edit_transport')
- end
-
- it 'does redirect if order valid' do
- get_with_defaults :update_transport, params: { id: order.id, order: { ends: Time.now } }, xhr: true
- expect(response).to have_http_status(:redirect)
- expect(assigns(:order).errors.count).to eq(0)
- expect(response).to redirect_to(new_finance_order_path(order_id: order.id))
- end
-
- it 'does redirect if order invalid' do
- get_with_defaults :update_transport, params: { id: order.id, order: { starts: Time.now + 2, ends: Time.now } }, xhr: true
- expect(assigns(:order).errors.count).to eq(1)
- expect(response).to have_http_status(:redirect)
- expect(response).to redirect_to(new_finance_order_path(order_id: order.id))
- end
- end
-
- describe 'confirm' do
- let(:order) { create(:order) }
-
- it 'renders the confirm template' do
- get_with_defaults :confirm, params: { id: order.id }, xhr: true
- expect(response).to have_http_status(:success)
- expect(response).to render_template('finance/balancing/confirm')
- end
- end
-
- describe 'close and update account balances' do
- let(:order) { create(:order) }
- let(:order1) { create(:order, ends: Time.now) }
- let(:fft) { create(:financial_transaction_type) }
-
- it 'does not close order if ends not set' do
- get_with_defaults :close, params: { id: order.id, type: fft.id }
- expect(assigns(:order)).not_to be_closed
- expect(response).to have_http_status(:redirect)
- expect(response).to redirect_to(new_finance_order_url(order_id: order.id))
- end
-
- it 'closes order' do
- get_with_defaults :close, params: { id: order1.id, type: fft.id }
- expect(assigns(:order)).to be_closed
- expect(response).to have_http_status(:redirect)
- expect(response).to redirect_to(finance_order_index_url)
- end
- end
-
- describe 'close direct' do
- let(:order) { create(:order) }
-
- it 'does not close order if already closed' do
- order.close_direct!(user)
- get_with_defaults :close_direct, params: { id: order.id }
- expect(assigns(:order)).to be_closed
- end
-
- it 'closes order directly' do
- get_with_defaults :close_direct, params: { id: order.id }
- expect(assigns(:order)).to be_closed
- end
- end
-
- describe 'close all direct' do
- let(:invoice) { create(:invoice) }
- let(:invoice1) { create(:invoice) }
- let(:order) { create(:order, state: 'finished', ends: Time.now + 2.hours, invoice: invoice) }
- let(:order1) { create(:order, state: 'finished', ends: Time.now + 2.hours) }
-
- before do
- order
- order1
- end
-
- it 'does close orders' do
- get_with_defaults :close_all_direct_with_invoice
- order.reload
- expect(order).to be_closed
- expect(response).to have_http_status(:redirect)
- expect(response).to redirect_to(finance_order_index_url)
- end
-
- it 'does not close orders when invoice not set' do
- get_with_defaults :close_all_direct_with_invoice
- order1.reload
- expect(order1).not_to be_closed
- expect(response).to have_http_status(:redirect)
- expect(response).to redirect_to(finance_order_index_url)
- end
- end
-end
diff --git a/spec/controllers/finance/base_controller_spec.rb b/spec/controllers/finance/base_controller_spec.rb
deleted file mode 100644
index 388f3a17..00000000
--- a/spec/controllers/finance/base_controller_spec.rb
+++ /dev/null
@@ -1,30 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-describe Finance::BaseController, type: :controller do
- let(:user) { create :user, :role_finance, :role_orders, :ordergroup }
-
- before { login user }
-
- describe 'GET index' do
- let(:fin_trans) { create_list :financial_transaction, 3, user: user, ordergroup: user.ordergroup }
- let(:orders) { create_list :order, 2, state: 'finished' }
- let(:invoices) { create_list :invoice, 4 }
-
- before do
- fin_trans
- orders
- invoices
- end
-
- it 'renders index page' do
- get_with_defaults :index
- expect(response).to have_http_status(:success)
- expect(response).to render_template('finance/index')
- expect(assigns(:financial_transactions).size).to eq(fin_trans.size)
- expect(assigns(:orders).size).to eq(orders.size)
- expect(assigns(:unpaid_invoices).size).to eq(invoices.size)
- end
- end
-end
diff --git a/spec/controllers/finance/ordergroups_controller_spec.rb b/spec/controllers/finance/ordergroups_controller_spec.rb
index f960c61d..73c1f3bb 100644
--- a/spec/controllers/finance/ordergroups_controller_spec.rb
+++ b/spec/controllers/finance/ordergroups_controller_spec.rb
@@ -3,24 +3,30 @@
require 'spec_helper'
describe Finance::OrdergroupsController do
+ include ActionView::Helpers::NumberHelper
+ render_views
+
let(:user) { create(:user, :role_finance, :role_orders, :ordergroup) }
let(:fin_trans_type1) { create(:financial_transaction_type) }
let(:fin_trans_type2) { create(:financial_transaction_type) }
let(:fin_trans1) do
create(:financial_transaction,
user: user,
+ amount: 100,
ordergroup: user.ordergroup,
financial_transaction_type: fin_trans_type1)
end
let(:fin_trans2) do
create(:financial_transaction,
user: user,
+ amount: 200,
ordergroup: user.ordergroup,
financial_transaction_type: fin_trans_type1)
end
let(:fin_trans3) do
create(:financial_transaction,
user: user,
+ amount: 42.23,
ordergroup: user.ordergroup,
financial_transaction_type: fin_trans_type2)
end
@@ -37,14 +43,15 @@ describe Finance::OrdergroupsController do
it 'renders index page' do
get_with_defaults :index
expect(response).to have_http_status(:success)
- expect(response).to render_template('finance/ordergroups/index')
end
it 'calculates total balance sums correctly' do
get_with_defaults :index
- expect(assigns(:total_balances).size).to eq(2)
- expect(assigns(:total_balances)[fin_trans_type1.id]).to eq(fin_trans1.amount + fin_trans2.amount)
- expect(assigns(:total_balances)[fin_trans_type2.id]).to eq(fin_trans3.amount)
+ expect(response).to have_http_status(:success)
+
+ assert_select "#total_balance#{fin_trans_type1.financial_transaction_class_id}", number_to_currency(300)
+ assert_select "#total_balance#{fin_trans_type2.financial_transaction_class_id}", number_to_currency(42.23)
+ assert_select '#total_balance_sum', number_to_currency(342.23)
end
end
end
diff --git a/spec/controllers/home_controller_spec.rb b/spec/controllers/home_controller_spec.rb
index be106282..525c27e4 100644
--- a/spec/controllers/home_controller_spec.rb
+++ b/spec/controllers/home_controller_spec.rb
@@ -2,8 +2,8 @@
require 'spec_helper'
-describe HomeController, type: :controller do
- let(:user) { create :user }
+describe HomeController do
+ let(:user) { create(:user) }
describe 'GET index' do
describe 'NOT logged in' do
@@ -14,16 +14,12 @@ describe HomeController, type: :controller do
end
end
- describe 'logegd in' do
+ describe 'logged in' do
before { login user }
- it 'assigns tasks' do
+ it 'succeeds' do
get_with_defaults :index
-
- expect(assigns(:unaccepted_tasks)).not_to be_nil
- expect(assigns(:next_tasks)).not_to be_nil
- expect(assigns(:unassigned_tasks)).not_to be_nil
- expect(response).to render_template('home/index')
+ expect(response).to have_http_status(:success)
end
end
end
@@ -31,10 +27,9 @@ describe HomeController, type: :controller do
describe 'GET profile' do
before { login user }
- it 'renders dashboard' do
+ it 'succeeds' do
get_with_defaults :profile
expect(response).to have_http_status(:success)
- expect(response).to render_template('home/profile')
end
end
@@ -50,14 +45,13 @@ describe HomeController, type: :controller do
end
describe 'with ordergroup user' do
- let(:og_user) { create :user, :ordergroup }
+ let(:og_user) { create(:user, :ordergroup) }
before { login og_user }
- it 'renders reference calculator' do
+ it 'succeeds' do
get_with_defaults :reference_calculator
expect(response).to have_http_status(:success)
- expect(response).to render_template('home/reference_calculator')
end
end
end
@@ -65,16 +59,14 @@ describe HomeController, type: :controller do
describe 'GET update_profile' do
describe 'with simple user' do
let(:unchanged_attributes) { user.attributes.slice('first_name', 'last_name', 'email') }
- let(:changed_attributes) { attributes_for :user }
+ let(:changed_attributes) { attributes_for(:user) }
let(:invalid_attributes) { { email: 'e.mail.com' } }
before { login user }
- it 'renders profile after update with invalid attributes' do
+ it 'stays on profile after update with invalid attributes' do
get_with_defaults :update_profile, params: { user: invalid_attributes }
expect(response).to have_http_status(:success)
- expect(response).to render_template('home/profile')
- expect(assigns(:current_user).errors.present?).to be true
end
it 'redirects to profile after update with unchanged attributes' do
@@ -88,12 +80,13 @@ describe HomeController, type: :controller do
expect(response).to have_http_status(:redirect)
expect(response).to redirect_to(my_profile_path)
expect(flash[:notice]).to match(/#{I18n.t('home.changes_saved')}/)
- expect(user.reload.attributes.slice(:first_name, :last_name, :email)).to eq(changed_attributes.slice('first_name', 'last_name', 'email'))
+ expect(user.reload.attributes.slice(:first_name, :last_name,
+ :email)).to eq(changed_attributes.slice('first_name', 'last_name', 'email'))
end
end
describe 'with ordergroup user' do
- let(:og_user) { create :user, :ordergroup }
+ let(:og_user) { create(:user, :ordergroup) }
let(:unchanged_attributes) { og_user.attributes.slice('first_name', 'last_name', 'email') }
let(:changed_attributes) { unchanged_attributes.merge({ ordergroup: { contact_address: 'new Adress 7' } }) }
@@ -120,40 +113,13 @@ describe HomeController, type: :controller do
end
describe 'with ordergroup user' do
- let(:og_user) { create :user, :ordergroup }
+ let(:og_user) { create(:user, :ordergroup) }
before { login og_user }
- it 'renders ordergroup' do
+ it 'succeeds' do
get_with_defaults :ordergroup
expect(response).to have_http_status(:success)
- expect(response).to render_template('home/ordergroup')
- end
-
- describe 'assigns sortings' do
- let(:fin_trans1) { create :financial_transaction, user: og_user, ordergroup: og_user.ordergroup, note: 'A', amount: 100 }
- let(:fin_trans2) { create :financial_transaction, user: og_user, ordergroup: og_user.ordergroup, note: 'B', amount: 200, created_on: Time.now + 1.minute }
-
- before do
- fin_trans1
- fin_trans2
- end
-
- it 'by criteria' do
- sortings = [
- ['date', [fin_trans1, fin_trans2]],
- ['note', [fin_trans1, fin_trans2]],
- ['amount', [fin_trans1, fin_trans2]],
- ['date_reverse', [fin_trans2, fin_trans1]],
- ['note_reverse', [fin_trans2, fin_trans1]],
- ['amount_reverse', [fin_trans2, fin_trans1]]
- ]
- sortings.each do |sorting|
- get_with_defaults :ordergroup, params: { sort: sorting[0] }
- expect(response).to have_http_status(:success)
- expect(assigns(:financial_transactions).to_a).to eq(sorting[1])
- end
- end
end
end
end
@@ -167,13 +133,13 @@ describe HomeController, type: :controller do
get_with_defaults :cancel_membership
end.to raise_error(ActiveRecord::RecordNotFound)
expect do
- get_with_defaults :cancel_membership, params: { membership_id: 424242 }
+ get_with_defaults :cancel_membership, params: { membership_id: 424_242 }
end.to raise_error(ActiveRecord::RecordNotFound)
end
end
describe 'with ordergroup user' do
- let(:fin_user) { create :user, :role_finance }
+ let(:fin_user) { create(:user, :role_finance) }
before { login fin_user }
@@ -182,7 +148,7 @@ describe HomeController, type: :controller do
get_with_defaults :cancel_membership, params: { group_id: fin_user.groups.first.id }
expect(response).to have_http_status(:redirect)
expect(response).to redirect_to(my_profile_path)
- expect(flash[:notice]).to match(/#{I18n.t('home.ordergroup_cancelled', :group => membership.group.name)}/)
+ expect(flash[:notice]).to match(/#{I18n.t('home.ordergroup_cancelled', group: membership.group.name)}/)
end
it 'removes user membership' do
@@ -190,7 +156,7 @@ describe HomeController, type: :controller do
get_with_defaults :cancel_membership, params: { membership_id: membership.id }
expect(response).to have_http_status(:redirect)
expect(response).to redirect_to(my_profile_path)
- expect(flash[:notice]).to match(/#{I18n.t('home.ordergroup_cancelled', :group => membership.group.name)}/)
+ expect(flash[:notice]).to match(/#{I18n.t('home.ordergroup_cancelled', group: membership.group.name)}/)
end
end
end
diff --git a/spec/controllers/login_controller_spec.rb b/spec/controllers/login_controller_spec.rb
deleted file mode 100644
index c824e429..00000000
--- a/spec/controllers/login_controller_spec.rb
+++ /dev/null
@@ -1,67 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-describe LoginController, type: :controller do
- let(:invite) { create :invite }
-
- describe 'GET accept_invitation' do
- let(:expired_invite) { create :expired_invite }
-
- describe 'with valid token' do
- it 'accepts invitation' do
- get_with_defaults :accept_invitation, params: { token: invite.token }
- expect(response).to have_http_status(:success)
- expect(response).to render_template('login/accept_invitation')
- end
- end
-
- describe 'with invalid token' do
- it 'redirects to login' do
- get_with_defaults :accept_invitation, params: { token: invite.token + 'XX' }
- expect(response).to have_http_status(:redirect)
- expect(response).to redirect_to(login_url)
- expect(flash[:alert]).to match(I18n.t('login.controller.error_invite_invalid'))
- end
- end
-
- describe 'with timed out token' do
- it 'redirects to login' do
- get_with_defaults :accept_invitation, params: { token: expired_invite.token }
- expect(response).to have_http_status(:redirect)
- expect(response).to redirect_to(login_url)
- expect(flash[:alert]).to match(I18n.t('login.controller.error_invite_invalid'))
- end
- end
-
- describe 'without group' do
- it 'redirects to login' do
- invite.group.destroy
- get_with_defaults :accept_invitation, params: { token: invite.token }
- expect(response).to have_http_status(:redirect)
- expect(response).to redirect_to(login_url)
- expect(flash[:alert]).to match(I18n.t('login.controller.error_group_invalid'))
- end
- end
- end
-
- describe 'POST accept_invitation' do
- describe 'with invalid parameters' do
- it 'renders accept_invitation view' do
- post_with_defaults :accept_invitation, params: { token: invite.token, user: invite.user.slice('first_name') }
- expect(response).to have_http_status(:success)
- expect(response).to render_template('login/accept_invitation')
- expect(assigns(:user).errors.present?).to be true
- end
- end
-
- describe 'with valid parameters' do
- it 'redirects to login' do
- post_with_defaults :accept_invitation, params: { token: invite.token, user: invite.user.slice('first_name', 'password') }
- expect(response).to have_http_status(:redirect)
- expect(response).to redirect_to(login_url)
- expect(flash[:notice]).to match(I18n.t('login.controller.accept_invitation.notice'))
- end
- end
- end
-end
diff --git a/spec/factories/delivery.rb b/spec/factories/delivery.rb
index 5d27d870..e3b37d0a 100644
--- a/spec/factories/delivery.rb
+++ b/spec/factories/delivery.rb
@@ -2,7 +2,7 @@ require 'factory_bot'
FactoryBot.define do
factory :delivery do
- supplier { create :supplier }
+ supplier { create(:supplier) }
date { Time.now }
end
end
diff --git a/spec/factories/group_order.rb b/spec/factories/group_order.rb
index f7e910df..d62172ea 100644
--- a/spec/factories/group_order.rb
+++ b/spec/factories/group_order.rb
@@ -4,6 +4,6 @@ FactoryBot.define do
# requires order
factory :group_order do
ordergroup { create(:user, groups: [FactoryBot.create(:ordergroup)]).ordergroup }
- updated_by { create :user }
+ updated_by { create(:user) }
end
end
diff --git a/spec/factories/invite.rb b/spec/factories/invite.rb
deleted file mode 100644
index 51d48840..00000000
--- a/spec/factories/invite.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-require 'factory_bot'
-
-FactoryBot.define do
- factory :invite do
- user { create :user }
- group { create :group }
- email { Faker::Internet.email }
-
- factory :expired_invite do
- after :create do |invite|
- invite.update_column(:expires_at, Time.now.yesterday)
- end
- end
- end
-end
diff --git a/spec/factories/invoice.rb b/spec/factories/invoice.rb
index b3e65a17..3564d977 100644
--- a/spec/factories/invoice.rb
+++ b/spec/factories/invoice.rb
@@ -3,9 +3,9 @@ require 'factory_bot'
FactoryBot.define do
factory :invoice do
supplier
- number { rand(1..99999) }
+ number { rand(1..99_999) }
amount { rand(0.1..26.0).round(2) }
- created_by { create :user }
+ created_by { create(:user) }
after :create do |invoice|
invoice.supplier.reload
diff --git a/spec/factories/order.rb b/spec/factories/order.rb
index 87febae2..970bd040 100644
--- a/spec/factories/order.rb
+++ b/spec/factories/order.rb
@@ -3,10 +3,10 @@ require 'factory_bot'
FactoryBot.define do
factory :order do
starts { Time.now }
- supplier { create :supplier, article_count: (article_count.nil? ? true : article_count) }
+ supplier { create(:supplier, article_count: (article_count.nil? ? true : article_count)) }
article_ids { supplier.articles.map(&:id) unless supplier.nil? }
- created_by { create :user }
- updated_by { create :user }
+ created_by { create(:user) }
+ updated_by { create(:user) }
transient do
article_count { true }
diff --git a/spec/factories/order_article.rb b/spec/factories/order_article.rb
deleted file mode 100644
index 99ca8701..00000000
--- a/spec/factories/order_article.rb
+++ /dev/null
@@ -1,8 +0,0 @@
-require 'factory_bot'
-
-FactoryBot.define do
- factory :order_article do
- order { create :order }
- article { create :article }
- end
-end
diff --git a/spec/factories/supplier.rb b/spec/factories/supplier.rb
index 67ba3528..ef592a60 100644
--- a/spec/factories/supplier.rb
+++ b/spec/factories/supplier.rb
@@ -10,8 +10,8 @@ FactoryBot.define do
article_count { 0 }
end
- before :create do |supplier, evaluator|
- next if supplier.class == SharedSupplier
+ before :create do |supplier, _evaluator|
+ next if supplier.instance_of?(SharedSupplier)
next if supplier.supplier_category_id?
supplier.supplier_category = create :supplier_category
@@ -20,7 +20,7 @@ FactoryBot.define do
after :create do |supplier, evaluator|
article_count = evaluator.article_count
article_count = rand(1..99) if article_count == true
- create_list :article, article_count, supplier: supplier
+ create_list(:article, article_count, supplier: supplier)
end
factory :shared_supplier, class: 'SharedSupplier'
diff --git a/spec/factories/user.rb b/spec/factories/user.rb
index a6067e6b..9563c15c 100644
--- a/spec/factories/user.rb
+++ b/spec/factories/user.rb
@@ -10,21 +10,21 @@ FactoryBot.define do
factory :admin do
sequence(:nick) { |n| "admin#{n}" }
first_name { 'Administrator' }
- after :create do |user, evaluator|
- create :workgroup, role_admin: true, user_ids: [user.id]
+ after :create do |user, _evaluator|
+ create(:workgroup, role_admin: true, user_ids: [user.id])
end
end
trait :ordergroup do
- after :create do |user, evaluator|
- create :ordergroup, user_ids: [user.id]
+ after :create do |user, _evaluator|
+ create(:ordergroup, user_ids: [user.id])
end
end
- [:ordergroup, :finance, :invoices, :article_meta, :suppliers, :pickups, :orders].each do |role|
+ %i[ordergroup finance invoices article_meta suppliers pickups orders].each do |role|
trait "role_#{role}".to_sym do
- after :create do |user, evaluator|
- create :workgroup, "role_#{role}" => true, user_ids: [user.id]
+ after :create do |user, _evaluator|
+ create(:workgroup, "role_#{role}" => true, user_ids: [user.id])
end
end
end
@@ -37,7 +37,7 @@ FactoryBot.define do
type { 'Workgroup' }
end
- factory :ordergroup, class: "Ordergroup" do
+ factory :ordergroup, class: 'Ordergroup' do
type { 'Ordergroup' }
sequence(:name) { |n| "Order group ##{n}" }
# workaround to avoid needing to save the ordergroup
diff --git a/spec/fixtures/bnn_file_01.bnn b/spec/fixtures/bnn_file_01.bnn
deleted file mode 100644
index 177da7be..00000000
--- a/spec/fixtures/bnn_file_01.bnn
+++ /dev/null
@@ -1,5 +0,0 @@
-BNN;3;0;Naturkost Nord, Hamburg;T;Angebot Nr. 0922;EUR;20220905;20221001;20220825;837;1
-29932;;;;4280001958081;4280001958203;Walnoten (ongeroosterd);bio;;;med;;GR;C%;DE-?KO-001;120;1302;10;55;;1;;1;1 kg;1;N;930190;99260;;1,41;;;;1;;;4,49;2,34;J;;2;3;;;;;;;;;;;;;;;;;;;A;;;;;Kg;28,571;;
-28391;;;;4280001958081;4280001958203;Pijnboompitten;dem;;;med;;GR;C%;DE-?KO-001;120;1302;10;55;;1;;1;100 g;10;N;930190;99260;;1,41;;;;1;;;5,56;2.89;J;;2;3;;;;;;;;;;;;;;;;;;;A;;;;;Kg;28,571;;
-1829;;;;4280001958081;4280001958203;Appelsap (verpakt);;;;med;;GR;C%;DE-?KO-001;120;1302;10;55;;1;4x250 ml;10;4x250 ml;10;N;930190;99260;;3,21;;;;1;;;4,49;2.89;J;;2;3;;;;;;;;;;;;;;;;;;;A;;;;;ml;28,571;;
-177813;;;;4280001958081;4280001958203;Tomaten;bio;;;med;;GR;C%;DE-?KO-001;120;1302;10;55;;1;;1;500 g;20;N;930190;99260;;1,20;;;;1;;;4,49;2.89;J;;2;3;;;;;;;;;;;;;;;;;;;A;;;;;g;28,571;;
diff --git a/spec/fixtures/bnn_file_02.bnn b/spec/fixtures/bnn_file_02.bnn
deleted file mode 100644
index e3dba5bb..00000000
--- a/spec/fixtures/bnn_file_02.bnn
+++ /dev/null
@@ -1,2 +0,0 @@
-BNN;3;0;Naturkost Nord, Hamburg;T;Angebot Nr. 0922;EUR;20220905;20221001;20220825;837;1
-1;;;;4280001958081;4280001958203;Tomatoes;organic;;;med;;GR;C%;DE-?KO-001;120;1302;10;55;;1;;20;500 g;1;N;930190;99260;;1,41;;;;1;;;4,49;1,20;J;;2;3;;;;;;;;;;;;;;;;;;;A;;;;;g;28,571;;
\ No newline at end of file
diff --git a/spec/fixtures/files/upload_test.csv b/spec/fixtures/files/upload_test.csv
deleted file mode 100644
index ac2f59b0..00000000
--- a/spec/fixtures/files/upload_test.csv
+++ /dev/null
@@ -1,3 +0,0 @@
-avail.;Order number;Name;Note;Manufacturer;Origin;Unit;Price (net);VAT;Deposit;Unit quantity;"";"";Category
-"";;AAAA;AAAA;;;500 g;25.55;6.0;0.0;1;"";"";AAAA
-"";;BBBB;BBBB;;;250 g;12.11;6.0;0.0;2;"";"";BBBB
diff --git a/spec/fixtures/odin_file_01.xml b/spec/fixtures/odin_file_01.xml
deleted file mode 100644
index 3b60e83e..00000000
--- a/spec/fixtures/odin_file_01.xml
+++ /dev/null
@@ -1,273 +0,0 @@
-
-
-
-1039
-1.08
-Estafette Associatie C.V.
-Geldermalsen
-
-
-8719325207668
-Walnoten (ongeroosterd)
-Nucli rose
-
-0
-0
-0
-1
-kg
-Stuk
-0
-Het warme woud
-bio
-
-
-NL
-
-6
-1017515
-29932
-10
-Actief
-druiven*
-0
-0
-2
-2
-0
-0
-0
-2
-2
-0
-2
-0
-2
-0
-2
-2
-2
-2
-1
-0
-2
-0
-2
-2
-
-
-
-0
-0
-0
-0
-1
-
-2
-0
-
-adviesprijs
-2022-08-18
-2.34
-7.95
-
-
-
-8719325207668
-Pijnboompitten
-Nucli rose
-
-0
-0
-0
-100
-g
-Stuk
-0
-NELEMAN
-dem
-
-
-TR
-
-6
-1017515
-28391
-10
-Actief
-druiven*
-0
-0
-2
-2
-0
-0
-0
-2
-2
-0
-2
-0
-2
-0
-2
-2
-2
-2
-1
-0
-2
-0
-2
-2
-
-
-
-0
-0
-0
-0
-1
-
-2
-0
-
-adviesprijs
-2022-08-18
-5.56
-7.95
-
-
-
-8719325207668
-Appelsap (verpakt)
-Nucli rose
-
-0
-0
-0
-4x250
-ml
-Stuk
-0.4
-Appelgaarde
-
-
-
-DE
-
-6
-1017515
-1829
-10
-Actief
-druiven*
-0
-0
-2
-2
-0
-0
-0
-2
-2
-0
-2
-0
-2
-0
-2
-2
-2
-2
-1
-0
-2
-0
-2
-2
-
-
-
-0
-0
-0
-0
-1
-
-2
-0
-
-adviesprijs
-2022-08-18
-3.21
-7.95
-
-
-
-8719325207668
-Tomaten
-Nucli rose
-
-0
-0
-0
-500
-g
-Stuk
-0
-De röde hof
-bio
-
-
-DE
-
-6
-1017515
-177813
-20
-Actief
-druiven*
-0
-0
-2
-2
-0
-0
-0
-2
-2
-0
-2
-0
-2
-0
-2
-2
-2
-2
-1
-0
-2
-0
-2
-2
-
-
-
-0
-0
-0
-0
-1
-
-2
-0
-
-adviesprijs
-2022-08-18
-1.2
-7.95
-
-
-
\ No newline at end of file
diff --git a/spec/fixtures/odin_file_02.xml b/spec/fixtures/odin_file_02.xml
deleted file mode 100644
index c732b4d5..00000000
--- a/spec/fixtures/odin_file_02.xml
+++ /dev/null
@@ -1,75 +0,0 @@
-
-
-
-1039
-1.08
-Estafette Associatie C.V.
-Geldermalsen
-
-
-8719325207668
-Tomatoes
-Nucli rose
-
-0
-0
-0
-500
-g
-Stuk
-0
-De röde hof
-organic
-
-
-Somewhere, UK
-
-6
-1017515
-1
-20
-Actief
-druiven*
-0
-0
-2
-2
-0
-0
-0
-2
-2
-0
-2
-0
-2
-0
-2
-2
-2
-2
-1
-0
-2
-0
-2
-2
-
-
-
-0
-0
-0
-0
-1
-
-2
-0
-
-adviesprijs
-2022-08-18
-1.2
-7.95
-
-
-
\ No newline at end of file
diff --git a/spec/fixtures/upload_test.csv b/spec/fixtures/upload_test.csv
deleted file mode 100644
index ac2f59b0..00000000
--- a/spec/fixtures/upload_test.csv
+++ /dev/null
@@ -1,3 +0,0 @@
-avail.;Order number;Name;Note;Manufacturer;Origin;Unit;Price (net);VAT;Deposit;Unit quantity;"";"";Category
-"";;AAAA;AAAA;;;500 g;25.55;6.0;0.0;1;"";"";AAAA
-"";;BBBB;BBBB;;;250 g;12.11;6.0;0.0;2;"";"";BBBB
diff --git a/spec/integration/articles_spec.rb b/spec/integration/articles_spec.rb
index b6a3a243..bddd80d6 100644
--- a/spec/integration/articles_spec.rb
+++ b/spec/integration/articles_spec.rb
@@ -8,10 +8,7 @@ feature ArticlesController do
before { login user }
describe ':index', js: true do
- before {
- login user
- visit supplier_articles_path(supplier_id: supplier.id)
- }
+ before { visit supplier_articles_path(supplier_id: supplier.id) }
it 'can visit supplier articles path' do
expect(page).to have_content(supplier.name)
@@ -23,13 +20,13 @@ feature ArticlesController do
expect(page).to have_selector('form#new_article')
article = build(:article, supplier: supplier, article_category: article_category)
within('#new_article') do
- fill_in 'article_name', :with => article.name
- fill_in 'article_unit', :with => article.unit
- select article.article_category.name, :from => 'article_article_category_id'
- fill_in 'article_price', :with => article.price
- fill_in 'article_unit_quantity', :with => article.unit_quantity
- fill_in 'article_tax', :with => article.tax
- fill_in 'article_deposit', :with => article.deposit
+ fill_in 'article_name', with: article.name
+ fill_in 'article_unit', with: article.unit
+ select article.article_category.name, from: 'article_article_category_id'
+ fill_in 'article_price', with: article.price
+ fill_in 'article_unit_quantity', with: article.unit_quantity
+ fill_in 'article_tax', with: article.tax
+ fill_in 'article_deposit', with: article.deposit
# "Element cannot be scrolled into view" error, js as workaround
# find('input[type="submit"]').click
page.execute_script('$("form#new_article").submit();')
@@ -52,140 +49,71 @@ feature ArticlesController do
let(:file) { Rails.root.join(test_file) }
it do
- find("#articles_type option[value='foodsoft']").select_option
find('input[type="submit"]').click
- expect(find("tr:nth-child(1) #new_articles__note").value).to eq "bio ◎"
- expect(find("tr:nth-child(2) #new_articles__name").value).to eq "Pijnboompitten"
+ expect(find('tr:nth-child(1) #new_articles__note').value).to eq 'bio ◎'
+ expect(find('tr:nth-child(2) #new_articles__name').value).to eq 'Pijnboompitten'
4.times do |i|
all("tr:nth-child(#{i + 1}) select > option")[1].select_option
end
find('input[type="submit"]').click
- expect(page).to have_content("Pijnboompitten")
+ expect(page).to have_content('Pijnboompitten')
expect(supplier.articles.count).to eq 4
end
end
end
- Dir.glob('spec/fixtures/bnn_file_01.*') do |test_file|
- describe "can import articles from #{test_file}" do
- let(:file) { Rails.root.join(test_file) }
+ describe 'can update existing article' do
+ let!(:article) { create(:article, supplier: supplier, name: 'Foobar', order_number: 1, unit: '250 g') }
- it do
- find("#articles_type option[value='bnn']").select_option
- find('input[type="submit"]').click
- expect(find("tr:nth-child(1) #new_articles__note").value).to eq "bio"
- expect(find("tr:nth-child(1) #new_articles__name").value).to eq "Walnoten (ongeroosterd)"
- # set article category
- 4.times do |i|
- all("tr:nth-child(#{i + 1}) select > option")[1].select_option
- end
- find('input[type="submit"]').click
-
- expect(page).to have_content("Pijnboompitten")
-
- expect(supplier.articles.count).to eq 4
- end
+ it do
+ find('input[type="submit"]').click
+ expect(find("#articles_#{article.id}_name").value).to eq 'Tomatoes'
+ find('input[type="submit"]').click
+ article.reload
+ expect(article.name).to eq 'Tomatoes'
+ expect([article.unit, article.unit_quantity, article.price]).to eq ['500 g', 20, 1.2]
end
end
- end
- describe "updates" do
- file_paths = ['spec/fixtures/foodsoft_file_02.csv', 'spec/fixtures/bnn_file_02.bnn', 'spec/fixtures/odin_file_02.xml']
- let(:filename) { 'foodsoft_file_02.csv' }
- let(:file) { Rails.root.join("spec/fixtures/#{filename}") }
- let(:val) { 'foodsoft' }
- let(:type) { %w[foodsoft bnn odin] }
+ describe 'handles missing data' do
+ it do
+ find('input[type="submit"]').click # to overview
+ find('input[type="submit"]').click # missing category, re-show form
+ expect(find('tr.alert')).to be_present
+ expect(supplier.articles.count).to eq 0
- before do
- visit upload_supplier_articles_path(supplier_id: supplier.id)
- attach_file 'articles_file', file
- find("#articles_type option[value='#{val}']").select_option
+ all('tr select > option')[1].select_option
+ find('input[type="submit"]').click # now it should succeed
+ expect(supplier.articles.count).to eq 1
+ end
end
- file_paths.each_with_index do |test_file, index|
- describe "updates article for #{test_file}" do
- let(:article) { create(:article, supplier: supplier, name: 'Foobar', order_number: 1, unit: '250 g') }
- let(:file) { Rails.root.join(test_file) }
- let(:val) { type[index] }
+ describe 'can remove an existing article' do
+ let!(:article) { create(:article, supplier: supplier, name: 'Foobar', order_number: 99_999) }
- it do
- article.reload
- find('input[type="submit"]').click
- expect(find("#articles_#{article.id}_name").value).to eq 'Tomatoes'
- find('input[type="submit"]').click
- article.reload
- expect(article.name).to eq 'Tomatoes'
- if type[index] == "odin"
- expect([article.unit, article.unit_quantity, article.price]).to eq ['500gr', 20, 1.20]
- else
- expect([article.unit, article.unit_quantity, article.price]).to eq ['500 g', 20, 1.20]
- end
- end
+ it do
+ check('articles_outlist_absent')
+ find('input[type="submit"]').click
+ expect(find("#outlisted_articles_#{article.id}", visible: :all)).to be_present
- it "handles missing data" do
- find('input[type="submit"]').click # to overview
- find('input[type="submit"]').click # missing category, re-show form
- expect(find('tr.alert')).to be_present
- expect(supplier.articles.count).to eq 0
-
- all("tr select > option")[1].select_option
- find('input[type="submit"]').click # now it should succeed
- expect(supplier.articles.count).to eq 1
- end
+ all('tr select > option')[1].select_option
+ find('input[type="submit"]').click
+ expect(article.reload.deleted?).to be true
end
+ end
- describe "takes over category from file" do
- it do
- find(:css, '#articles_update_category[value="1"]').set(true) # check take over category from file
- expect(ArticleCategory.count).to eq 1 # new Category vegetables should be created from file
- find('input[type="submit"]').click # upload file
- find('input[type="submit"]').click # submit changes
- expect(ArticleCategory.count).to eq 2 # it is
- expect(supplier.articles.count).to eq 1
- expect(supplier.articles.first.article_category.name).to eq "Vegetables"
- end
- end
+ describe 'can convert units when updating' do
+ let!(:article) { create(:article, supplier: supplier, order_number: 1, unit: '250 g') }
- describe "overwrites article_category from file" do
- let!(:article_category) { create(:article_category, name: "Fruit") }
- let(:article) { create(:article, supplier: supplier, name: 'Tomatoes', order_number: 1, unit: '250 g', article_category: article_category) }
-
- it do
- find(:css, '#articles_update_category[value="1"]').set(true) # check take over category from file
- find('input[type="submit"]').click #upload file
- find('input[type="submit"]').click #submit changes
- expect(supplier.articles.count).to eq 1
- expect(supplier.articles.first.article_category.name).to eq "Vegetables"
- end
- end
-
- describe "can remove an existing article" do
- let!(:article) { create(:article, supplier: supplier, name: 'Foobar', order_number: 99999) }
-
- it do
- check('articles_outlist_absent')
- find('input[type="submit"]').click
- expect(find("#outlisted_articles_#{article.id}", visible: :all)).to be_present
-
- all("tr select > option")[1].select_option
- find('input[type="submit"]').click
- expect(article.reload.deleted?).to be true
- end
- end
-
- describe "can convert units when updating" do
- let!(:article) { create(:article, supplier: supplier, order_number: 1, unit: '250 g') }
-
- it do
- check('articles_convert_units')
- find('input[type="submit"]').click
- expect(find("#articles_#{article.id}_name").value).to eq 'Tomatoes'
- find('input[type="submit"]').click
- article.reload
- expect([article.unit, article.unit_quantity, article.price]).to eq ['250 g', 40, 0.6]
- end
+ it do
+ check('articles_convert_units')
+ find('input[type="submit"]').click
+ expect(find("#articles_#{article.id}_name").value).to eq 'Tomatoes'
+ find('input[type="submit"]').click
+ article.reload
+ expect([article.unit, article.unit_quantity, article.price]).to eq ['250 g', 40, 0.6]
end
end
end
diff --git a/spec/integration/balancing_spec.rb b/spec/integration/balancing_spec.rb
index 556d102d..d8e58e6d 100644
--- a/spec/integration/balancing_spec.rb
+++ b/spec/integration/balancing_spec.rb
@@ -1,17 +1,17 @@
require_relative '../spec_helper'
feature 'settling an order', js: true do
- let(:ftt) { create :financial_transaction_type }
- let(:admin) { create :user, groups: [create(:workgroup, role_finance: true)] }
- let(:user) { create :user, groups: [create(:ordergroup)] }
- let(:supplier) { create :supplier }
- let(:article) { create :article, supplier: supplier, unit_quantity: 1 }
- let(:order) { create :order, supplier: supplier, article_ids: [article.id] } # need to ref article
- let(:go1) { create :group_order, order: order }
- let(:go2) { create :group_order, order: order }
+ let(:ftt) { create(:financial_transaction_type) }
+ let(:admin) { create(:user, groups: [create(:workgroup, role_finance: true)]) }
+ let(:user) { create(:user, groups: [create(:ordergroup)]) }
+ let(:supplier) { create(:supplier) }
+ let(:article) { create(:article, supplier: supplier, unit_quantity: 1) }
+ let(:order) { create(:order, supplier: supplier, article_ids: [article.id]) } # need to ref article
+ let(:go1) { create(:group_order, order: order) }
+ let(:go2) { create(:group_order, order: order) }
let(:oa) { order.order_articles.find_by_article_id(article.id) }
- let(:goa1) { create :group_order_article, group_order: go1, order_article: oa }
- let(:goa2) { create :group_order_article, group_order: go2, order_article: oa }
+ let(:goa1) { create(:group_order_article, group_order: go1, order_article: oa) }
+ let(:goa2) { create(:group_order_article, group_order: go2, order_article: oa) }
before do
goa1.update_quantities(3, 0)
@@ -22,6 +22,9 @@ feature 'settling an order', js: true do
goa2.reload
end
+ before { visit new_finance_order_path(order_id: order.id) }
+ before { login admin }
+
it 'has correct order result' do
expect(oa.quantity).to eq(4)
expect(oa.tolerance).to eq(0)
@@ -29,10 +32,6 @@ feature 'settling an order', js: true do
expect(goa2.result).to eq(1)
end
- before { login admin }
-
- before { visit new_finance_order_path(order_id: order.id) }
-
it 'has product ordered visible' do
expect(page).to have_content(article.name)
expect(page).to have_selector("#order_article_#{oa.id}")
@@ -59,7 +58,7 @@ feature 'settling an order', js: true do
click_link I18n.t('ui.delete')
end
end
- expect(page).to_not have_selector("#order_article_#{oa.id}")
+ expect(page).not_to have_selector("#order_article_#{oa.id}")
expect(OrderArticle.exists?(oa.id)).to be true
oa.reload
expect(oa.quantity).to eq(4)
@@ -77,7 +76,7 @@ feature 'settling an order', js: true do
click_link I18n.t('ui.delete')
end
end
- expect(page).to_not have_selector("#order_article_#{oa.id}")
+ expect(page).not_to have_selector("#order_article_#{oa.id}")
expect(OrderArticle.exists?(oa.id)).to be false
end
@@ -87,7 +86,7 @@ feature 'settling an order', js: true do
within("#group_order_article_#{goa1.id}") do
click_link I18n.t('ui.delete')
end
- expect(page).to_not have_selector("#group_order_article_#{goa1.id}")
+ expect(page).not_to have_selector("#group_order_article_#{goa1.id}")
expect(OrderArticle.exists?(oa.id)).to be true
expect(GroupOrderArticle.exists?(goa1.id)).to be true
goa1.reload
@@ -103,7 +102,7 @@ feature 'settling an order', js: true do
within("#group_order_article_#{goa1.id}") do
click_link I18n.t('ui.delete')
end
- expect(page).to_not have_selector("#group_order_article_#{goa1.id}")
+ expect(page).not_to have_selector("#group_order_article_#{goa1.id}")
expect(OrderArticle.exists?(oa.id)).to be true
expect(GroupOrderArticle.exists?(goa1.id)).to be false
end
@@ -134,15 +133,15 @@ feature 'settling an order', js: true do
end
expect(page).to have_selector('form#new_group_order_article')
within('#new_group_order_article') do
- select user.ordergroup.name, :from => 'group_order_article_ordergroup_id'
+ select user.ordergroup.name, from: 'group_order_article_ordergroup_id'
find_by_id('group_order_article_result').set(8)
sleep 0.25
find('input[type="submit"]').click
end
- expect(page).to_not have_selector('form#new_group_order_article')
+ expect(page).not_to have_selector('form#new_group_order_article')
expect(page).to have_content(user.ordergroup.name)
goa = GroupOrderArticle.last
- expect(goa).to_not be_nil
+ expect(goa).not_to be_nil
expect(goa.result).to eq 8
expect(page).to have_selector("#group_order_article_#{goa.id}")
expect(find("#r_#{goa.id}").value.to_f).to eq 8
@@ -169,8 +168,8 @@ feature 'settling an order', js: true do
end
it 'can add an article' do
- new_article = create :article, supplier: supplier
- expect(page).to_not have_content(new_article.name)
+ new_article = create(:article, supplier: supplier)
+ expect(page).not_to have_content(new_article.name)
click_link I18n.t('finance.balancing.edit_results_by_articles.add_article')
expect(page).to have_selector('form#new_order_article')
within('#new_order_article') do
@@ -178,8 +177,8 @@ feature 'settling an order', js: true do
sleep 0.25
find('input[type="submit"]').click
end
- expect(page).to_not have_selector('form#new_order_article')
+ expect(page).not_to have_selector('form#new_order_article')
expect(page).to have_content(new_article.name)
- expect(order.order_articles.where(article_id: new_article.id)).to_not be_nil
+ expect(order.order_articles.where(article_id: new_article.id)).not_to be_nil
end
end
diff --git a/spec/integration/config_spec.rb b/spec/integration/config_spec.rb
index 91f376dd..4f67802a 100644
--- a/spec/integration/config_spec.rb
+++ b/spec/integration/config_spec.rb
@@ -3,7 +3,7 @@ require_relative '../spec_helper'
feature 'admin/configs' do
let(:name) { Faker::Lorem.words(number: rand(2..4)).join(' ') }
let(:email) { Faker::Internet.email }
- let(:admin) { create :admin }
+ let(:admin) { create(:admin) }
before { login admin }
@@ -51,13 +51,13 @@ feature 'admin/configs' do
end
def compact_hash_deep!(h)
- h.each do |k, v|
+ h.each do |_k, v|
if v.is_a? Hash
compact_hash_deep!(v)
- v.reject! { |k, v| v.blank? }
+ v.compact_blank!
end
end
- h.reject! { |k, v| v.blank? }
+ h.compact_blank!
h
end
end
diff --git a/spec/integration/home_spec.rb b/spec/integration/home_spec.rb
index 313b9afe..87390bd9 100644
--- a/spec/integration/home_spec.rb
+++ b/spec/integration/home_spec.rb
@@ -1,7 +1,7 @@
require_relative '../spec_helper'
feature 'my profile page' do
- let(:user) { create :user }
+ let(:user) { create(:user) }
before { login user }
diff --git a/spec/integration/login_spec.rb b/spec/integration/login_spec.rb
index 49af6852..747d170f 100644
--- a/spec/integration/login_spec.rb
+++ b/spec/integration/login_spec.rb
@@ -1,7 +1,7 @@
require_relative '../spec_helper'
feature LoginController do
- let(:user) { create :user }
+ let(:user) { create(:user) }
describe 'forgot password' do
before { visit forgot_password_path }
@@ -36,7 +36,7 @@ feature LoginController do
it 'is not accessible' do
expect(page).to have_selector '.alert-error'
- expect(page).to_not have_selector 'input[type=password]'
+ expect(page).not_to have_selector 'input[type=password]'
end
end
diff --git a/spec/integration/order_spec.rb b/spec/integration/order_spec.rb
index dd768997..37b9e60a 100644
--- a/spec/integration/order_spec.rb
+++ b/spec/integration/order_spec.rb
@@ -1,12 +1,12 @@
require_relative '../spec_helper'
feature Order, js: true do
- let(:admin) { create :user, groups: [create(:workgroup, role_orders: true)] }
- let(:article) { create :article, unit_quantity: 1 }
- let(:order) { create :order, supplier: article.supplier, article_ids: [article.id] } # need to ref article
- let(:go1) { create :group_order, order: order }
+ let(:admin) { create(:user, groups: [create(:workgroup, role_orders: true)]) }
+ let(:article) { create(:article, unit_quantity: 1) }
+ let(:order) { create(:order, supplier: article.supplier, article_ids: [article.id]) } # need to ref article
+ let(:go1) { create(:group_order, order: order) }
let(:oa) { order.order_articles.find_by_article_id(article.id) }
- let(:goa1) { create :group_order_article, group_order: go1, order_article: oa }
+ let(:goa1) { create(:group_order_article, group_order: go1, order_article: oa) }
before { login admin }
diff --git a/spec/integration/product_distribution_example_spec.rb b/spec/integration/product_distribution_example_spec.rb
index e15642f1..2c1af327 100644
--- a/spec/integration/product_distribution_example_spec.rb
+++ b/spec/integration/product_distribution_example_spec.rb
@@ -1,12 +1,12 @@
require_relative '../spec_helper'
feature 'product distribution', js: true do
- let(:ftt) { create :financial_transaction_type }
- let(:admin) { create :admin }
- let(:user_a) { create :user, groups: [create(:ordergroup)] }
- let(:user_b) { create :user, groups: [create(:ordergroup)] }
- let(:supplier) { create :supplier }
- let(:article) { create :article, supplier: supplier, unit_quantity: 5 }
+ let(:ftt) { create(:financial_transaction_type) }
+ let(:admin) { create(:admin) }
+ let(:user_a) { create(:user, groups: [create(:ordergroup)]) }
+ let(:user_b) { create(:user, groups: [create(:ordergroup)]) }
+ let(:supplier) { create(:supplier) }
+ let(:article) { create(:article, supplier: supplier, unit_quantity: 5) }
let(:order) { create(:order, supplier: supplier, article_ids: [article.id]) }
let(:oa) { order.order_articles.first }
@@ -50,10 +50,10 @@ feature 'product distribution', js: true do
expect(oa.quantity).to eq(6)
expect(oa.tolerance).to eq(1)
# Gruppe a bekommt 3 einheiten.
- goa_a = oa.group_order_articles.joins(:group_order).where(:group_orders => { :ordergroup_id => user_a.ordergroup.id }).first
+ goa_a = oa.group_order_articles.joins(:group_order).where(group_orders: { ordergroup_id: user_a.ordergroup.id }).first
expect(goa_a.result).to eq(3)
# gruppe b bekommt 2 einheiten.
- goa_b = oa.group_order_articles.joins(:group_order).where(:group_orders => { :ordergroup_id => user_b.ordergroup.id }).first
+ goa_b = oa.group_order_articles.joins(:group_order).where(group_orders: { ordergroup_id: user_b.ordergroup.id }).first
expect(goa_b.result).to eq(2)
end
end
diff --git a/spec/integration/receive_spec.rb b/spec/integration/receive_spec.rb
index 3b65107e..6bf021e8 100644
--- a/spec/integration/receive_spec.rb
+++ b/spec/integration/receive_spec.rb
@@ -1,15 +1,15 @@
require_relative '../spec_helper'
feature 'receiving an order', js: true do
- let(:admin) { create :user, groups: [create(:workgroup, role_orders: true)] }
- let(:supplier) { create :supplier }
- let(:article) { create :article, supplier: supplier, unit_quantity: 3 }
- let(:order) { create :order, supplier: supplier, article_ids: [article.id] } # need to ref article
- let(:go1) { create :group_order, order: order }
- let(:go2) { create :group_order, order: order }
+ let(:admin) { create(:user, groups: [create(:workgroup, role_orders: true)]) }
+ let(:supplier) { create(:supplier) }
+ let(:article) { create(:article, supplier: supplier, unit_quantity: 3) }
+ let(:order) { create(:order, supplier: supplier, article_ids: [article.id]) } # need to ref article
+ let(:go1) { create(:group_order, order: order) }
+ let(:go2) { create(:group_order, order: order) }
let(:oa) { order.order_articles.find_by_article_id(article.id) }
- let(:goa1) { create :group_order_article, group_order: go1, order_article: oa }
- let(:goa2) { create :group_order_article, group_order: go2, order_article: oa }
+ let(:goa1) { create(:group_order_article, group_order: go1, order_article: oa) }
+ let(:goa2) { create(:group_order_article, group_order: go2, order_article: oa) }
# set quantities of group_order_articles
def set_quantities(q1, q2)
@@ -46,7 +46,7 @@ feature 'receiving an order', js: true do
it 'has product not ordered invisible' do
set_quantities [0, 0], [0, 0]
visit receive_order_path(id: order.id)
- expect(page).to_not have_selector("#order_article_#{oa.id}")
+ expect(page).not_to have_selector("#order_article_#{oa.id}")
end
it 'is not received by default' do
@@ -58,7 +58,7 @@ feature 'receiving an order', js: true do
it 'does not change anything when received is ordered' do
set_quantities [2, 0], [3, 2]
visit receive_order_path(id: order.id)
- fill_in "order_articles_#{oa.id}_units_received", :with => oa.units_to_order
+ fill_in "order_articles_#{oa.id}_units_received", with: oa.units_to_order
find('input[type="submit"]').click
expect(page).to have_selector('body')
check_quantities 2, 2, 4
@@ -67,7 +67,7 @@ feature 'receiving an order', js: true do
it 'redistributes properly when received is more' do
set_quantities [2, 0], [3, 2]
visit receive_order_path(id: order.id)
- fill_in "order_articles_#{oa.id}_units_received", :with => 3
+ fill_in "order_articles_#{oa.id}_units_received", with: 3
find('input[type="submit"]').click
expect(page).to have_selector('body')
check_quantities 3, 2, 5
@@ -76,7 +76,7 @@ feature 'receiving an order', js: true do
it 'redistributes properly when received is less' do
set_quantities [2, 0], [3, 2]
visit receive_order_path(id: order.id)
- fill_in "order_articles_#{oa.id}_units_received", :with => 1
+ fill_in "order_articles_#{oa.id}_units_received", with: 1
find('input[type="submit"]').click
expect(page).to have_selector('body')
check_quantities 1, 2, 1
diff --git a/spec/integration/session_spec.rb b/spec/integration/session_spec.rb
index 2571ccab..e264efcb 100644
--- a/spec/integration/session_spec.rb
+++ b/spec/integration/session_spec.rb
@@ -1,7 +1,7 @@
require_relative '../spec_helper'
feature 'the session' do
- let(:user) { create :user }
+ let(:user) { create(:user) }
describe 'login page' do
it 'is accessible' do
@@ -11,7 +11,7 @@ feature 'the session' do
it 'logs me in' do
login user
- expect(page).to_not have_selector('.alert-error')
+ expect(page).not_to have_selector('.alert-error')
end
it 'does not log me in with wrong password' do
@@ -21,10 +21,10 @@ feature 'the session' do
it 'can log me in using an email address' do
visit login_path
- fill_in 'nick', :with => user.email
- fill_in 'password', :with => user.password
+ fill_in 'nick', with: user.email
+ fill_in 'password', with: user.password
find('input[type=submit]').click
- expect(page).to_not have_selector('.alert-error')
+ expect(page).not_to have_selector('.alert-error')
end
end
end
diff --git a/spec/integration/supplier_spec.rb b/spec/integration/supplier_spec.rb
index 178892b8..5683d8da 100644
--- a/spec/integration/supplier_spec.rb
+++ b/spec/integration/supplier_spec.rb
@@ -1,20 +1,20 @@
require_relative '../spec_helper'
feature 'supplier' do
- let(:supplier) { create :supplier }
- let(:user) { create :user, :role_suppliers }
+ let(:supplier) { create(:supplier) }
+ let(:user) { create(:user, :role_suppliers) }
before { login user }
describe 'create new' do
it 'can be created' do
- create :supplier_category
+ create(:supplier_category)
visit new_supplier_path
- supplier = build :supplier
+ supplier = build(:supplier)
within('#new_supplier') do
- fill_in 'supplier_name', :with => supplier.name
- fill_in 'supplier_address', :with => supplier.address
- fill_in 'supplier_phone', :with => supplier.phone
+ fill_in 'supplier_name', with: supplier.name
+ fill_in 'supplier_address', with: supplier.address
+ fill_in 'supplier_phone', with: supplier.phone
find('input[type="submit"]').click
end
expect(page).to have_content(supplier.name)
@@ -38,7 +38,7 @@ feature 'supplier' do
end
it 'can be updated' do
- new_supplier = build :supplier
+ new_supplier = build(:supplier)
supplier
visit edit_supplier_path(id: supplier.id)
fill_in 'supplier_name', with: new_supplier.name
diff --git a/spec/lib/bank_account_information_importer_spec.rb b/spec/lib/bank_account_information_importer_spec.rb
index 40c3b1ea..cbe48fe2 100644
--- a/spec/lib/bank_account_information_importer_spec.rb
+++ b/spec/lib/bank_account_information_importer_spec.rb
@@ -1,7 +1,7 @@
require_relative '../spec_helper'
describe BankTransaction do
- let(:bank_account) { create :bank_account }
+ let(:bank_account) { create(:bank_account) }
it 'empty content' do
content = ''
@@ -188,7 +188,7 @@ describe BankTransaction do
expect(bt.date).to eq('2019-02-13'.to_date)
expect(bt.text).to eq('Deutsche Bundesbahn')
expect(bt.iban).to eq('DE72957284895783674747')
- expect(bt.reference).to eq("743574386368 Muenchen-Hamburg 27.03.2019")
+ expect(bt.reference).to eq('743574386368 Muenchen-Hamburg 27.03.2019')
expect(bt.receipt).to eq('Lastschrift')
end
@@ -277,7 +277,7 @@ describe BankTransaction do
expect(bt.date).to eq('2019-02-14'.to_date)
expect(bt.text).to eq('superbank AG')
expect(bt.iban).to be_nil
- expect(bt.reference).to eq("Überweisung US, Wechselspesen u Provision")
+ expect(bt.reference).to eq('Überweisung US, Wechselspesen u Provision')
expect(bt.receipt).to eq('Spesen/Gebühren')
end
@@ -384,7 +384,7 @@ describe BankTransaction do
expect(bank_account.last_transaction_date).to eq('2020-01-01'.to_date)
expect(bank_account.balance).to eq(22)
- bt1 = bank_account.bank_transactions.find_by_external_id("T1")
+ bt1 = bank_account.bank_transactions.find_by_external_id('T1')
expect(bt1.amount).to eq(11)
expect(bt1.date).to eq('2020-01-01'.to_date)
expect(bt1.text).to eq('DN1')
@@ -392,7 +392,7 @@ describe BankTransaction do
expect(bt1.reference).to eq('')
expect(bt1.receipt).to eq('AI1')
- bt2 = bank_account.bank_transactions.find_by_external_id("T2")
+ bt2 = bank_account.bank_transactions.find_by_external_id('T2')
expect(bt2.amount).to eq(-22)
expect(bt2.date).to eq('2010-02-01'.to_date)
expect(bt2.text).to eq('CN2')
@@ -400,7 +400,7 @@ describe BankTransaction do
expect(bt2.reference).to eq('RI2')
expect(bt2.receipt).to be_nil
- bt3 = bank_account.bank_transactions.find_by_external_id("T3")
+ bt3 = bank_account.bank_transactions.find_by_external_id('T3')
expect(bt3.amount).to eq(33)
expect(bt3.date).to eq('2000-03-01'.to_date)
expect(bt3.text).to eq('DN3')
diff --git a/spec/lib/bank_transaction_reference_spec.rb b/spec/lib/bank_transaction_reference_spec.rb
index a03e901b..de999906 100644
--- a/spec/lib/bank_transaction_reference_spec.rb
+++ b/spec/lib/bank_transaction_reference_spec.rb
@@ -34,62 +34,65 @@ describe BankTransactionReference do
end
it 'returns correct value for FS1A1' do
- expect(BankTransactionReference.parse('FS1A1')).to match({ group: 1, parts: { "A" => 1 } })
+ expect(BankTransactionReference.parse('FS1A1')).to match({ group: 1, parts: { 'A' => 1 } })
end
it 'returns correct value for FS1.2A3' do
- expect(BankTransactionReference.parse('FS1.2A3')).to match({ group: 1, user: 2, parts: { "A" => 3 } })
+ expect(BankTransactionReference.parse('FS1.2A3')).to match({ group: 1, user: 2, parts: { 'A' => 3 } })
end
it 'returns correct value for FS1A2B3C4' do
- expect(BankTransactionReference.parse('FS1A2B3C4')).to match({ group: 1, parts: { "A" => 2, "B" => 3, "C" => 4 } })
+ expect(BankTransactionReference.parse('FS1A2B3C4')).to match({ group: 1, parts: { 'A' => 2, 'B' => 3, 'C' => 4 } })
end
it 'returns correct value for FS1A2B3A4' do
- expect(BankTransactionReference.parse('FS1A2B3A4')).to match({ group: 1, parts: { "A" => 6, "B" => 3 } })
+ expect(BankTransactionReference.parse('FS1A2B3A4')).to match({ group: 1, parts: { 'A' => 6, 'B' => 3 } })
end
it 'returns correct value for FS1A2.34B5.67C8.90' do
- expect(BankTransactionReference.parse('FS1A2.34B5.67C8.90')).to match({ group: 1, parts: { "A" => 2.34, "B" => 5.67, "C" => 8.90 } })
+ expect(BankTransactionReference.parse('FS1A2.34B5.67C8.90')).to match({ group: 1,
+ parts: { 'A' => 2.34, 'B' => 5.67,
+ 'C' => 8.90 } })
end
it 'returns correct value for FS123A456 with comma-separated prefix' do
- expect(BankTransactionReference.parse('x,FS123A456')).to match({ group: 123, parts: { "A" => 456 } })
+ expect(BankTransactionReference.parse('x,FS123A456')).to match({ group: 123, parts: { 'A' => 456 } })
end
it 'returns correct value for FS123A456 with minus-separated prefix' do
- expect(BankTransactionReference.parse('x-FS123A456')).to match({ group: 123, parts: { "A" => 456 } })
+ expect(BankTransactionReference.parse('x-FS123A456')).to match({ group: 123, parts: { 'A' => 456 } })
end
it 'returns correct value for FS123A456 with semicolon-separated prefix' do
- expect(BankTransactionReference.parse('x;FS123A456')).to match({ group: 123, parts: { "A" => 456 } })
+ expect(BankTransactionReference.parse('x;FS123A456')).to match({ group: 123, parts: { 'A' => 456 } })
end
it 'returns correct value for FS123A456 with space-separated prefix' do
- expect(BankTransactionReference.parse('x FS123A456')).to match({ group: 123, parts: { "A" => 456 } })
+ expect(BankTransactionReference.parse('x FS123A456')).to match({ group: 123, parts: { 'A' => 456 } })
end
it 'returns correct value for FS234A567 with comma-separated suffix' do
- expect(BankTransactionReference.parse('FS234A567,x')).to match({ group: 234, parts: { "A" => 567 } })
+ expect(BankTransactionReference.parse('FS234A567,x')).to match({ group: 234, parts: { 'A' => 567 } })
end
it 'returns correct value for FS234A567 with minus-separated suffix' do
- expect(BankTransactionReference.parse('FS234A567-x')).to match({ group: 234, parts: { "A" => 567 } })
+ expect(BankTransactionReference.parse('FS234A567-x')).to match({ group: 234, parts: { 'A' => 567 } })
end
it 'returns correct value for FS234A567 with space-separated suffix' do
- expect(BankTransactionReference.parse('FS234A567 x')).to match({ group: 234, parts: { "A" => 567 } })
+ expect(BankTransactionReference.parse('FS234A567 x')).to match({ group: 234, parts: { 'A' => 567 } })
end
it 'returns correct value for FS234A567 with semicolon-separated suffix' do
- expect(BankTransactionReference.parse('FS234A567;x')).to match({ group: 234, parts: { "A" => 567 } })
+ expect(BankTransactionReference.parse('FS234A567;x')).to match({ group: 234, parts: { 'A' => 567 } })
end
it 'returns correct value for FS234A567 with minus-separated suffix' do
- expect(BankTransactionReference.parse('FS234A567-x')).to match({ group: 234, parts: { "A" => 567 } })
+ expect(BankTransactionReference.parse('FS234A567-x')).to match({ group: 234, parts: { 'A' => 567 } })
end
it 'returns correct value for FS34.56A67.89 with prefix and suffix' do
- expect(BankTransactionReference.parse('prefix FS34.56A67.89, suffix')).to match({ group: 34, user: 56, parts: { "A" => 67.89 } })
+ expect(BankTransactionReference.parse('prefix FS34.56A67.89, suffix')).to match({ group: 34, user: 56,
+ parts: { 'A' => 67.89 } })
end
end
diff --git a/spec/lib/foodsoft_mail_receiver_spec.rb b/spec/lib/foodsoft_mail_receiver_spec.rb
index 59eab47b..47ddb57d 100644
--- a/spec/lib/foodsoft_mail_receiver_spec.rb
+++ b/spec/lib/foodsoft_mail_receiver_spec.rb
@@ -6,55 +6,6 @@ describe FoodsoftMailReceiver do
@server.start
end
- it 'does not accept empty addresses' do
- begin
- FoodsoftMailReceiver.received('', 'body')
- rescue => error
- expect(error.to_s).to include 'missing'
- end
- end
-
- it 'does not accept invalid addresses' do
- begin
- FoodsoftMailReceiver.received('invalid', 'body')
- rescue => error
- expect(error.to_s).to include 'has an invalid format'
- end
- end
-
- it 'does not accept invalid scope in address' do
- begin
- FoodsoftMailReceiver.received('invalid.invalid', 'body')
- rescue => error
- expect(error.to_s).to include 'could not be found'
- end
- end
-
- it 'does not accept address without handler' do
- begin
- address = "#{FoodsoftConfig[:default_scope]}.invalid"
- FoodsoftMailReceiver.received(address, 'body')
- rescue => error
- expect(error.to_s).to include 'invalid format for recipient'
- end
- end
-
- it 'does not accept invalid addresses via SMTP' do
- expect {
- Net::SMTP.start(@server.hosts.first, @server.ports.first) do |smtp|
- smtp.send_message 'body', 'from@example.com', 'invalid'
- end
- }.to raise_error(Net::SMTPFatalError)
- end
-
- it 'does not accept invalid addresses via SMTP' do
- expect {
- Net::SMTP.start(@server.hosts.first, @server.ports.first) do |smtp|
- smtp.send_message 'body', 'from@example.com', 'invalid'
- end
- }.to raise_error(Net::SMTPFatalError)
- end
-
# TODO: Reanable this test.
# It raised "Mysql2::Error: Lock wait timeout exceeded" at time of writing.
# it 'accepts bounce mails via SMTP' do
@@ -74,4 +25,45 @@ describe FoodsoftMailReceiver do
after :all do
@server.shutdown
end
+
+ it 'does not accept empty addresses' do
+ FoodsoftMailReceiver.received('', 'body')
+ rescue StandardError => e
+ expect(e.to_s).to include 'missing'
+ end
+
+ it 'does not accept invalid addresses' do
+ FoodsoftMailReceiver.received('invalid', 'body')
+ rescue StandardError => e
+ expect(e.to_s).to include 'has an invalid format'
+ end
+
+ it 'does not accept invalid scope in address' do
+ FoodsoftMailReceiver.received('invalid.invalid', 'body')
+ rescue StandardError => e
+ expect(e.to_s).to include 'could not be found'
+ end
+
+ it 'does not accept address without handler' do
+ address = "#{FoodsoftConfig[:default_scope]}.invalid"
+ FoodsoftMailReceiver.received(address, 'body')
+ rescue StandardError => e
+ expect(e.to_s).to include 'invalid format for recipient'
+ end
+
+ it 'does not accept invalid addresses via SMTP' do
+ expect do
+ Net::SMTP.start(@server.hosts.first, @server.ports.first) do |smtp|
+ smtp.send_message 'body', 'from@example.com', 'invalid'
+ end
+ end.to raise_error(Net::SMTPFatalError)
+ end
+
+ it 'does not accept invalid addresses via SMTP' do
+ expect do
+ Net::SMTP.start(@server.hosts.first, @server.ports.first) do |smtp|
+ smtp.send_message 'body', 'from@example.com', 'invalid'
+ end
+ end.to raise_error(Net::SMTPFatalError)
+ end
end
diff --git a/spec/lib/quantity_unit_spec.rb b/spec/lib/quantity_unit_spec.rb
deleted file mode 100644
index bbe3d546..00000000
--- a/spec/lib/quantity_unit_spec.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-require_relative '../spec_helper'
-
-describe QuantityUnit do
- it "parses a string correctly" do
- qu = QuantityUnit.parse("1.5 k g"); expect([qu.quantity, qu.unit]).to eq([1.5, "kg"])
- qu = QuantityUnit.parse(" 1,5 kg"); expect([qu.quantity, qu.unit]).to eq([1.5, "kg"])
- qu = QuantityUnit.parse("1500 g"); expect([qu.quantity, qu.unit]).to eq([1500, "g"])
- qu = QuantityUnit.parse("1.5L "); expect([qu.quantity, qu.unit]).to eq([1.5, "l"])
- qu = QuantityUnit.parse("2400mL"); expect([qu.quantity, qu.unit]).to eq([2400, "ml"])
- end
-
- it "scales prices correctly" do
- qu = QuantityUnit.new(1.5, "kg")
- expect(qu.scale_price_to_base_unit(12.34)).to eq([8.23, "kg"])
- qu = QuantityUnit.new(1500, "g")
- expect(qu.scale_price_to_base_unit(12.34)).to eq([8.23, "kg"])
- qu = QuantityUnit.new(1.5, "l")
- expect(qu.scale_price_to_base_unit(12.34)).to eq([8.23, "L"])
- qu = QuantityUnit.new(2400, "ml")
- expect(qu.scale_price_to_base_unit(12.34)).to eq([5.14, "L"])
- end
-end
\ No newline at end of file
diff --git a/spec/lib/token_verifier_spec.rb b/spec/lib/token_verifier_spec.rb
index d4a7e5ea..3097e888 100644
--- a/spec/lib/token_verifier_spec.rb
+++ b/spec/lib/token_verifier_spec.rb
@@ -6,12 +6,12 @@ describe TokenVerifier do
let(:msg) { v.generate }
it 'validates' do
- expect { v.verify(msg) }.to_not raise_error
+ expect { v.verify(msg) }.not_to raise_error
end
it 'validates when recreated' do
v2 = TokenVerifier.new(prefix)
- expect { v2.verify(msg) }.to_not raise_error
+ expect { v2.verify(msg) }.not_to raise_error
end
it 'does not validate with a different prefix' do
@@ -32,7 +32,9 @@ describe TokenVerifier do
end
it 'does not validate a random string' do
- expect { v.verify(Faker::Lorem.characters(number: 100)) }.to raise_error(ActiveSupport::MessageVerifier::InvalidSignature)
+ expect do
+ v.verify(Faker::Lorem.characters(number: 100))
+ end.to raise_error(ActiveSupport::MessageVerifier::InvalidSignature)
end
it 'returns the message' do
diff --git a/spec/models/article_spec.rb b/spec/models/article_spec.rb
index 519f5b64..3a810827 100644
--- a/spec/models/article_spec.rb
+++ b/spec/models/article_spec.rb
@@ -1,11 +1,11 @@
require_relative '../spec_helper'
describe Article do
- let(:supplier) { create :supplier }
- let(:article) { create :article, supplier: supplier }
+ let(:supplier) { create(:supplier) }
+ let(:article) { create(:article, supplier: supplier) }
it 'has a unique name' do
- article2 = build :article, supplier: supplier, name: article.name
+ article2 = build(:article, supplier: supplier, name: article.name)
expect(article2).to be_invalid
end
@@ -21,21 +21,33 @@ describe Article do
end
it 'returns false when invalid unit' do
- article1 = build :article, supplier: supplier, unit: 'invalid'
+ article1 = build(:article, supplier: supplier, unit: 'invalid')
expect(article.convert_units(article1)).to be false
end
+ it 'returns false if unit = 0' do
+ article1 = build(:article, supplier: supplier, unit: '1kg', price: 2, unit_quantity: 1)
+ article2 = build(:article, supplier: supplier, unit: '0kg', price: 2, unit_quantity: 1)
+ expect(article1.convert_units(article2)).to be false
+ end
+
+ it 'returns false if unit becomes zero because of , symbol in unit format' do
+ article1 = build(:article, supplier: supplier, unit: '0,8kg', price: 2, unit_quantity: 1)
+ article2 = build(:article, supplier: supplier, unit: '0,9kg', price: 2, unit_quantity: 1)
+ expect(article1.convert_units(article2)).to be false
+ end
+
it 'converts from ST to KI (german foodcoops legacy)' do
- article1 = build :article, supplier: supplier, unit: 'ST'
- article2 = build :article, supplier: supplier, name: 'banana 10-12 St', price: 12.34, unit: 'KI'
+ article1 = build(:article, supplier: supplier, unit: 'ST')
+ article2 = build(:article, supplier: supplier, name: 'banana 10-12 St', price: 12.34, unit: 'KI')
new_price, new_unit_quantity = article1.convert_units(article2)
expect(new_unit_quantity).to eq 10
expect(new_price).to eq 1.23
end
it 'converts from g to kg' do
- article1 = build :article, supplier: supplier, unit: 'kg'
- article2 = build :article, supplier: supplier, unit: 'g', price: 0.12, unit_quantity: 1500
+ article1 = build(:article, supplier: supplier, unit: 'kg')
+ article2 = build(:article, supplier: supplier, unit: 'g', price: 0.12, unit_quantity: 1500)
new_price, new_unit_quantity = article1.convert_units(article2)
expect(new_unit_quantity).to eq 1.5
expect(new_price).to eq 120
@@ -43,7 +55,7 @@ describe Article do
end
it 'computes changed article attributes' do
- article2 = build :article, supplier: supplier, name: 'banana'
+ article2 = build(:article, supplier: supplier, name: 'banana')
expect(article.unequal_attributes(article2)[:name]).to eq 'banana'
end
@@ -59,10 +71,16 @@ describe Article do
expect(article.gross_price).to be >= article.price
end
- it 'computes the fc price correctly' do
- expect(article.fc_price).to eq((article.gross_price * 1.05).round(2))
+ [[nil, 1],
+ [0, 1],
+ [5, 1.05],
+ [42, 1.42],
+ [100, 2]].each do |price_markup, percent|
+ it "computes the fc price with price_markup #{price_markup} correctly" do
+ FoodsoftConfig.config['price_markup'] = price_markup
+ expect(article.fc_price).to eq((article.gross_price * percent).round(2))
+ end
end
-
it 'knows when it is deleted' do
expect(supplier.deleted?).to be false
supplier.mark_as_deleted
@@ -83,7 +101,7 @@ describe Article do
end
it 'is knows its open order' do
- order = create :order, supplier: supplier, article_ids: [article.id]
+ order = create(:order, supplier: supplier, article_ids: [article.id])
expect(article.in_open_order).to eq(order)
end
@@ -91,26 +109,26 @@ describe Article do
expect(article.shared_article).to be_nil
end
- describe 'connected to a shared database', :type => :feature do
- let(:shared_article) { create :shared_article }
- let(:supplier) { create :supplier, shared_supplier_id: shared_article.supplier_id }
- let(:article) { create :article, supplier: supplier, order_number: shared_article.order_number }
+ describe 'connected to a shared database', type: :feature do
+ let(:shared_article) { create(:shared_article) }
+ let(:supplier) { create(:supplier, shared_supplier_id: shared_article.supplier_id) }
+ let(:article) { create(:article, supplier: supplier, order_number: shared_article.order_number) }
it 'can be found in the shared database' do
- expect(article.shared_article).to_not be_nil
+ expect(article.shared_article).not_to be_nil
end
it 'can find updates' do
changed = article.shared_article_changed?
- expect(changed).to_not be_falsey
+ expect(changed).not_to be_falsey
expect(changed.length).to be > 1
end
it 'can be synchronised' do
- # TODO move article sync from supplier to article
+ # TODO: move article sync from supplier to article
article # need to reference for it to exist when syncing
updated_article = supplier.sync_all[0].select { |s| s[0].id == article.id }.first[0]
- article.update(updated_article.attributes.reject { |k, v| k == 'id' or k == 'type' })
+ article.update(updated_article.attributes.reject { |k, _v| %w[id type].include?(k) })
expect(article.name).to eq(shared_article.name)
# now synchronising shouldn't change anything anymore
expect(article.shared_article_changed?).to be_falsey
@@ -131,9 +149,9 @@ describe Article do
article.unit = '200g'
article.shared_updated_on -= 1 # to make update do something
article.save!
- # TODO get sync functionality in article
+ # TODO: get sync functionality in article
updated_article = supplier.sync_all[0].select { |s| s[0].id == article.id }.first[0]
- article.update!(updated_article.attributes.reject { |k, v| k == 'id' or k == 'type' })
+ article.update!(updated_article.attributes.reject { |k, _v| %w[id type].include?(k) })
expect(article.unit).to eq '200g'
expect(article.unit_quantity).to eq 5
expect(article.price).to be_within(0.005).of(shared_article.price / 5)
diff --git a/spec/models/bank_transaction_spec.rb b/spec/models/bank_transaction_spec.rb
index 21d6185e..14172676 100644
--- a/spec/models/bank_transaction_spec.rb
+++ b/spec/models/bank_transaction_spec.rb
@@ -1,24 +1,32 @@
require_relative '../spec_helper'
describe BankTransaction do
- let(:bank_account) { create :bank_account }
- let(:ordergroup) { create :ordergroup }
- let(:supplier) { create :supplier, iban: Faker::Bank.iban }
- let!(:user) { create :user, groups: [ordergroup] }
- let!(:ftt_a) { create :financial_transaction_type, name_short: 'A' }
- let!(:ftt_b) { create :financial_transaction_type, name_short: 'B' }
+ let(:bank_account) { create(:bank_account) }
+ let(:ordergroup) { create(:ordergroup) }
+ let(:supplier) { create(:supplier, iban: Faker::Bank.iban) }
+ let!(:user) { create(:user, groups: [ordergroup]) }
+ let!(:ftt_a) { create(:financial_transaction_type, name_short: 'A') }
+ let!(:ftt_b) { create(:financial_transaction_type, name_short: 'B') }
describe 'supplier' do
- let!(:invoice1) { create :invoice, supplier: supplier, number: '11', amount: 10 }
- let!(:invoice2) { create :invoice, supplier: supplier, number: '22', amount: 20 }
- let!(:invoice3) { create :invoice, supplier: supplier, number: '33', amount: 30 }
- let!(:invoice4) { create :invoice, supplier: supplier, number: '44', amount: 40 }
- let!(:invoice5) { create :invoice, supplier: supplier, number: '55', amount: 50 }
+ let!(:invoice1) { create(:invoice, supplier: supplier, number: '11', amount: 10) }
+ let!(:invoice2) { create(:invoice, supplier: supplier, number: '22', amount: 20) }
+ let!(:invoice3) { create(:invoice, supplier: supplier, number: '33', amount: 30) }
+ let!(:invoice4) { create(:invoice, supplier: supplier, number: '44', amount: 40) }
+ let!(:invoice5) { create(:invoice, supplier: supplier, number: '55', amount: 50) }
- let!(:bank_transaction1) { create :bank_transaction, bank_account: bank_account, iban: supplier.iban, reference: '11', amount: 10 }
- let!(:bank_transaction2) { create :bank_transaction, bank_account: bank_account, iban: supplier.iban, reference: '22', amount: -20 }
- let!(:bank_transaction3) { create :bank_transaction, bank_account: bank_account, iban: supplier.iban, reference: '33,44', amount: -70 }
- let!(:bank_transaction4) { create :bank_transaction, bank_account: bank_account, iban: supplier.iban, text: '55', amount: -50 }
+ let!(:bank_transaction1) do
+ create(:bank_transaction, bank_account: bank_account, iban: supplier.iban, reference: '11', amount: 10)
+ end
+ let!(:bank_transaction2) do
+ create(:bank_transaction, bank_account: bank_account, iban: supplier.iban, reference: '22', amount: -20)
+ end
+ let!(:bank_transaction3) do
+ create(:bank_transaction, bank_account: bank_account, iban: supplier.iban, reference: '33,44', amount: -70)
+ end
+ let!(:bank_transaction4) do
+ create(:bank_transaction, bank_account: bank_account, iban: supplier.iban, text: '55', amount: -50)
+ end
it 'ignores invoices with invalid amount' do
expect(bank_transaction1.assign_to_invoice).to be false
@@ -49,14 +57,26 @@ describe BankTransaction do
end
describe 'ordergroup' do
- let!(:bank_transaction1) { create :bank_transaction, bank_account: bank_account, reference: "invalid", amount: 10 }
- let!(:bank_transaction2) { create :bank_transaction, bank_account: bank_account, reference: "FS99A10", amount: 10 }
- let!(:bank_transaction3) { create :bank_transaction, bank_account: bank_account, reference: "FS#{ordergroup.id}.99A10", amount: 10 }
- let!(:bank_transaction4) { create :bank_transaction, bank_account: bank_account, reference: "FS#{ordergroup.id}A10", amount: 99 }
- let!(:bank_transaction5) { create :bank_transaction, bank_account: bank_account, reference: "FS#{ordergroup.id}A10", amount: 10 }
- let!(:bank_transaction6) { create :bank_transaction, bank_account: bank_account, reference: "FS#{ordergroup.id}A10B20", amount: 30 }
- let!(:bank_transaction7) { create :bank_transaction, bank_account: bank_account, reference: "FS#{ordergroup.id}.#{user.id}A10", amount: 10 }
- let!(:bank_transaction8) { create :bank_transaction, bank_account: bank_account, reference: "FS#{ordergroup.id}X10", amount: 10 }
+ let!(:bank_transaction1) { create(:bank_transaction, bank_account: bank_account, reference: 'invalid', amount: 10) }
+ let!(:bank_transaction2) { create(:bank_transaction, bank_account: bank_account, reference: 'FS99A10', amount: 10) }
+ let!(:bank_transaction3) do
+ create(:bank_transaction, bank_account: bank_account, reference: "FS#{ordergroup.id}.99A10", amount: 10)
+ end
+ let!(:bank_transaction4) do
+ create(:bank_transaction, bank_account: bank_account, reference: "FS#{ordergroup.id}A10", amount: 99)
+ end
+ let!(:bank_transaction5) do
+ create(:bank_transaction, bank_account: bank_account, reference: "FS#{ordergroup.id}A10", amount: 10)
+ end
+ let!(:bank_transaction6) do
+ create(:bank_transaction, bank_account: bank_account, reference: "FS#{ordergroup.id}A10B20", amount: 30)
+ end
+ let!(:bank_transaction7) do
+ create(:bank_transaction, bank_account: bank_account, reference: "FS#{ordergroup.id}.#{user.id}A10", amount: 10)
+ end
+ let!(:bank_transaction8) do
+ create(:bank_transaction, bank_account: bank_account, reference: "FS#{ordergroup.id}X10", amount: 10)
+ end
it 'ignores transaction with invalid reference' do
expect(bank_transaction1.assign_to_ordergroup).to be_nil
diff --git a/spec/models/delivery_spec.rb b/spec/models/delivery_spec.rb
index b48449ab..80f4c2ed 100644
--- a/spec/models/delivery_spec.rb
+++ b/spec/models/delivery_spec.rb
@@ -1,8 +1,8 @@
require_relative '../spec_helper'
describe Delivery do
- let(:delivery) { create :delivery }
- let(:stock_article) { create :stock_article, price: 3 }
+ let(:delivery) { create(:delivery) }
+ let(:stock_article) { create(:stock_article, price: 3) }
it 'creates new stock_changes' do
delivery.new_stock_changes = ([
diff --git a/spec/models/group_order_article_spec.rb b/spec/models/group_order_article_spec.rb
index 42178a6c..434f9a29 100644
--- a/spec/models/group_order_article_spec.rb
+++ b/spec/models/group_order_article_spec.rb
@@ -1,10 +1,10 @@
require_relative '../spec_helper'
describe GroupOrderArticle do
- let(:user) { create :user, groups: [create(:ordergroup)] }
+ let(:user) { create(:user, groups: [create(:ordergroup)]) }
let(:order) { create(:order) }
- let(:go) { create :group_order, order: order, ordergroup: user.ordergroup }
- let(:goa) { create :group_order_article, group_order: go, order_article: order.order_articles.first }
+ let(:go) { create(:group_order, order: order, ordergroup: user.ordergroup) }
+ let(:goa) { create(:group_order_article, group_order: go, order_article: order.order_articles.first) }
it 'has zero quantity by default' do expect(goa.quantity).to eq(0) end
it 'has zero tolerance by default' do expect(goa.tolerance).to eq(0) end
@@ -12,9 +12,9 @@ describe GroupOrderArticle do
it 'has zero total price by default' do expect(goa.total_price).to eq(0) end
describe do
- let(:article) { create :article, supplier: order.supplier, unit_quantity: 1 }
- let(:oa) { order.order_articles.create(:article => article) }
- let(:goa) { create :group_order_article, group_order: go, order_article: oa }
+ let(:article) { create(:article, supplier: order.supplier, unit_quantity: 1) }
+ let(:oa) { order.order_articles.create(article: article) }
+ let(:goa) { create(:group_order_article, group_order: go, order_article: oa) }
it 'can be ordered by piece' do
goa.update_quantities(1, 0)
@@ -23,7 +23,8 @@ describe GroupOrderArticle do
end
it 'can be ordered in larger amounts' do
- quantity, tolerance = rand(13..99), rand(0..99)
+ quantity = rand(13..99)
+ tolerance = rand(0..99)
goa.update_quantities(quantity, tolerance)
expect(goa.quantity).to eq(quantity)
expect(goa.tolerance).to eq(tolerance)
@@ -52,10 +53,10 @@ describe GroupOrderArticle do
end
describe 'distribution strategy' do
- let(:article) { create :article, supplier: order.supplier, unit_quantity: 1 }
- let(:oa) { order.order_articles.create(:article => article) }
- let(:goa) { create :group_order_article, group_order: go, order_article: oa }
- let!(:goaq) { create :group_order_article_quantity, group_order_article: goa, quantity: 4, tolerance: 6 }
+ let(:article) { create(:article, supplier: order.supplier, unit_quantity: 1) }
+ let(:oa) { order.order_articles.create(article: article) }
+ let(:goa) { create(:group_order_article, group_order: go, order_article: oa) }
+ let!(:goaq) { create(:group_order_article_quantity, group_order_article: goa, quantity: 4, tolerance: 6) }
it 'can calculate the result for the distribution strategy "first order first serve"' do
res = goa.calculate_result(2)
diff --git a/spec/models/group_order_spec.rb b/spec/models/group_order_spec.rb
index a2b8a2c5..648fa100 100644
--- a/spec/models/group_order_spec.rb
+++ b/spec/models/group_order_spec.rb
@@ -1,8 +1,8 @@
require_relative '../spec_helper'
describe GroupOrder do
- let(:user) { create :user, groups: [create(:ordergroup)] }
- let(:order) { create :order }
+ let(:user) { create(:user, groups: [create(:ordergroup)]) }
+ let(:order) { create(:order) }
# the following two tests are currently disabled - https://github.com/foodcoops/foodsoft/issues/158
@@ -15,7 +15,7 @@ describe GroupOrder do
# end
describe do
- let(:go) { create :group_order, order: order, ordergroup: user.ordergroup }
+ let(:go) { create(:group_order, order: order, ordergroup: user.ordergroup) }
it 'has zero price initially' do
expect(go.price).to eq(0)
diff --git a/spec/models/order_article_spec.rb b/spec/models/order_article_spec.rb
index 829678a9..cef0e09c 100644
--- a/spec/models/order_article_spec.rb
+++ b/spec/models/order_article_spec.rb
@@ -1,14 +1,14 @@
require 'spec_helper'
describe OrderArticle do
- let(:order) { create :order, article_count: 1 }
+ let(:order) { create(:order, article_count: 1) }
let(:oa) { order.order_articles.first }
it 'is not ordered by default' do
expect(OrderArticle.ordered.count).to eq 0
end
- [:units_to_order, :units_billed, :units_received].each do |units|
+ %i[units_to_order units_billed units_received].each do |units|
it "is ordered when there are #{units.to_s.gsub '_', ' '}" do
oa.update_attribute units, rand(1..99)
expect(OrderArticle.ordered.count).to eq 1
@@ -46,15 +46,15 @@ describe OrderArticle do
end
describe 'redistribution' do
- let(:admin) { create :user, groups: [create(:workgroup, role_finance: true)] }
- let(:article) { create :article, unit_quantity: 3 }
- let(:order) { create :order, article_ids: [article.id] }
- let(:go1) { create :group_order, order: order }
- let(:go2) { create :group_order, order: order }
- let(:go3) { create :group_order, order: order }
- let(:goa1) { create :group_order_article, group_order: go1, order_article: oa }
- let(:goa2) { create :group_order_article, group_order: go2, order_article: oa }
- let(:goa3) { create :group_order_article, group_order: go3, order_article: oa }
+ let(:admin) { create(:user, groups: [create(:workgroup, role_finance: true)]) }
+ let(:article) { create(:article, unit_quantity: 3) }
+ let(:order) { create(:order, article_ids: [article.id]) }
+ let(:go1) { create(:group_order, order: order) }
+ let(:go2) { create(:group_order, order: order) }
+ let(:go3) { create(:group_order, order: order) }
+ let(:goa1) { create(:group_order_article, group_order: go1, order_article: oa) }
+ let(:goa2) { create(:group_order_article, group_order: go2, order_article: oa) }
+ let(:goa3) { create(:group_order_article, group_order: go3, order_article: oa) }
# set quantities of group_order_articles
def set_quantities(q1, q2, q3)
@@ -79,21 +79,21 @@ describe OrderArticle do
it 'does nothing when nothing has changed' do
set_quantities [3, 2], [1, 3], [1, 0]
- expect(oa.redistribute 6, [:tolerance, nil]).to eq [1, 0]
+ expect(oa.redistribute(6, [:tolerance, nil])).to eq [1, 0]
goa_reload
expect([goa1, goa2, goa3].map(&:result).map(&:to_i)).to eq [4, 1, 1]
end
it 'works when there is nothing to distribute' do
set_quantities [3, 2], [1, 3], [1, 0]
- expect(oa.redistribute 0, [:tolerance, nil]).to eq [0, 0]
+ expect(oa.redistribute(0, [:tolerance, nil])).to eq [0, 0]
goa_reload
expect([goa1, goa2, goa3].map(&:result)).to eq [0, 0, 0]
end
it 'works when quantity needs to be reduced' do
set_quantities [3, 2], [1, 3], [1, 0]
- expect(oa.redistribute 4, [:tolerance, nil]).to eq [0, 0]
+ expect(oa.redistribute(4, [:tolerance, nil])).to eq [0, 0]
goa_reload
expect([goa1, goa2, goa3].map(&:result)).to eq [3, 1, 0]
end
@@ -101,28 +101,28 @@ describe OrderArticle do
it 'works when quantity is increased within quantity' do
set_quantities [3, 0], [2, 0], [2, 0]
expect([goa1, goa2, goa3].map(&:result)).to eq [3, 2, 1]
- expect(oa.redistribute 7, [:tolerance, nil]).to eq [0, 0]
+ expect(oa.redistribute(7, [:tolerance, nil])).to eq [0, 0]
goa_reload
expect([goa1, goa2, goa3].map(&:result).map(&:to_i)).to eq [3, 2, 2]
end
it 'works when there is just one for the first' do
set_quantities [3, 2], [1, 3], [1, 0]
- expect(oa.redistribute 1, [:tolerance, nil]).to eq [0, 0]
+ expect(oa.redistribute(1, [:tolerance, nil])).to eq [0, 0]
goa_reload
expect([goa1, goa2, goa3].map(&:result)).to eq [1, 0, 0]
end
it 'works when there is tolerance and left-over' do
set_quantities [3, 2], [1, 1], [1, 0]
- expect(oa.redistribute 10, [:tolerance, nil]).to eq [3, 2]
+ expect(oa.redistribute(10, [:tolerance, nil])).to eq [3, 2]
goa_reload
expect([goa1, goa2, goa3].map(&:result)).to eq [5, 2, 1]
end
it 'works when redistributing without tolerance' do
set_quantities [3, 2], [1, 3], [1, 0]
- expect(oa.redistribute 8, [nil]).to eq [3]
+ expect(oa.redistribute(8, [nil])).to eq [3]
goa_reload
expect([goa1, goa2, goa3].map(&:result)).to eq [3, 1, 1]
end
@@ -131,17 +131,18 @@ describe OrderArticle do
describe 'boxfill' do
before { FoodsoftConfig[:use_boxfill] = true }
- let(:article) { create :article, unit_quantity: 6 }
- let(:order) { create :order, article_ids: [article.id], starts: 1.week.ago }
+ let(:article) { create(:article, unit_quantity: 6) }
+ let(:order) { create(:order, article_ids: [article.id], starts: 1.week.ago) }
let(:oa) { order.order_articles.first }
- let(:go) { create :group_order, order: order }
- let(:goa) { create :group_order_article, group_order: go, order_article: oa }
+ let(:go) { create(:group_order, order: order) }
+ let(:goa) { create(:group_order_article, group_order: go, order_article: oa) }
- shared_examples "boxfill" do |success, q|
+ shared_examples 'boxfill' do |success, q|
# initial situation
before do
goa.update_quantities(*q.keys[0])
- oa.update_results!; oa.reload
+ oa.update_results!
+ oa.reload
end
# check starting condition
@@ -172,11 +173,11 @@ describe OrderArticle do
let(:boxfill_from) { 1.hour.from_now }
context 'decreasing the missing units' do
- include_examples "boxfill", true, [6, 0] => [5, 0], [6, 0, 0] => [5, 0, 1]
+ include_examples 'boxfill', true, [6, 0] => [5, 0], [6, 0, 0] => [5, 0, 1]
end
context 'decreasing the tolerance' do
- include_examples "boxfill", true, [1, 2] => [1, 1], [1, 2, 3] => [1, 1, 4]
+ include_examples 'boxfill', true, [1, 2] => [1, 1], [1, 2, 3] => [1, 1, 4]
end
end
@@ -184,27 +185,27 @@ describe OrderArticle do
let(:boxfill_from) { 1.second.ago }
context 'changing nothing in particular' do
- include_examples "boxfill", true, [4, 1] => [4, 1], [4, 1, 1] => [4, 1, 1]
+ include_examples 'boxfill', true, [4, 1] => [4, 1], [4, 1, 1] => [4, 1, 1]
end
context 'increasing missing units' do
- include_examples "boxfill", false, [3, 0] => [2, 0], [3, 0, 3] => [3, 0, 3]
+ include_examples 'boxfill', false, [3, 0] => [2, 0], [3, 0, 3] => [3, 0, 3]
end
context 'increasing tolerance' do
- include_examples "boxfill", true, [2, 1] => [2, 2], [2, 1, 3] => [2, 2, 2]
+ include_examples 'boxfill', true, [2, 1] => [2, 2], [2, 1, 3] => [2, 2, 2]
end
context 'decreasing quantity to fix missing units' do
- include_examples "boxfill", true, [7, 0] => [6, 0], [7, 0, 5] => [6, 0, 0]
+ include_examples 'boxfill', true, [7, 0] => [6, 0], [7, 0, 5] => [6, 0, 0]
end
context 'decreasing quantity keeping missing units equal' do
- include_examples "boxfill", false, [7, 0] => [1, 0], [7, 0, 5] => [7, 0, 5]
+ include_examples 'boxfill', false, [7, 0] => [1, 0], [7, 0, 5] => [7, 0, 5]
end
context 'moving tolerance to quantity' do
- include_examples "boxfill", true, [4, 2] => [6, 0], [4, 2, 0] => [6, 0, 0]
+ include_examples 'boxfill', true, [4, 2] => [6, 0], [4, 2, 0] => [6, 0, 0]
end
# @todo enable test when tolerance doesn't count in missing_units
# context 'decreasing tolerance' do
diff --git a/spec/models/order_spec.rb b/spec/models/order_spec.rb
index aee48f33..71c46a84 100644
--- a/spec/models/order_spec.rb
+++ b/spec/models/order_spec.rb
@@ -1,14 +1,14 @@
require_relative '../spec_helper'
describe Order do
- let!(:ftt) { create :financial_transaction_type }
- let(:user) { create :user, groups: [create(:ordergroup)] }
+ let!(:ftt) { create(:financial_transaction_type) }
+ let(:user) { create(:user, groups: [create(:ordergroup)]) }
it 'automaticly finishes ended' do
- create :order, created_by: user, starts: Date.yesterday, ends: 1.hour.from_now
- create :order, created_by: user, starts: Date.yesterday, ends: 1.hour.ago
- create :order, created_by: user, starts: Date.yesterday, ends: 1.hour.from_now, end_action: :auto_close
- order = create :order, created_by: user, starts: Date.yesterday, ends: 1.hour.ago, end_action: :auto_close
+ create(:order, created_by: user, starts: Date.yesterday, ends: 1.hour.from_now)
+ create(:order, created_by: user, starts: Date.yesterday, ends: 1.hour.ago)
+ create(:order, created_by: user, starts: Date.yesterday, ends: 1.hour.from_now, end_action: :auto_close)
+ order = create(:order, created_by: user, starts: Date.yesterday, ends: 1.hour.ago, end_action: :auto_close)
Order.finish_ended!
order.reload
@@ -19,10 +19,10 @@ describe Order do
end
describe 'state scopes and boolean getters' do
- let!(:open_order) { create :order, state: 'open' }
- let!(:finished_order) { create :order, state: 'finished' }
- let!(:received_order) { create :order, state: 'received' }
- let!(:closed_order) { create :order, state: 'closed' }
+ let!(:open_order) { create(:order, state: 'open') }
+ let!(:finished_order) { create(:order, state: 'finished') }
+ let!(:received_order) { create(:order, state: 'received') }
+ let!(:closed_order) { create(:order, state: 'closed') }
it 'retrieves open orders in the "open" scope' do
expect(Order.open.count).to eq(1)
@@ -72,8 +72,9 @@ describe Order do
end
it 'sends mail if min_order_quantity has been reached' do
- create :user, groups: [create(:ordergroup)]
- create :order, created_by: user, starts: Date.yesterday, ends: 1.hour.ago, end_action: :auto_close_and_send_min_quantity
+ create(:user, groups: [create(:ordergroup)])
+ create(:order, created_by: user, starts: Date.yesterday, ends: 1.hour.ago,
+ end_action: :auto_close_and_send_min_quantity)
Order.finish_ended!
expect(ActionMailer::Base.deliveries.count).to eq 1
@@ -84,7 +85,7 @@ describe Order do
end
it 'needs order articles' do
- supplier = create :supplier, article_count: 0
+ supplier = create(:supplier, article_count: 0)
expect(build(:order, supplier: supplier)).to be_invalid
end
@@ -93,35 +94,35 @@ describe Order do
end
describe 'with articles' do
- let(:order) { create :order }
+ let(:order) { create(:order) }
it 'is open by default' do expect(order).to be_open end
- it 'is not finished by default' do expect(order).to_not be_finished end
- it 'is not closed by default' do expect(order).to_not be_closed end
+ it 'is not finished by default' do expect(order).not_to be_finished end
+ it 'is not closed by default' do expect(order).not_to be_closed end
it 'has valid order articles' do
order.order_articles.each { |oa| expect(oa).to be_valid }
end
it 'can be finished' do
- # TODO randomise user
+ # TODO: randomise user
order.finish!(user)
- expect(order).to_not be_open
+ expect(order).not_to be_open
expect(order).to be_finished
- expect(order).to_not be_closed
+ expect(order).not_to be_closed
end
it 'can be closed' do
- # TODO randomise user
+ # TODO: randomise user
order.finish!(user)
order.close!(user)
- expect(order).to_not be_open
+ expect(order).not_to be_open
expect(order).to be_closed
end
end
describe 'with a default end date' do
- let(:order) { create :order }
+ let(:order) { create(:order) }
before do
FoodsoftConfig[:order_schedule] = { ends: { recurr: 'FREQ=WEEKLY;BYDAY=MO', time: '9:00' } }
@@ -138,10 +139,10 @@ describe Order do
end
describe 'mapped to GroupOrders' do
- let!(:user) { create :user, groups: [create(:ordergroup)] }
- let!(:order) { create :order }
- let!(:order2) { create :order }
- let!(:go) { create :group_order, order: order, ordergroup: user.ordergroup }
+ let!(:user) { create(:user, groups: [create(:ordergroup)]) }
+ let!(:order) { create(:order) }
+ let!(:order2) { create(:order) }
+ let!(:go) { create(:group_order, order: order, ordergroup: user.ordergroup) }
it 'to map a user\'s GroupOrders to a list of Orders' do
orders = Order.ordergroup_group_orders_map(user.ordergroup)
@@ -156,10 +157,10 @@ describe Order do
describe 'balancing charges correct amounts' do
let!(:transport) { rand(0.1..26.0).round(2) }
- let!(:order) { create :order, article_count: 1 }
+ let!(:order) { create(:order, article_count: 1) }
let!(:oa) { order.order_articles.first }
- let!(:go) { create :group_order, order: order, transport: transport }
- let!(:goa) { create :group_order_article, group_order: go, order_article: oa, quantity: 1 }
+ let!(:go) { create(:group_order, order: order, transport: transport) }
+ let!(:goa) { create(:group_order_article, group_order: go, order_article: oa, quantity: 1) }
before do
goa.update_quantities(1, 0)
diff --git a/spec/models/ordergroup_spec.rb b/spec/models/ordergroup_spec.rb
index a7f0c94a..cdac353d 100644
--- a/spec/models/ordergroup_spec.rb
+++ b/spec/models/ordergroup_spec.rb
@@ -1,22 +1,22 @@
require_relative '../spec_helper'
describe Ordergroup do
- let(:ftc1) { create :financial_transaction_class }
- let(:ftc2) { create :financial_transaction_class }
- let(:ftt1) { create :financial_transaction_type, financial_transaction_class: ftc1 }
- let(:ftt2) { create :financial_transaction_type, financial_transaction_class: ftc2 }
- let(:ftt3) { create :financial_transaction_type, financial_transaction_class: ftc2 }
- let(:user) { create :user, groups: [create(:ordergroup)] }
+ let(:ftc1) { create(:financial_transaction_class) }
+ let(:ftc2) { create(:financial_transaction_class) }
+ let(:ftt1) { create(:financial_transaction_type, financial_transaction_class: ftc1) }
+ let(:ftt2) { create(:financial_transaction_type, financial_transaction_class: ftc2) }
+ let(:ftt3) { create(:financial_transaction_type, financial_transaction_class: ftc2) }
+ let(:user) { create(:user, groups: [create(:ordergroup)]) }
it 'shows no active ordergroups when all orders are older than 3 months' do
- order = create :order, starts: 4.months.ago
+ order = create(:order, starts: 4.months.ago)
user.ordergroup.group_orders.create!(order: order)
expect(Ordergroup.active).to be_empty
end
it 'shows active ordergroups when there are recent orders' do
- order = create :order, starts: 2.days.ago
+ order = create(:order, starts: 2.days.ago)
user.ordergroup.group_orders.create!(order: order)
expect(Ordergroup.active).not_to be_empty
@@ -24,17 +24,17 @@ describe Ordergroup do
describe 'sort correctly' do
it 'by name' do
- group_b = create :ordergroup, name: 'bbb'
- group_a = create :ordergroup, name: 'aaa'
- group_c = create :ordergroup, name: 'ccc'
+ group_b = create(:ordergroup, name: 'bbb')
+ group_a = create(:ordergroup, name: 'aaa')
+ group_c = create(:ordergroup, name: 'ccc')
expect(Ordergroup.sort_by_param('name')).to eq([group_a, group_b, group_c])
end
it 'reverse by name' do
- group_b = create :ordergroup, name: 'bbb'
- group_a = create :ordergroup, name: 'aaa'
- group_c = create :ordergroup, name: 'ccc'
+ group_b = create(:ordergroup, name: 'bbb')
+ group_a = create(:ordergroup, name: 'aaa')
+ group_c = create(:ordergroup, name: 'ccc')
expect(Ordergroup.sort_by_param('name_reverse')).to eq([group_c, group_b, group_a])
end
@@ -43,9 +43,9 @@ describe Ordergroup do
users_b = [create(:user)]
users_a = []
users_c = [create(:user), create(:user), create(:user)]
- group_b = create :ordergroup, name: 'bbb', user_ids: users_b.map(&:id)
- group_a = create :ordergroup, name: 'aaa', user_ids: users_a.map(&:id)
- group_c = create :ordergroup, name: 'ccc', user_ids: users_c.map(&:id)
+ group_b = create(:ordergroup, name: 'bbb', user_ids: users_b.map(&:id))
+ group_a = create(:ordergroup, name: 'aaa', user_ids: users_a.map(&:id))
+ group_c = create(:ordergroup, name: 'ccc', user_ids: users_c.map(&:id))
expect(Ordergroup.sort_by_param('members_count')).to eq([group_a, group_b, group_c])
end
@@ -54,39 +54,39 @@ describe Ordergroup do
users_b = [create(:user)]
users_a = []
users_c = [create(:user), create(:user), create(:user)]
- group_b = create :ordergroup, name: 'bbb', user_ids: users_b.map(&:id)
- group_a = create :ordergroup, name: 'aaa', user_ids: users_a.map(&:id)
- group_c = create :ordergroup, name: 'ccc', user_ids: users_c.map(&:id)
+ group_b = create(:ordergroup, name: 'bbb', user_ids: users_b.map(&:id))
+ group_a = create(:ordergroup, name: 'aaa', user_ids: users_a.map(&:id))
+ group_c = create(:ordergroup, name: 'ccc', user_ids: users_c.map(&:id))
expect(Ordergroup.sort_by_param('members_count_reverse')).to eq([group_c, group_b, group_a])
end
it 'by last_user_activity' do
- user_b = create :user, last_activity: 3.days.ago
- user_a = create :user, last_activity: 5.days.ago
- user_c = create :user, last_activity: Time.now
- group_b = create :ordergroup, name: 'bbb', user_ids: [user_b.id]
- group_a = create :ordergroup, name: 'aaa', user_ids: [user_a.id]
- group_c = create :ordergroup, name: 'ccc', user_ids: [user_c.id]
+ user_b = create(:user, last_activity: 3.days.ago)
+ user_a = create(:user, last_activity: 5.days.ago)
+ user_c = create(:user, last_activity: Time.now)
+ group_b = create(:ordergroup, name: 'bbb', user_ids: [user_b.id])
+ group_a = create(:ordergroup, name: 'aaa', user_ids: [user_a.id])
+ group_c = create(:ordergroup, name: 'ccc', user_ids: [user_c.id])
expect(Ordergroup.sort_by_param('last_user_activity')).to eq([group_a, group_b, group_c])
end
it 'reverse by last_user_activity' do
- user_b = create :user, last_activity: 3.days.ago
- user_a = create :user, last_activity: 5.days.ago
- user_c = create :user, last_activity: Time.now
- group_b = create :ordergroup, name: 'bbb', user_ids: [user_b.id]
- group_a = create :ordergroup, name: 'aaa', user_ids: [user_a.id]
- group_c = create :ordergroup, name: 'ccc', user_ids: [user_c.id]
+ user_b = create(:user, last_activity: 3.days.ago)
+ user_a = create(:user, last_activity: 5.days.ago)
+ user_c = create(:user, last_activity: Time.now)
+ group_b = create(:ordergroup, name: 'bbb', user_ids: [user_b.id])
+ group_a = create(:ordergroup, name: 'aaa', user_ids: [user_a.id])
+ group_c = create(:ordergroup, name: 'ccc', user_ids: [user_c.id])
expect(Ordergroup.sort_by_param('last_user_activity_reverse')).to eq([group_c, group_b, group_a])
end
it 'by last_order' do
- group_b = create :ordergroup, name: 'bbb'
- group_a = create :ordergroup, name: 'aaa'
- group_c = create :ordergroup, name: 'ccc'
+ group_b = create(:ordergroup, name: 'bbb')
+ group_a = create(:ordergroup, name: 'aaa')
+ group_c = create(:ordergroup, name: 'ccc')
group_b.group_orders.create! order: create(:order, starts: 6.days.ago)
group_a.group_orders.create! order: create(:order, starts: 4.months.ago)
group_c.group_orders.create! order: create(:order, starts: Time.now)
@@ -95,9 +95,9 @@ describe Ordergroup do
end
it 'reverse by last_order' do
- group_b = create :ordergroup, name: 'bbb'
- group_a = create :ordergroup, name: 'aaa'
- group_c = create :ordergroup, name: 'ccc'
+ group_b = create(:ordergroup, name: 'bbb')
+ group_a = create(:ordergroup, name: 'aaa')
+ group_c = create(:ordergroup, name: 'ccc')
group_b.group_orders.create! order: create(:order, starts: 6.days.ago)
group_a.group_orders.create! order: create(:order, starts: 4.months.ago)
group_c.group_orders.create! order: create(:order, starts: Time.now)
diff --git a/spec/models/supplier_spec.rb b/spec/models/supplier_spec.rb
index 42b4a304..5216b8e9 100644
--- a/spec/models/supplier_spec.rb
+++ b/spec/models/supplier_spec.rb
@@ -1,17 +1,19 @@
require_relative '../spec_helper'
describe Supplier do
- let(:supplier) { create :supplier }
+ let(:supplier) { create(:supplier) }
context 'syncs from file' do
it 'imports and updates articles' do
- article1 = create(:article, supplier: supplier, order_number: 177813, unit: '250 g', price: 0.1)
- article2 = create(:article, supplier: supplier, order_number: 12345)
+ article1 = create(:article, supplier: supplier, order_number: 177_813, unit: '250 g', price: 0.1)
+ article2 = create(:article, supplier: supplier, order_number: 12_345)
supplier.articles = [article1, article2]
options = { filename: 'foodsoft_file_01.csv' }
options[:outlist_absent] = true
options[:convert_units] = true
- updated_article_pairs, outlisted_articles, new_articles = supplier.sync_from_file(Rails.root.join('spec/fixtures/foodsoft_file_01.csv'), "foodsoft", options)
+ updated_article_pairs, outlisted_articles, new_articles = supplier.sync_from_file(
+ Rails.root.join('spec/fixtures/foodsoft_file_01.csv'), options
+ )
expect(new_articles.length).to be > 0
expect(updated_article_pairs.first[1][:name]).to eq 'Tomaten'
expect(outlisted_articles.first).to eq article2
@@ -19,18 +21,16 @@ describe Supplier do
end
it 'return correct tolerance' do
- supplier = create :supplier
- articles = create_list(:article, 1, unit_quantity: 1, supplier_id: supplier.id)
- supplier.reload
+ supplier = create(:supplier)
+ supplier.articles = create_list(:article, 1, unit_quantity: 1)
expect(supplier.has_tolerance?).to be false
- supplier2 = create :supplier
- articles = create_list(:article, 1, unit_quantity: 2, supplier_id: supplier2.id)
- supplier.reload
+ supplier2 = create(:supplier)
+ supplier2.articles = create_list(:article, 1, unit_quantity: 2)
expect(supplier2.has_tolerance?).to be true
end
it 'deletes the supplier and its articles' do
- supplier = create :supplier, article_count: 3
+ supplier = create(:supplier, article_count: 3)
supplier.articles.each { |a| allow(a).to receive(:mark_as_deleted) }
supplier.mark_as_deleted
supplier.articles.each { |a| expect(a).to have_received(:mark_as_deleted) }
@@ -38,29 +38,29 @@ describe Supplier do
end
it 'has a unique name' do
- supplier2 = build :supplier, name: supplier.name
+ supplier2 = build(:supplier, name: supplier.name)
expect(supplier2).to be_invalid
end
it 'has valid articles' do
- supplier = create :supplier, article_count: true
+ supplier = create(:supplier, article_count: true)
supplier.articles.each { |a| expect(a).to be_valid }
end
context 'connected to a shared supplier' do
let(:shared_sync_method) { nil }
- let(:shared_supplier) { create :shared_supplier }
- let(:supplier) { create :supplier, shared_supplier: shared_supplier, shared_sync_method: shared_sync_method }
+ let(:shared_supplier) { create(:shared_supplier) }
+ let(:supplier) { create(:supplier, shared_supplier: shared_supplier, shared_sync_method: shared_sync_method) }
- let!(:synced_shared_article) { create :shared_article, shared_supplier: shared_supplier }
- let!(:updated_shared_article) { create :shared_article, shared_supplier: shared_supplier }
- let!(:new_shared_article) { create :shared_article, shared_supplier: shared_supplier }
+ let!(:synced_shared_article) { create(:shared_article, shared_supplier: shared_supplier) }
+ let!(:updated_shared_article) { create(:shared_article, shared_supplier: shared_supplier) }
+ let!(:new_shared_article) { create(:shared_article, shared_supplier: shared_supplier) }
- let!(:removed_article) { create :article, supplier: supplier, order_number: '10001-ABC' }
+ let!(:removed_article) { create(:article, supplier: supplier, order_number: '10001-ABC') }
let!(:updated_article) do
updated_shared_article.build_new_article(supplier).tap do |article|
article.article_category = create :article_category
- article.origin = "FubarX1"
+ article.origin = 'FubarX1'
article.shared_updated_on = 1.day.ago
article.save!
end
@@ -79,7 +79,7 @@ describe Supplier do
it 'returns the expected articles' do
updated_article_pairs, outlisted_articles, new_articles = supplier.sync_all
- expect(updated_article_pairs).to_not be_empty
+ expect(updated_article_pairs).not_to be_empty
expect(updated_article_pairs[0][0].id).to eq updated_article.id
expect(updated_article_pairs[0][1].keys).to include :origin
@@ -95,13 +95,13 @@ describe Supplier do
it 'returns the expected articles' do
updated_article_pairs, outlisted_articles, new_articles = supplier.sync_all
- expect(updated_article_pairs).to_not be_empty
+ expect(updated_article_pairs).not_to be_empty
expect(updated_article_pairs[0][0].id).to eq updated_article.id
expect(updated_article_pairs[0][1].keys).to include :origin
expect(outlisted_articles).to eq [removed_article]
- expect(new_articles).to_not be_empty
+ expect(new_articles).not_to be_empty
expect(new_articles[0].order_number).to eq new_shared_article.number
expect(new_articles[0].availability?).to be true
end
@@ -113,13 +113,13 @@ describe Supplier do
it 'returns the expected articles' do
updated_article_pairs, outlisted_articles, new_articles = supplier.sync_all
- expect(updated_article_pairs).to_not be_empty
+ expect(updated_article_pairs).not_to be_empty
expect(updated_article_pairs[0][0].id).to eq updated_article.id
expect(updated_article_pairs[0][1].keys).to include :origin
expect(outlisted_articles).to eq [removed_article]
- expect(new_articles).to_not be_empty
+ expect(new_articles).not_to be_empty
expect(new_articles[0].order_number).to eq new_shared_article.number
expect(new_articles[0].availability?).to be false
end
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index 59a797de..def2d1f8 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -2,9 +2,9 @@ require_relative '../spec_helper'
describe User do
it 'is correctly created' do
- user = create :user,
+ user = create(:user,
nick: 'johnnydoe', first_name: 'Johnny', last_name: 'DoeBar',
- email: 'johnnydoe@foodcoop.test', phone: '+1234567890'
+ email: 'johnnydoe@foodcoop.test', phone: '+1234567890')
expect(user.nick).to eq('johnnydoe')
expect(user.first_name).to eq('Johnny')
expect(user.last_name).to eq('DoeBar')
@@ -14,7 +14,7 @@ describe User do
end
describe 'does not have the role' do
- let(:user) { create :user }
+ let(:user) { create(:user) }
it 'admin' do expect(user.role_admin?).to be_falsey end
it 'finance' do expect(user.role_finance?).to be_falsey end
@@ -24,7 +24,7 @@ describe User do
end
describe do
- let(:user) { create :user, password: 'blahblahblah' }
+ let(:user) { create(:user, password: 'blahblahblah') }
it 'can authenticate with correct password' do
expect(User.authenticate(user.nick, 'blahblahblah')).to be_truthy
@@ -74,124 +74,124 @@ describe User do
end
describe 'admin' do
- let(:user) { create :admin }
+ let(:user) { create(:admin) }
it 'default admin role' do expect(user.role_admin?).to be_truthy end
end
describe 'sort correctly' do
it 'by nick' do
- user_b = create :user, nick: 'bbb'
- user_a = create :user, nick: 'aaa'
- user_c = create :user, nick: 'ccc'
+ user_b = create(:user, nick: 'bbb')
+ user_a = create(:user, nick: 'aaa')
+ user_c = create(:user, nick: 'ccc')
expect(User.sort_by_param('nick')).to eq([user_a, user_b, user_c])
end
it 'reverse by nick' do
- user_b = create :user, nick: 'bbb'
- user_a = create :user, nick: 'aaa'
- user_c = create :user, nick: 'ccc'
+ user_b = create(:user, nick: 'bbb')
+ user_a = create(:user, nick: 'aaa')
+ user_c = create(:user, nick: 'ccc')
expect(User.sort_by_param('nick_reverse')).to eq([user_c, user_b, user_a])
end
it 'by name' do
- user_b = create :user, first_name: 'aaa', last_name: 'bbb'
- user_a = create :user, first_name: 'aaa', last_name: 'aaa'
- user_c = create :user, first_name: 'ccc', last_name: 'aaa'
+ user_b = create(:user, first_name: 'aaa', last_name: 'bbb')
+ user_a = create(:user, first_name: 'aaa', last_name: 'aaa')
+ user_c = create(:user, first_name: 'ccc', last_name: 'aaa')
expect(User.sort_by_param('name')).to eq([user_a, user_b, user_c])
end
it 'reverse by name' do
- user_b = create :user, first_name: 'aaa', last_name: 'bbb'
- user_a = create :user, first_name: 'aaa', last_name: 'aaa'
- user_c = create :user, first_name: 'ccc', last_name: 'aaa'
+ user_b = create(:user, first_name: 'aaa', last_name: 'bbb')
+ user_a = create(:user, first_name: 'aaa', last_name: 'aaa')
+ user_c = create(:user, first_name: 'ccc', last_name: 'aaa')
expect(User.sort_by_param('name_reverse')).to eq([user_c, user_b, user_a])
end
it 'by email' do
- user_b = create :user, email: 'bbb@dummy.com'
- user_a = create :user, email: 'aaa@dummy.com'
- user_c = create :user, email: 'ccc@dummy.com'
+ user_b = create(:user, email: 'bbb@dummy.com')
+ user_a = create(:user, email: 'aaa@dummy.com')
+ user_c = create(:user, email: 'ccc@dummy.com')
expect(User.sort_by_param('email')).to eq([user_a, user_b, user_c])
end
it 'reverse by email' do
- user_b = create :user, email: 'bbb@dummy.com'
- user_a = create :user, email: 'aaa@dummy.com'
- user_c = create :user, email: 'ccc@dummy.com'
+ user_b = create(:user, email: 'bbb@dummy.com')
+ user_a = create(:user, email: 'aaa@dummy.com')
+ user_c = create(:user, email: 'ccc@dummy.com')
expect(User.sort_by_param('email_reverse')).to eq([user_c, user_b, user_a])
end
it 'by phone' do
- user_b = create :user, phone: 'bbb'
- user_a = create :user, phone: 'aaa'
- user_c = create :user, phone: 'ccc'
+ user_b = create(:user, phone: 'bbb')
+ user_a = create(:user, phone: 'aaa')
+ user_c = create(:user, phone: 'ccc')
expect(User.sort_by_param('phone')).to eq([user_a, user_b, user_c])
end
it 'reverse by phone' do
- user_b = create :user, phone: 'bbb'
- user_a = create :user, phone: 'aaa'
- user_c = create :user, phone: 'ccc'
+ user_b = create(:user, phone: 'bbb')
+ user_a = create(:user, phone: 'aaa')
+ user_c = create(:user, phone: 'ccc')
expect(User.sort_by_param('phone_reverse')).to eq([user_c, user_b, user_a])
end
it 'by last_activity' do
- user_b = create :user, last_activity: 3.days.ago
- user_a = create :user, last_activity: 5.days.ago
- user_c = create :user, last_activity: Time.now
+ user_b = create(:user, last_activity: 3.days.ago)
+ user_a = create(:user, last_activity: 5.days.ago)
+ user_c = create(:user, last_activity: Time.now)
expect(User.sort_by_param('last_activity')).to eq([user_a, user_b, user_c])
end
it 'reverse by last_activity' do
- user_b = create :user, last_activity: 3.days.ago
- user_a = create :user, last_activity: 5.days.ago
- user_c = create :user, last_activity: Time.now
+ user_b = create(:user, last_activity: 3.days.ago)
+ user_a = create(:user, last_activity: 5.days.ago)
+ user_c = create(:user, last_activity: Time.now)
expect(User.sort_by_param('last_activity_reverse')).to eq([user_c, user_b, user_a])
end
it 'by ordergroup' do
- user_b = create :user, groups: [create(:workgroup, name: 'a'), create(:ordergroup, name: 'bb')]
- user_a = create :user, groups: [create(:workgroup, name: 'b'), create(:ordergroup, name: 'aa')]
- user_c = create :user, groups: [create(:workgroup, name: 'c'), create(:ordergroup, name: 'cc')]
+ user_b = create(:user, groups: [create(:workgroup, name: 'a'), create(:ordergroup, name: 'bb')])
+ user_a = create(:user, groups: [create(:workgroup, name: 'b'), create(:ordergroup, name: 'aa')])
+ user_c = create(:user, groups: [create(:workgroup, name: 'c'), create(:ordergroup, name: 'cc')])
expect(User.sort_by_param('ordergroup')).to eq([user_a, user_b, user_c])
end
it 'reverse by ordergroup' do
- user_b = create :user, groups: [create(:workgroup, name: 'a'), create(:ordergroup, name: 'bb')]
- user_a = create :user, groups: [create(:workgroup, name: 'b'), create(:ordergroup, name: 'aa')]
- user_c = create :user, groups: [create(:workgroup, name: 'c'), create(:ordergroup, name: 'cc')]
+ user_b = create(:user, groups: [create(:workgroup, name: 'a'), create(:ordergroup, name: 'bb')])
+ user_a = create(:user, groups: [create(:workgroup, name: 'b'), create(:ordergroup, name: 'aa')])
+ user_c = create(:user, groups: [create(:workgroup, name: 'c'), create(:ordergroup, name: 'cc')])
expect(User.sort_by_param('ordergroup_reverse')).to eq([user_c, user_b, user_a])
end
it 'and users are only listed once' do
- create :user
+ create(:user)
expect(User.sort_by_param('ordergroup').size).to eq(1)
end
it 'and users belonging to a workgroup are only listed once' do
- create :admin
+ create(:admin)
expect(User.sort_by_param('ordergroup').size).to eq(1)
end
it 'and users belonging to 2 ordergroups are only listed once' do
- user = create :user
- create :ordergroup, user_ids: [user.id]
- create :ordergroup, user_ids: [user.id]
+ user = create(:user)
+ create(:ordergroup, user_ids: [user.id])
+ create(:ordergroup, user_ids: [user.id])
expect(User.sort_by_param('ordergroup').size).to eq(1)
end
diff --git a/spec/requests/api/article_categories_spec.rb b/spec/requests/api/v1/article_categories_controller_spec.rb
similarity index 96%
rename from spec/requests/api/article_categories_spec.rb
rename to spec/requests/api/v1/article_categories_controller_spec.rb
index 4c079ff2..209349a2 100644
--- a/spec/requests/api/article_categories_spec.rb
+++ b/spec/requests/api/v1/article_categories_controller_spec.rb
@@ -1,6 +1,6 @@
require 'swagger_helper'
-describe 'Article Categories', type: :request do
+describe Api::V1::ArticleCategoriesController do
include ApiHelper
path '/article_categories' do
diff --git a/spec/requests/api/configs_spec.rb b/spec/requests/api/v1/configs_controller_spec.rb
similarity index 90%
rename from spec/requests/api/configs_spec.rb
rename to spec/requests/api/v1/configs_controller_spec.rb
index 75f48ceb..1809065a 100644
--- a/spec/requests/api/configs_spec.rb
+++ b/spec/requests/api/v1/configs_controller_spec.rb
@@ -1,6 +1,6 @@
require 'swagger_helper'
-describe 'Config', type: :request do
+describe Api::V1::ConfigsController do
include ApiHelper
path '/config' do
diff --git a/spec/requests/api/financial_transaction_classes_spec.rb b/spec/requests/api/v1/financial_transaction_classes_controller_spec.rb
similarity index 95%
rename from spec/requests/api/financial_transaction_classes_spec.rb
rename to spec/requests/api/v1/financial_transaction_classes_controller_spec.rb
index 1eaf046f..4db7f2b7 100644
--- a/spec/requests/api/financial_transaction_classes_spec.rb
+++ b/spec/requests/api/v1/financial_transaction_classes_controller_spec.rb
@@ -1,6 +1,6 @@
require 'swagger_helper'
-describe 'Financial Transaction Classes', type: :request do
+describe Api::V1::FinancialTransactionClassesController do
include ApiHelper
path '/financial_transaction_classes' do
diff --git a/spec/requests/api/financial_transaction_types_spec.rb b/spec/requests/api/v1/financial_transaction_types_controller_spec.rb
similarity index 95%
rename from spec/requests/api/financial_transaction_types_spec.rb
rename to spec/requests/api/v1/financial_transaction_types_controller_spec.rb
index 82a30f83..d061214e 100644
--- a/spec/requests/api/financial_transaction_types_spec.rb
+++ b/spec/requests/api/v1/financial_transaction_types_controller_spec.rb
@@ -1,6 +1,6 @@
require 'swagger_helper'
-describe 'Financial Transaction types', type: :request do
+describe Api::V1::FinancialTransactionTypesController do
include ApiHelper
path '/financial_transaction_types' do
diff --git a/spec/requests/api/financial_transactions_spec.rb b/spec/requests/api/v1/financial_transactions_controller_spec.rb
similarity index 88%
rename from spec/requests/api/financial_transactions_spec.rb
rename to spec/requests/api/v1/financial_transactions_controller_spec.rb
index 1d3ef2b9..915f3891 100644
--- a/spec/requests/api/financial_transactions_spec.rb
+++ b/spec/requests/api/v1/financial_transactions_controller_spec.rb
@@ -1,10 +1,12 @@
require 'swagger_helper'
-describe 'Financial Transaction', type: :request do
+describe Api::V1::FinancialTransactionsController do
include ApiHelper
let!(:finance_user) { create(:user, groups: [create(:workgroup, role_finance: true)]) }
let!(:api_scopes) { ['finance:read', 'finance:write'] }
- let(:api_access_token) { create(:oauth2_access_token, resource_owner_id: finance_user.id, scopes: api_scopes&.join(' ')).token }
+ let(:api_access_token) do
+ create(:oauth2_access_token, resource_owner_id: finance_user.id, scopes: api_scopes&.join(' ')).token
+ end
let(:financial_transaction) { create(:financial_transaction, user: user) }
path '/financial_transactions' do
diff --git a/spec/requests/api/navigations_spec.rb b/spec/requests/api/v1/navigations_controller_spec.rb
similarity index 90%
rename from spec/requests/api/navigations_spec.rb
rename to spec/requests/api/v1/navigations_controller_spec.rb
index c2312437..13c0a449 100644
--- a/spec/requests/api/navigations_spec.rb
+++ b/spec/requests/api/v1/navigations_controller_spec.rb
@@ -1,6 +1,6 @@
require 'swagger_helper'
-describe 'Navigation', type: :request do
+describe Api::V1::NavigationsController do
include ApiHelper
path '/navigation' do
diff --git a/spec/requests/api/order_articles_spec.rb b/spec/requests/api/v1/order_articles_controller_spec.rb
similarity index 98%
rename from spec/requests/api/order_articles_spec.rb
rename to spec/requests/api/v1/order_articles_controller_spec.rb
index 17feefa6..97fea3bb 100644
--- a/spec/requests/api/order_articles_spec.rb
+++ b/spec/requests/api/v1/order_articles_controller_spec.rb
@@ -1,6 +1,6 @@
require 'swagger_helper'
-describe 'Order Articles', type: :request do
+describe Api::V1::OrderArticlesController do
include ApiHelper
path '/order_articles' do
diff --git a/spec/requests/api/orders_spec.rb b/spec/requests/api/v1/orders_controller_spec.rb
similarity index 96%
rename from spec/requests/api/orders_spec.rb
rename to spec/requests/api/v1/orders_controller_spec.rb
index c0505d7f..0ad4131e 100644
--- a/spec/requests/api/orders_spec.rb
+++ b/spec/requests/api/v1/orders_controller_spec.rb
@@ -1,6 +1,6 @@
require 'swagger_helper'
-describe 'Orders', type: :request do
+describe Api::V1::OrdersController do
include ApiHelper
let(:api_scopes) { ['orders:read'] }
diff --git a/spec/requests/api/user/financial_transactions_spec.rb b/spec/requests/api/v1/user/financial_transactions_spec.rb
similarity index 74%
rename from spec/requests/api/user/financial_transactions_spec.rb
rename to spec/requests/api/v1/user/financial_transactions_spec.rb
index 4fb69cd6..c37d5b22 100644
--- a/spec/requests/api/user/financial_transactions_spec.rb
+++ b/spec/requests/api/v1/user/financial_transactions_spec.rb
@@ -1,11 +1,11 @@
require 'swagger_helper'
-describe 'User', type: :request do
+describe 'User' do
include ApiHelper
let(:api_scopes) { ['finance:user'] }
- let(:user) { create :user, groups: [create(:ordergroup)] }
- let(:other_user2) { create :user }
+ let(:user) { create(:user, groups: [create(:ordergroup)]) }
+ let(:other_user2) { create(:user) }
let(:ft) { create(:financial_transaction, user: user, ordergroup: user.ordergroup) }
before do
@@ -27,7 +27,9 @@ describe 'User', type: :request do
}
}
- let(:financial_transaction) { { amount: 3, financial_transaction_type_id: create(:financial_transaction_type).id, note: 'lirum larum' } }
+ let(:financial_transaction) do
+ { amount: 3, financial_transaction_type_id: create(:financial_transaction_type).id, note: 'lirum larum' }
+ end
response '200', 'success' do
schema type: :object, properties: {
@@ -45,15 +47,11 @@ describe 'User', type: :request do
run_test!
end
- # TODO: fix controller to actually send a 422 for invalid params?
- # Expected response code '200' to match '422'
- # Response body: {"financial_transaction":{"id":316,"user_id":599,"user_name":"Lisbeth ","amount":-3.0,"note":"-2","created_at":"2022-12-12T13:05:32.000+01:00","financial_transaction_type_id":346,"financial_transaction_type_name":"aut est iste #9"}}
- #
- # response '422', 'invalid parameter value' do
- # # schema '$ref' => '#/components/schemas/Error422'
- # let(:financial_transaction) { { amount: -3, financial_transaction_type_id: create(:financial_transaction_type).id, note: -2 } }
- # run_test!
- # end
+ response '422', 'invalid parameter value' do
+ schema '$ref' => '#/components/schemas/Error422'
+ let(:financial_transaction) { { amount: "abc", financial_transaction_type_id: create(:financial_transaction_type).id, note: "foo bar" } }
+ run_test!
+ end
end
get "financial transactions of the member's ordergroup" do
diff --git a/spec/requests/api/user/group_order_articles_spec.rb b/spec/requests/api/v1/user/group_order_articles_spec.rb
similarity index 88%
rename from spec/requests/api/user/group_order_articles_spec.rb
rename to spec/requests/api/v1/user/group_order_articles_spec.rb
index 205a4070..e93c7ecf 100644
--- a/spec/requests/api/user/group_order_articles_spec.rb
+++ b/spec/requests/api/v1/user/group_order_articles_spec.rb
@@ -1,15 +1,15 @@
require 'swagger_helper'
-describe 'User', type: :request do
+describe 'User' do
include ApiHelper
let(:api_scopes) { ['group_orders:user'] }
- let(:user) { create :user, groups: [create(:ordergroup)] }
- let(:other_user2) { create :user }
+ let(:user) { create(:user, groups: [create(:ordergroup)]) }
+ let(:other_user2) { create(:user) }
let(:order) { create(:order, article_count: 4) }
let(:order_articles) { order.order_articles }
- let(:group_order) { create :group_order, ordergroup: user.ordergroup, order_id: order.id }
- let(:goa) { create :group_order_article, group_order: group_order, order_article: order_articles.first }
+ let(:group_order) { create(:group_order, ordergroup: user.ordergroup, order_id: order.id) }
+ let(:goa) { create(:group_order_article, group_order: group_order, order_article: order_articles.first) }
before do
goa
@@ -134,11 +134,12 @@ describe 'User', type: :request do
response 401, 'not logged-in' do
schema '$ref' => '#/components/schemas/Error401'
- let(:Authorization) { 'abc' }
+ let(:Authorization) { 'abc' } # rubocop:disable RSpec/VariableName
run_test!
end
- response 403, 'user has no ordergroup, order not open, is below minimum balance, has not enough apple points, or missing scope' do
+ response 403,
+ 'user has no ordergroup, order not open, is below minimum balance, has not enough apple points, or missing scope' do
let(:api_scopes) { ['none'] }
schema '$ref' => '#/components/schemas/Error403'
run_test!
@@ -180,7 +181,8 @@ describe 'User', type: :request do
it_handles_invalid_token_with_id
- response 403, 'user has no ordergroup, order not open, is below minimum balance, has not enough apple points, or missing scope' do
+ response 403,
+ 'user has no ordergroup, order not open, is below minimum balance, has not enough apple points, or missing scope' do
let(:api_scopes) { ['none'] }
schema '$ref' => '#/components/schemas/Error403'
run_test!
diff --git a/spec/requests/api/user/users_spec.rb b/spec/requests/api/v1/user/users_spec.rb
similarity index 94%
rename from spec/requests/api/user/users_spec.rb
rename to spec/requests/api/v1/user/users_spec.rb
index 0d3196bc..90e343fa 100644
--- a/spec/requests/api/user/users_spec.rb
+++ b/spec/requests/api/v1/user/users_spec.rb
@@ -1,6 +1,6 @@
require 'swagger_helper'
-describe 'User', type: :request do
+describe 'User' do
include ApiHelper
path '/user' do
@@ -8,9 +8,9 @@ describe 'User', type: :request do
tags 'User'
produces 'application/json'
let(:api_scopes) { ['user:read'] }
- let(:other_user1) { create :user }
- let(:user) { create :user }
- let(:other_user2) { create :user }
+ let(:other_user1) { create(:user) }
+ let(:user) { create(:user) }
+ let(:other_user2) { create(:user) }
response '200', 'success' do
schema type: :object,
@@ -52,7 +52,7 @@ describe 'User', type: :request do
get 'financial summary about the currently logged-in user' do
tags 'User', 'Financial Transaction'
produces 'application/json'
- let(:user) { create :user, :ordergroup }
+ let(:user) { create(:user, :ordergroup) }
let(:api_scopes) { ['finance:user'] }
FinancialTransactionClass.create(name: 'TestTransaction')
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index 41894406..3bbf03ea 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -1,8 +1,8 @@
# This file is copied to spec/ when you run 'rails generate rspec:install'
-ENV["RAILS_ENV"] ||= 'test'
-ENV["FOODSOFT_APP_CONFIG"] ||= 'spec/app_config.yml' # load special foodsoft config
+ENV['RAILS_ENV'] ||= 'test'
+ENV['FOODSOFT_APP_CONFIG'] ||= 'spec/app_config.yml' # load special foodsoft config
require_relative 'support/coverage' # needs to be first
-require File.expand_path("../../config/environment", __FILE__)
+require File.expand_path('../config/environment', __dir__)
require 'rspec/rails'
require 'capybara/rails'
require 'capybara/apparition'
@@ -17,21 +17,17 @@ end
# Requires supporting ruby files with custom matchers and macros, etc,
# in spec/support/ and its subdirectories.
-Dir[Rails.root.join("spec/support/**/*.rb")].each { |f| require f }
+Dir[Rails.root.join('spec/support/**/*.rb')].each { |f| require f }
RSpec.configure do |config|
# We use capybara with webkit, and need database_cleaner
- config.before(:suite) do
- DatabaseCleaner.clean_with(:truncation)
- end
-
- config.before(:each) do
+ config.before do
DatabaseCleaner.strategy = (RSpec.current_example.metadata[:js] ? :truncation : :transaction)
DatabaseCleaner.start
# clean slate mail queues, not sure why needed - https://github.com/rspec/rspec-rails/issues/661
ActionMailer::Base.deliveries.clear
end
- config.after(:each) do
+ config.after do
DatabaseCleaner.clean
# Need to clear cache for RailsSettings::CachedSettings
Rails.cache.clear
@@ -39,7 +35,7 @@ RSpec.configure do |config|
# reload foodsoft configuration, so that tests can use FoodsoftConfig.config[:foo]=x
# without messing up tests run after that
- config.before(:each) do
+ config.before do
FoodsoftConfig.init
FoodsoftConfig.init_mailing
end
@@ -53,7 +49,7 @@ RSpec.configure do |config|
# order dependency and want to debug it, you can fix the order by providing
# the seed, which is printed after each run.
# --seed 1234
- config.order = "random"
+ config.order = 'random'
config.include SpecTestHelper, type: :controller
config.include SessionHelper, type: :feature
diff --git a/spec/support/api_helper.rb b/spec/support/api_helper.rb
index 86e2ca07..3a6e7894 100644
--- a/spec/support/api_helper.rb
+++ b/spec/support/api_helper.rb
@@ -4,12 +4,14 @@ module ApiHelper
included do
let(:user) { create(:user) }
let(:api_scopes) { [] } # empty scopes for stricter testing (in reality this would be default_scopes)
- let(:api_access_token) { create(:oauth2_access_token, resource_owner_id: user.id, scopes: api_scopes&.join(' ')).token }
- let(:Authorization) { "Bearer #{api_access_token}" }
+ let(:api_access_token) do
+ create(:oauth2_access_token, resource_owner_id: user.id, scopes: api_scopes&.join(' ')).token
+ end
+ let(:Authorization) { "Bearer #{api_access_token}" } # rubocop:disable RSpec/VariableName
def self.it_handles_invalid_token
context 'with invalid access token' do
- let(:Authorization) { 'abc' }
+ let(:Authorization) { 'abc' } # rubocop:disable RSpec/VariableName
response 401, 'not logged-in' do
schema '$ref' => '#/components/schemas/Error401'
@@ -20,7 +22,7 @@ module ApiHelper
def self.it_handles_invalid_token_with_id
context 'with invalid access token' do
- let(:Authorization) { 'abc' }
+ let(:Authorization) { 'abc' } # rubocop:disable RSpec/VariableName
let(:id) { 42 } # id doesn't matter here
response 401, 'not logged-in' do
diff --git a/spec/support/api_oauth.rb b/spec/support/api_oauth.rb
index 00d5318d..da8a56c1 100644
--- a/spec/support/api_oauth.rb
+++ b/spec/support/api_oauth.rb
@@ -5,7 +5,7 @@ module ApiOAuth
included do
let(:user) { build(:user) }
let(:api_scopes) { [] } # empty scopes for stricter testing (in reality this would be default_scopes)
- let(:api_access_token) { double(:acceptable? => true, :accessible? => true, scopes: api_scopes) }
+ let(:api_access_token) { double(acceptable?: true, accessible?: true, scopes: api_scopes) }
before { allow(controller).to receive(:doorkeeper_token) { api_access_token } }
before { allow(controller).to receive(:current_user) { user } }
diff --git a/spec/support/coverage.rb b/spec/support/coverage.rb
index 20bbdcf3..b4142c3d 100644
--- a/spec/support/coverage.rb
+++ b/spec/support/coverage.rb
@@ -11,7 +11,7 @@ if ENV['COVERAGE'] or ENV['COVERALLS']
# slightly tweaked coverage reporting
def cov_no_plugins(source_file, path)
- source_file.filename =~ /#{path}/ and not source_file.filename =~ /\/lib\/foodsoft_.*\//
+ source_file.filename =~ /#{path}/ and !(source_file.filename =~ %r{/lib/foodsoft_.*/})
end
SimpleCov.start do
add_filter '/spec/'
@@ -21,6 +21,6 @@ if ENV['COVERAGE'] or ENV['COVERALLS']
add_group 'Helpers' do |s| cov_no_plugins s, '/app/helpers/' end
add_group 'Documents' do |s| cov_no_plugins s, '/app/documents/' end
add_group 'Libraries' do |s| cov_no_plugins s, '/lib/' end
- add_group 'Plugins' do |s| s.filename =~ /\/lib\/foodsoft_.*\// end
+ add_group 'Plugins' do |s| s.filename =~ %r{/lib/foodsoft_.*/} end
end
end
diff --git a/spec/support/faker.rb b/spec/support/faker.rb
index 47441ca8..6516fa92 100644
--- a/spec/support/faker.rb
+++ b/spec/support/faker.rb
@@ -2,7 +2,7 @@ module Faker
class Unit
class << self
def unit
- ['kg', '1L', '100ml', 'piece', 'bunch', '500g'].sample
+ %w[kg 1L 100ml piece bunch 500g].sample
end
end
end
diff --git a/spec/support/integration.rb b/spec/support/integration.rb
index 26add35a..6882ac5a 100644
--- a/spec/support/integration.rb
+++ b/spec/support/integration.rb
@@ -1,4 +1,4 @@
# @see http://stackoverflow.com/a/11048669/2866660
def scrolldown
- page.execute_script "window.scrollBy(0,10000)"
+ page.execute_script 'window.scrollBy(0,10000)'
end
diff --git a/spec/support/session_helper.rb b/spec/support/session_helper.rb
index 31fb0946..1075695e 100644
--- a/spec/support/session_helper.rb
+++ b/spec/support/session_helper.rb
@@ -1,14 +1,15 @@
module SessionHelper
def login(user = nil, password = nil)
visit login_path
- user = FactoryBot.create :user if user.nil?
+ user = FactoryBot.create(:user) if user.nil?
if user.instance_of? ::User
- nick, password = user.nick, user.password
+ nick = user.nick
+ password = user.password
else
nick = user
end
- fill_in 'nick', :with => nick
- fill_in 'password', :with => password
+ fill_in 'nick', with: nick
+ fill_in 'password', with: password
find('input[type=submit]').click
end
end
diff --git a/spec/support/shared_database.rb b/spec/support/shared_database.rb
index f6c0ff0a..180877ec 100644
--- a/spec/support/shared_database.rb
+++ b/spec/support/shared_database.rb
@@ -4,7 +4,7 @@ ActiveSupport.on_load(:after_initialize) do
# But take care when designing tests using the shared database.
SharedSupplier.establish_connection Rails.env.to_sym
SharedArticle.establish_connection Rails.env.to_sym
- # hack for different structure of shared database
+ # HACK: for different structure of shared database
SharedArticle.class_eval do
belongs_to :supplier, class_name: 'SharedSupplier'
alias_attribute :number, :order_number
diff --git a/spec/support/spec_test_helper.rb b/spec/support/spec_test_helper.rb
index 58a1c0ef..f3737c15 100644
--- a/spec/support/spec_test_helper.rb
+++ b/spec/support/spec_test_helper.rb
@@ -2,7 +2,7 @@
module SpecTestHelper
def login(user)
- user = User.where(:nick => user.nick).first if user.is_a?(Symbol)
+ user = User.find_by_nick(user.nick)
session[:user_id] = user.id
session[:scope] = FoodsoftConfig[:default_scope] # Save scope in session to not allow switching between foodcoops with one account
session[:locale] = user.locale
@@ -16,13 +16,8 @@ module SpecTestHelper
params['foodcoop'] = FoodsoftConfig[:default_scope]
get action, params: params, xhr: xhr, format: format
end
-
- def post_with_defaults(action, params: {}, xhr: false, format: nil)
- params['foodcoop'] = FoodsoftConfig[:default_scope]
- post action, params: params, xhr: xhr, format: format
- end
end
RSpec.configure do |config|
- config.include SpecTestHelper, :type => :controller
+ config.include SpecTestHelper, type: :controller
end
diff --git a/spec/swagger_helper.rb b/spec/swagger_helper.rb
index 912504b8..dbe5a912 100644
--- a/spec/swagger_helper.rb
+++ b/spec/swagger_helper.rb
@@ -32,7 +32,7 @@ RSpec.configure do |config|
currentPage: { type: :integer },
pageSize: { type: :integer }
},
- required: %w(recordCount pageCount currentPage pageSize)
+ required: %w[recordCount pageCount currentPage pageSize]
},
Order: {
type: :object,
@@ -127,7 +127,8 @@ RSpec.configure do |config|
description: 'number of units available (only present on stock articles)'
}
},
- required: %w[id name supplier_id supplier_name unit unit_quantity note manufacturer origin article_category_id]
+ required: %w[id name supplier_id supplier_name unit unit_quantity note manufacturer origin
+ article_category_id]
},
OrderArticle: {
type: :object,
@@ -396,7 +397,7 @@ RSpec.configure do |config|
description: 'link'
},
items: {
- '$ref': "#/components/schemas/Navigation"
+ '$ref': '#/components/schemas/Navigation'
}
},
required: ['name'],