From c194d2545f60550ba5c16f52b59488f46c625fc8 Mon Sep 17 00:00:00 2001 From: Robert Waltemath Date: Tue, 4 Jun 2013 11:28:25 +0200 Subject: [PATCH 01/59] Allowing SharedSuppliers to have multiple Suppliers. Should fix bennibu#107. --- app/controllers/articles_controller.rb | 2 +- app/models/shared_article.rb | 4 ++-- app/models/shared_supplier.rb | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/controllers/articles_controller.rb b/app/controllers/articles_controller.rb index 820242d6..e8718a0a 100644 --- a/app/controllers/articles_controller.rb +++ b/app/controllers/articles_controller.rb @@ -213,7 +213,7 @@ class ArticlesController < ApplicationController # fills a form whith values of the selected shared_article def import - @article = SharedArticle.find(params[:shared_article_id]).build_new_article + @article = SharedArticle.find(params[:shared_article_id]).build_new_article(@supplier) render :action => 'new', :layout => false end diff --git a/app/models/shared_article.rb b/app/models/shared_article.rb index 777b7f77..440842ec 100644 --- a/app/models/shared_article.rb +++ b/app/models/shared_article.rb @@ -7,8 +7,8 @@ class SharedArticle < ActiveRecord::Base belongs_to :shared_supplier, :foreign_key => :supplier_id - def build_new_article - shared_supplier.supplier.articles.build( + def build_new_article(supplier) + supplier.articles.build( :name => name, :unit => unit, :note => note, diff --git a/app/models/shared_supplier.rb b/app/models/shared_supplier.rb index fa1e582a..f4bd44df 100644 --- a/app/models/shared_supplier.rb +++ b/app/models/shared_supplier.rb @@ -5,7 +5,7 @@ class SharedSupplier < ActiveRecord::Base # set correct table_name in external DB self.table_name = 'suppliers' - has_one :supplier + has_many :suppliers has_many :shared_articles, :foreign_key => :supplier_id end From 6bdb7b35f0b91ec9bc2b5e5107beef31792331d9 Mon Sep 17 00:00:00 2001 From: Robert Waltemath Date: Mon, 10 Jun 2013 11:37:59 +0200 Subject: [PATCH 02/59] Showing/allowing multiple suppliers per shared supplier in shared-supplier-listing. --- app/views/suppliers/shared_suppliers.haml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/views/suppliers/shared_suppliers.haml b/app/views/suppliers/shared_suppliers.haml index 2de9234d..0c060582 100644 --- a/app/views/suppliers/shared_suppliers.haml +++ b/app/views/suppliers/shared_suppliers.haml @@ -22,7 +22,9 @@ %td= shared_supplier.note %td= shared_supplier.delivery_days %td - - if shared_supplier.supplier + - if shared_supplier.suppliers %i.icon-ok + = '(' + shared_supplier.suppliers.map{|s| s.name}.join(', ') + ')' + = link_to "abonnieren", new_supplier_path(:shared_supplier_id => shared_supplier), class: 'btn' - else - = link_to "abonnieren", new_supplier_path(:shared_supplier_id => shared_supplier), class: 'btn' \ No newline at end of file + = link_to "abonnieren", new_supplier_path(:shared_supplier_id => shared_supplier), class: 'btn' From f4a0e292979ca87585d8ff880080555a8346f189 Mon Sep 17 00:00:00 2001 From: Benjamin Meichsner Date: Wed, 12 Jun 2013 10:47:54 +0200 Subject: [PATCH 03/59] Fixed bug in with new shared multiple suppliers feature. --- app/controllers/suppliers_controller.rb | 2 +- app/helpers/suppliers_helper.rb | 6 ++++++ app/views/suppliers/shared_suppliers.haml | 6 +++--- 3 files changed, 10 insertions(+), 4 deletions(-) create mode 100644 app/helpers/suppliers_helper.rb diff --git a/app/controllers/suppliers_controller.rb b/app/controllers/suppliers_controller.rb index 8b8af131..4c9a4852 100644 --- a/app/controllers/suppliers_controller.rb +++ b/app/controllers/suppliers_controller.rb @@ -18,7 +18,7 @@ class SuppliersController < ApplicationController def new if params[:shared_supplier_id] shared_supplier = SharedSupplier.find(params[:shared_supplier_id]) - @supplier = shared_supplier.build_supplier(shared_supplier.autofill_attributes) + @supplier = shared_supplier.suppliers.new(shared_supplier.autofill_attributes) else @supplier = Supplier.new end diff --git a/app/helpers/suppliers_helper.rb b/app/helpers/suppliers_helper.rb new file mode 100644 index 00000000..9876f11d --- /dev/null +++ b/app/helpers/suppliers_helper.rb @@ -0,0 +1,6 @@ +module SuppliersHelper + + def associated_supplier_names(shared_supplier) + "(#{shared_supplier.suppliers.map(&:name).join(', ')})" + end +end \ No newline at end of file diff --git a/app/views/suppliers/shared_suppliers.haml b/app/views/suppliers/shared_suppliers.haml index 0c060582..30355291 100644 --- a/app/views/suppliers/shared_suppliers.haml +++ b/app/views/suppliers/shared_suppliers.haml @@ -22,9 +22,9 @@ %td= shared_supplier.note %td= shared_supplier.delivery_days %td - - if shared_supplier.suppliers + - if shared_supplier.suppliers.any? %i.icon-ok - = '(' + shared_supplier.suppliers.map{|s| s.name}.join(', ') + ')' - = link_to "abonnieren", new_supplier_path(:shared_supplier_id => shared_supplier), class: 'btn' + = associated_supplier_names(shared_supplier) + = link_to "erneut abonnieren", new_supplier_path(:shared_supplier_id => shared_supplier), class: 'btn' - else = link_to "abonnieren", new_supplier_path(:shared_supplier_id => shared_supplier), class: 'btn' From 7fa81930106ce6ddc560ce2bd82f8b4d39063877 Mon Sep 17 00:00:00 2001 From: wvengen Date: Fri, 12 Jul 2013 20:06:49 +0200 Subject: [PATCH 04/59] start using rspec for tests --- Gemfile | 9 +++--- Gemfile.lock | 23 ++++++++++++--- spec/factories/user.rb | 33 +++++++++++++++++++++ spec/models/user_spec.rb | 63 ++++++++++++++++++++++++++++++++++++++++ spec/spec_helper.rb | 38 ++++++++++++++++++++++++ 5 files changed, 158 insertions(+), 8 deletions(-) create mode 100644 spec/factories/user.rb create mode 100644 spec/models/user_spec.rb create mode 100644 spec/spec_helper.rb diff --git a/Gemfile b/Gemfile index 9bec3431..4f60ef24 100644 --- a/Gemfile +++ b/Gemfile @@ -52,10 +52,6 @@ group :development do gem 'better_errors' gem 'binding_of_caller' - # Re-enable rails benchmarker/profiler - gem 'ruby-prof' - gem 'test-unit' - # Get infos when not using proper eager loading gem 'bullet' @@ -69,3 +65,8 @@ group :development do # Avoid having content-length warnings gem 'thin' end + +group :development, :test do + gem 'rspec-rails' + gem 'factory_girl_rails', '~> 4.0' +end diff --git a/Gemfile.lock b/Gemfile.lock index c10e145e..b4bfaa25 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -81,6 +81,7 @@ GEM coffee-script-source (1.3.3) commonjs (0.2.6) daemons (1.1.9) + diff-lcs (1.2.4) erubis (2.7.0) eventmachine (1.0.3) exception_notification (2.6.1) @@ -88,6 +89,11 @@ GEM execjs (1.4.0) multi_json (~> 1.0) expression_parser (0.9.0) + factory_girl (4.2.0) + activesupport (>= 3.0.0) + factory_girl_rails (4.2.1) + factory_girl (~> 4.2.0) + railties (>= 3.0.0) haml (3.1.7) haml-rails (0.3.5) actionpack (>= 3.1, < 4.1) @@ -195,7 +201,17 @@ GEM redis-namespace (~> 1.2) sinatra (>= 0.9.2) vegas (~> 0.1.2) - ruby-prof (0.11.2) + rspec-core (2.14.2) + rspec-expectations (2.14.0) + diff-lcs (>= 1.1.3, < 2.0) + rspec-mocks (2.14.1) + rspec-rails (2.14.0) + actionpack (>= 3.0) + activesupport (>= 3.0) + railties (>= 3.0) + rspec-core (~> 2.14.0) + rspec-expectations (~> 2.14.0) + rspec-mocks (~> 2.14.0) ruby-rc4 (0.1.5) sass (3.2.1) sass-rails (3.2.5) @@ -222,7 +238,6 @@ GEM rack (~> 1.0) tilt (~> 1.1, != 1.3.0) sqlite3 (1.3.6) - test-unit (2.5.3) therubyracer (0.10.2) libv8 (~> 3.3.10) thin (1.5.1) @@ -271,6 +286,7 @@ DEPENDENCIES coffee-rails (~> 3.2.1) daemons exception_notification + factory_girl_rails (~> 4.0) haml-rails inherited_resources jquery-rails @@ -283,13 +299,12 @@ DEPENDENCIES quiet_assets rails (~> 3.2.9) resque - ruby-prof + rspec-rails sass-rails (~> 3.2.3) simple-navigation simple-navigation-bootstrap simple_form sqlite3 - test-unit therubyracer thin twitter-bootstrap-rails diff --git a/spec/factories/user.rb b/spec/factories/user.rb new file mode 100644 index 00000000..1161efd6 --- /dev/null +++ b/spec/factories/user.rb @@ -0,0 +1,33 @@ +require 'factory_girl' + +FactoryGirl.define do + + factory :user do + sequence(:nick) { |n| "user#{n}"} + first_name 'John' + email { "#{nick}@foodcoop.test" } + password { new_random_password } + + factory :admin do + sequence(:nick) { |n| "admin#{n}" } + first_name 'Administrator' + after :create do |user, evaluator| + FactoryGirl.create :workgroup, role_admin: true, user_ids: [user.id] + end + end + end + + factory :group do + sequence(:name) {|n| "Group ##{n}"} + + factory :workgroup do + type '' + end + + factory :ordergroup do + type 'Ordergroup' + sequence(:name) {|n| "Order group ##{n}"} + end + end + +end diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb new file mode 100644 index 00000000..b03e9e40 --- /dev/null +++ b/spec/models/user_spec.rb @@ -0,0 +1,63 @@ +require 'spec_helper' + +describe User do + + it 'is correctly created' do + user = FactoryGirl.create :user, + nick: 'johnnydoe', first_name: 'Johnny', last_name: 'DoeBar', + email: 'johnnydoe@foodcoop.test', phone: '+1234567890' + user.nick.should == 'johnnydoe' + user.first_name.should == 'Johnny' + user.last_name.should == 'DoeBar' + user.name.should == 'Johnny DoeBar' + user.email.should == 'johnnydoe@foodcoop.test' + user.phone.should == '+1234567890' + end + + describe 'does not have the role' do + let(:user) { FactoryGirl.create :user } + it 'admin' do user.role_admin?.should be_false end + it 'finance' do user.role_finance?.should be_false end + it 'article_meta' do user.role_article_meta?.should be_false end + it 'suppliers' do user.role_suppliers?.should be_false end + it 'orders' do user.role_orders?.should be_false end + end + + describe do + let(:user) { FactoryGirl.create :user, password: 'blahblah' } + + it 'can authenticate with correct password' do + User.authenticate(user.nick, 'blahblah').should be_true + end + it 'can not authenticate with incorrect password' do + User.authenticate(user.nick, 'foobar').should be_nil + end + it 'can not set a password without confirmation' do + user.password = 'abcdefghij' + user.should_not be_valid + end + it 'can not set a password without matching confirmation' do + user.password = 'abcdefghij' + user.password_confirmation = 'foobarxyz' + user.should_not be_valid + end + it 'can set a password with matching confirmation' do + user.password = 'abcdefghij' + user.password_confirmation = 'abcdefghij' + user.should be_valid + end + + it 'has a unique nick' do + FactoryGirl.build(:user, nick: user.nick, email: "x-#{user.email}").should_not be_valid + end + it 'has a unique email' do + FactoryGirl.build(:user, email: "#{user.email}").should_not be_valid + end + end + + describe 'admin' do + let(:user) { FactoryGirl.create :admin } + it 'default admin role' do user.role_admin?.should be_true end + end + +end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb new file mode 100644 index 00000000..d2cbea7d --- /dev/null +++ b/spec/spec_helper.rb @@ -0,0 +1,38 @@ +# This file is copied to spec/ when you run 'rails generate rspec:install' +ENV["RAILS_ENV"] ||= 'test' +require File.expand_path("../../config/environment", __FILE__) +require 'rspec/rails' +require 'rspec/autorun' + +# 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 } + +RSpec.configure do |config| + # ## Mock Framework + # + # If you prefer to use mocha, flexmock or RR, uncomment the appropriate line: + # + # config.mock_with :mocha + # config.mock_with :flexmock + # config.mock_with :rr + + # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures + config.fixture_path = "#{::Rails.root}/spec/fixtures" + + # If you're not using ActiveRecord, or you'd prefer not to run each of your + # examples within a transaction, remove the following line or assign false + # instead of true. + config.use_transactional_fixtures = true + + # If true, the base class of anonymous controllers will be inferred + # automatically. This will be the default behavior in future versions of + # rspec-rails. + config.infer_base_class_for_anonymous_controllers = false + + # Run specs in random order to surface order dependencies. If you find an + # 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" +end From 3c264f6225f87d5e467049d654e80f1725a5bec3 Mon Sep 17 00:00:00 2001 From: wvengen Date: Sun, 14 Jul 2013 02:49:40 +0200 Subject: [PATCH 05/59] add some rspec tests for supplier and article --- Gemfile | 1 + Gemfile.lock | 3 +++ spec/factories/article.rb | 20 ++++++++++++++++ spec/factories/supplier.rb | 19 ++++++++++++++++ spec/factories/user.rb | 4 ++-- spec/models/article_spec.rb | 44 ++++++++++++++++++++++++++++++++++++ spec/models/supplier_spec.rb | 11 +++++++++ spec/spec_helper.rb | 10 ++++++++ 8 files changed, 110 insertions(+), 2 deletions(-) create mode 100644 spec/factories/article.rb create mode 100644 spec/factories/supplier.rb create mode 100644 spec/models/article_spec.rb create mode 100644 spec/models/supplier_spec.rb diff --git a/Gemfile b/Gemfile index 4f60ef24..8405d992 100644 --- a/Gemfile +++ b/Gemfile @@ -69,4 +69,5 @@ end group :development, :test do gem 'rspec-rails' gem 'factory_girl_rails', '~> 4.0' + gem 'faker' end diff --git a/Gemfile.lock b/Gemfile.lock index b4bfaa25..27e48df4 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -94,6 +94,8 @@ GEM factory_girl_rails (4.2.1) factory_girl (~> 4.2.0) railties (>= 3.0.0) + faker (1.1.2) + i18n (~> 0.5) haml (3.1.7) haml-rails (0.3.5) actionpack (>= 3.1, < 4.1) @@ -287,6 +289,7 @@ DEPENDENCIES daemons exception_notification factory_girl_rails (~> 4.0) + faker haml-rails inherited_resources jquery-rails diff --git a/spec/factories/article.rb b/spec/factories/article.rb new file mode 100644 index 00000000..04144b24 --- /dev/null +++ b/spec/factories/article.rb @@ -0,0 +1,20 @@ +require 'factory_girl' + +FactoryGirl.define do + + factory :article do + name { Faker::Lorem.words(rand(2..5)).join(' ') } + unit { Faker::Unit.unit } + price { rand(2600) / 100 } + tax { [6, 21].sample } + deposit { rand(10) < 8 ? 0 : [0.0, 0.80, 1.20, 12.00].sample } + unit_quantity { rand(5) < 3 ? 1 : rand(1..20) } + #supplier_id + article_category { FactoryGirl.create :article_category } + end + + factory :article_category do + name { Faker::Lorem.characters(rand(2..20)) } + end + +end diff --git a/spec/factories/supplier.rb b/spec/factories/supplier.rb new file mode 100644 index 00000000..0833721f --- /dev/null +++ b/spec/factories/supplier.rb @@ -0,0 +1,19 @@ +require 'factory_girl' + +FactoryGirl.define do + + factory :supplier do + name { Faker::Company.name } + phone { Faker::PhoneNumber.phone_number } + address { Faker::Address.street_address } + + ignore do + article_count 0 + end + + after :create do |supplier, evaluator| + FactoryGirl.create_list :article, evaluator.article_count, supplier: supplier + end + end + +end diff --git a/spec/factories/user.rb b/spec/factories/user.rb index 1161efd6..0453d3e1 100644 --- a/spec/factories/user.rb +++ b/spec/factories/user.rb @@ -4,8 +4,8 @@ FactoryGirl.define do factory :user do sequence(:nick) { |n| "user#{n}"} - first_name 'John' - email { "#{nick}@foodcoop.test" } + first_name { Faker::Name.first_name } + email { Faker::Internet.email } password { new_random_password } factory :admin do diff --git a/spec/models/article_spec.rb b/spec/models/article_spec.rb new file mode 100644 index 00000000..5df322a3 --- /dev/null +++ b/spec/models/article_spec.rb @@ -0,0 +1,44 @@ +require 'spec_helper' + +describe Article do + let(:supplier) { FactoryGirl.create :supplier } + let(:article) { FactoryGirl.create :article, supplier: supplier } + + it 'has a unique name' do + article2 = FactoryGirl.build :article, supplier: supplier, name: article.name + article2.should_not be_valid + end + + it 'computes the gross price correctly' do + article.deposit = 0 + article.tax = 12 + article.gross_price.should == (article.price * 1.12).round(2) + article.deposit = 1.20 + article.gross_price.should == ((article.price + 1.20) * 1.12).round(2) + end + + it 'gross price >= net price' do + article.gross_price.should >= article.price + end + + it 'fc-price > gross price' do + article.fc_price.should > article.gross_price + end + + it 'knows when it is deleted' do + supplier.deleted?.should be_false + supplier.mark_as_deleted + supplier.deleted?.should be_true + end + + it 'keeps a price history' do + article.article_prices.count.should == 1 + oldprice = article.price + article.price += 1 + article.save! + article.article_prices.count.should == 2 + article.article_prices[0].price.should == article.price + article.article_prices[-1].price.should == oldprice + end + +end diff --git a/spec/models/supplier_spec.rb b/spec/models/supplier_spec.rb new file mode 100644 index 00000000..28dff73f --- /dev/null +++ b/spec/models/supplier_spec.rb @@ -0,0 +1,11 @@ +require 'spec_helper' + +describe Supplier do + let(:supplier) { FactoryGirl.create :supplier } + + it 'has a unique name' do + supplier2 = FactoryGirl.build :supplier, name: supplier.name + supplier2.should_not be_valid + end + +end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index d2cbea7d..5bf80082 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -36,3 +36,13 @@ RSpec.configure do |config| # --seed 1234 config.order = "random" end + +module Faker + class Unit + class << self + def unit + ['kg', '1L', '100ml', 'piece', 'bunch', '500g'].sample + end + end + end +end From acd18721aad385fa4ebf655b19f49b4a4f999eab Mon Sep 17 00:00:00 2001 From: wvengen Date: Mon, 15 Jul 2013 00:17:07 +0200 Subject: [PATCH 06/59] expand rspec tests --- spec/factories/order.rb | 14 +++++++++++ spec/factories/supplier.rb | 4 ++- spec/models/order_spec.rb | 49 ++++++++++++++++++++++++++++++++++++ spec/models/supplier_spec.rb | 5 ++++ 4 files changed, 71 insertions(+), 1 deletion(-) create mode 100644 spec/factories/order.rb create mode 100644 spec/models/order_spec.rb diff --git a/spec/factories/order.rb b/spec/factories/order.rb new file mode 100644 index 00000000..ac2182b5 --- /dev/null +++ b/spec/factories/order.rb @@ -0,0 +1,14 @@ +require 'factory_girl' + +FactoryGirl.define do + + # requires articles from single supplier, or supplier (with all its articles) + factory :order do + starts { Time.now } + + factory :stock_order do + supplier_id 0 + end + end + +end diff --git a/spec/factories/supplier.rb b/spec/factories/supplier.rb index 0833721f..39d0607b 100644 --- a/spec/factories/supplier.rb +++ b/spec/factories/supplier.rb @@ -12,7 +12,9 @@ FactoryGirl.define do end after :create do |supplier, evaluator| - FactoryGirl.create_list :article, evaluator.article_count, supplier: supplier + article_count = evaluator.article_count + article_count = rand(1..100) if article_count == true + FactoryGirl.create_list :article, article_count, supplier: supplier end end diff --git a/spec/models/order_spec.rb b/spec/models/order_spec.rb new file mode 100644 index 00000000..0d7a1d9f --- /dev/null +++ b/spec/models/order_spec.rb @@ -0,0 +1,49 @@ +require 'spec_helper' + +describe Order do + + it 'needs a supplier' do + FactoryGirl.build(:order).should_not be_valid + end + + it 'needs order articles' do + supplier = FactoryGirl.create :supplier, article_count: 0 + FactoryGirl.build(:order, supplier: supplier).should_not be_valid + end + + it 'can be created' do + supplier = FactoryGirl.create :supplier, article_count: 1 + FactoryGirl.build(:order, supplier: supplier, article_ids: supplier.articles.map(&:id)).should be_valid + end + + describe 'with articles' do + let(:supplier) { FactoryGirl.create :supplier, article_count: true } + let(:order) { FactoryGirl.create(:order, supplier: supplier, article_ids: supplier.articles.map(&:id)).reload } + + it 'is open by default' do order.open?.should be_true end + it 'is not finished by default' do order.finished?.should be_false end + it 'is not closed by default' do order.closed?.should be_false end + + it 'has valid order articles' do + order.order_articles.all.each {|oa| oa.should be_valid } + end + + it 'can be finished' do + # TODO randomise user + order.finish!(User.first) + order.open?.should be_false + order.finished?.should be_true + order.closed?.should be_false + end + + it 'can be closed' do + # TODO randomise user + order.finish!(User.first) + order.close!(User.first) + order.open?.should be_false + order.closed?.should be_true + end + + end + +end diff --git a/spec/models/supplier_spec.rb b/spec/models/supplier_spec.rb index 28dff73f..e7bf293e 100644 --- a/spec/models/supplier_spec.rb +++ b/spec/models/supplier_spec.rb @@ -8,4 +8,9 @@ describe Supplier do supplier2.should_not be_valid end + it 'has valid articles' do + supplier = FactoryGirl.create :supplier, article_count: true + supplier.articles.all.should be_valid + end + end From cc6a188f4e3d336acf6e21792dd7675846e857dd Mon Sep 17 00:00:00 2001 From: wvengen Date: Mon, 15 Jul 2013 00:22:20 +0200 Subject: [PATCH 07/59] fix small test bug --- spec/models/supplier_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/models/supplier_spec.rb b/spec/models/supplier_spec.rb index e7bf293e..3457e2da 100644 --- a/spec/models/supplier_spec.rb +++ b/spec/models/supplier_spec.rb @@ -10,7 +10,7 @@ describe Supplier do it 'has valid articles' do supplier = FactoryGirl.create :supplier, article_count: true - supplier.articles.all.should be_valid + supplier.articles.all.each {|a| a.should be_valid } end end From 3ed8e0bc84da7c5c2fae3facdb2d441b13c233f8 Mon Sep 17 00:00:00 2001 From: wvengen Date: Mon, 15 Jul 2013 17:57:00 +0200 Subject: [PATCH 08/59] allow longer supplier phone number --- app/models/supplier.rb | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/app/models/supplier.rb b/app/models/supplier.rb index 01f93d35..b1466a70 100644 --- a/app/models/supplier.rb +++ b/app/models/supplier.rb @@ -13,11 +13,9 @@ class Supplier < ActiveRecord::Base :delivery_days, :order_howto, :note, :shared_supplier_id, :min_order_quantity validates :name, :presence => true, :length => { :in => 4..30 } - validates :phone, :presence => true, :length => { :in => 8..20 } + validates :phone, :presence => true, :length => { :in => 8..25 } validates :address, :presence => true, :length => { :in => 8..50 } validates_length_of :order_howto, :note, maximum: 250 - validates_length_of :phone, :in => 8..20 - validates_length_of :address, :in => 8..50 validate :uniqueness_of_name scope :undeleted, -> { where(deleted_at: nil) } From 3a7d650ed87c7eb9dee9c7c07a37026cfa32de24 Mon Sep 17 00:00:00 2001 From: wvengen Date: Mon, 15 Jul 2013 17:57:20 +0200 Subject: [PATCH 09/59] fix tests --- spec/factories/supplier.rb | 2 +- spec/models/user_spec.rb | 4 ---- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/spec/factories/supplier.rb b/spec/factories/supplier.rb index 39d0607b..fdb2fa03 100644 --- a/spec/factories/supplier.rb +++ b/spec/factories/supplier.rb @@ -3,7 +3,7 @@ require 'factory_girl' FactoryGirl.define do factory :supplier do - name { Faker::Company.name } + name { Faker::Company.name.truncate(30) } phone { Faker::PhoneNumber.phone_number } address { Faker::Address.street_address } diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index b03e9e40..91e4abe7 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -32,10 +32,6 @@ describe User do it 'can not authenticate with incorrect password' do User.authenticate(user.nick, 'foobar').should be_nil end - it 'can not set a password without confirmation' do - user.password = 'abcdefghij' - user.should_not be_valid - end it 'can not set a password without matching confirmation' do user.password = 'abcdefghij' user.password_confirmation = 'foobarxyz' From 679fc673c7d1079880a5753ac9fc48005378cfc0 Mon Sep 17 00:00:00 2001 From: wvengen Date: Mon, 15 Jul 2013 18:45:02 +0200 Subject: [PATCH 10/59] add group_order spec --- spec/factories/group_order.rb | 9 +++++++++ spec/models/group_order_spec.rb | 24 ++++++++++++++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 spec/factories/group_order.rb create mode 100644 spec/models/group_order_spec.rb diff --git a/spec/factories/group_order.rb b/spec/factories/group_order.rb new file mode 100644 index 00000000..ed6b6017 --- /dev/null +++ b/spec/factories/group_order.rb @@ -0,0 +1,9 @@ +require 'factory_girl' + +FactoryGirl.define do + + # requires order and ordergroup + factory :group_order do + end + +end diff --git a/spec/models/group_order_spec.rb b/spec/models/group_order_spec.rb new file mode 100644 index 00000000..5c2138dd --- /dev/null +++ b/spec/models/group_order_spec.rb @@ -0,0 +1,24 @@ +require 'spec_helper' + +describe GroupOrder do + let(:user) { FactoryGirl.create :user, groups: [FactoryGirl.create(:ordergroup)] } + let(:supplier) { FactoryGirl.create :supplier, article_count: true } + let(:order) { FactoryGirl.create(:order, supplier: supplier, article_ids: supplier.articles.map(&:id)).reload } + + it 'needs an order' do + FactoryGirl.build(:group_order, ordergroup: user.ordergroup).should_not be_valid + end + + it 'needs an ordergroup' do + FactoryGirl.build(:group_order, order: order).should_not be_valid + end + + describe do + let(:go) { FactoryGirl.create :group_order, order: order, ordergroup: user.ordergroup } + + it 'has zero price initially' do + go.price.should == 0 + end + end + +end From 427a023135d7c055633bd6375a384454a0aa25a4 Mon Sep 17 00:00:00 2001 From: wvengen Date: Mon, 15 Jul 2013 21:01:46 +0200 Subject: [PATCH 11/59] add group_order_article spec --- spec/factories/group_order_article.rb | 9 ++++ spec/models/group_order_article_spec.rb | 62 +++++++++++++++++++++++++ 2 files changed, 71 insertions(+) create mode 100644 spec/factories/group_order_article.rb create mode 100644 spec/models/group_order_article_spec.rb diff --git a/spec/factories/group_order_article.rb b/spec/factories/group_order_article.rb new file mode 100644 index 00000000..8b2982d8 --- /dev/null +++ b/spec/factories/group_order_article.rb @@ -0,0 +1,9 @@ +require 'factory_girl' + +FactoryGirl.define do + + # requires order_article + factory :group_order_article do + end + +end diff --git a/spec/models/group_order_article_spec.rb b/spec/models/group_order_article_spec.rb new file mode 100644 index 00000000..e9b9046f --- /dev/null +++ b/spec/models/group_order_article_spec.rb @@ -0,0 +1,62 @@ +require 'spec_helper' + +describe GroupOrderArticle do + let(:user) { FactoryGirl.create :user, groups: [FactoryGirl.create(:ordergroup)] } + let(:supplier) { FactoryGirl.create :supplier, article_count: true } + let(:order) { FactoryGirl.create(:order, supplier: supplier, article_ids: supplier.articles.map(&:id)).reload } + let(:go) { FactoryGirl.create :group_order, order: order, ordergroup: user.ordergroup } + let(:goa) { FactoryGirl.create :group_order_article, group_order: go, order_article: order.order_articles.first } + + it 'has zero quantity by default' do goa.quantity.should == 0 end + it 'has zero tolerance by default' do goa.tolerance.should == 0 end + it 'has zero result by default' do goa.result.should == 0 end + it 'is not ordered by default' do GroupOrderArticle.ordered.where(:id => goa.id).exists?.should be_false end + it 'has zero total price by default' do goa.total_price.should == 0 end + + describe do + let(:article) { FactoryGirl.create :article, supplier: supplier, unit_quantity: 1 } + let(:goa) { article; FactoryGirl.create :group_order_article, group_order: go, order_article: order.order_articles.find_by_article_id(article.id) } + + it 'can be ordered by piece' do + goa.update_quantities(1, 0) + goa.quantity.should == 1 + goa.tolerance == 0 + end + + it 'can be ordered in larger amounts' do + quantity, tolerance = rand(13..100), rand(0..100) + goa.update_quantities(quantity, tolerance) + goa.quantity.should == quantity + goa.tolerance.should == tolerance + end + + it 'has a proper total price' do + quantity = rand(1..100) + goa.update_quantities(quantity, 0) + goa.total_price.should == quantity * goa.order_article.price.fc_price + end + + it 'can unorder a product' do + goa.update_quantities(rand(1..100), rand(0..100)) + goa.update_quantities(0, 0) + goa.quantity.should == 0 + goa.tolerance.should == 0 + end + + it 'keeps track of article quantities' do + startq = startt = nil + for i in 0..6 do + goa.group_order_article_quantities.count == i + quantity, tolerance = rand(1..100), rand(0..100) + goa.update_quantities(quantity, tolerance) + startq.nil? and startq = quantity + startt.nil? and startt = tolerance + end + goaq = goa.group_order_article_quantities.last + goaq.quantity.should == startq + goaq.tolerance.should == startt + end + + end + +end From d58ce31b7f50b9850d233c776a2bb455187cc193 Mon Sep 17 00:00:00 2001 From: wvengen Date: Wed, 24 Jul 2013 01:05:01 +0200 Subject: [PATCH 12/59] add first integration test --- Gemfile | 1 + Gemfile.lock | 21 +++++++++++++++++++++ spec/integration/session_spec.rb | 21 +++++++++++++++++++++ spec/spec_helper.rb | 17 ++++++++++++++--- spec/support/session_helper.rb | 15 +++++++++++++++ 5 files changed, 72 insertions(+), 3 deletions(-) create mode 100644 spec/integration/session_spec.rb create mode 100644 spec/support/session_helper.rb diff --git a/Gemfile b/Gemfile index 8405d992..5f58bf54 100644 --- a/Gemfile +++ b/Gemfile @@ -70,4 +70,5 @@ group :development, :test do gem 'rspec-rails' gem 'factory_girl_rails', '~> 4.0' gem 'faker' + gem 'capybara' end diff --git a/Gemfile.lock b/Gemfile.lock index 27e48df4..2ce2d80c 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -69,6 +69,15 @@ GEM net-ssh-gateway (>= 1.1.0) capistrano-ext (1.2.1) capistrano (>= 1.0.0) + capybara (2.0.2) + mime-types (>= 1.16) + nokogiri (>= 1.3.3) + rack (>= 1.0.0) + rack-test (>= 0.5.4) + selenium-webdriver (~> 2.0) + xpath (~> 1.0.0) + childprocess (0.3.9) + ffi (~> 1.0, >= 1.0.11) chronic (0.9.0) client_side_validations (3.1.4) coderay (1.0.8) @@ -96,6 +105,7 @@ GEM railties (>= 3.0.0) faker (1.1.2) i18n (~> 0.5) + ffi (1.4.0) haml (3.1.7) haml-rails (0.3.5) actionpack (>= 3.1, < 4.1) @@ -153,6 +163,7 @@ GEM net-ssh (2.6.7) net-ssh-gateway (1.2.0) net-ssh (>= 2.6.5) + nokogiri (1.5.10) pdf-reader (1.2.0) Ascii85 (~> 1.0.0) hashery (~> 2.0) @@ -215,11 +226,17 @@ GEM rspec-expectations (~> 2.14.0) rspec-mocks (~> 2.14.0) ruby-rc4 (0.1.5) + rubyzip (0.9.9) sass (3.2.1) sass-rails (3.2.5) railties (~> 3.2.0) sass (>= 3.1.10) tilt (~> 1.3) + selenium-webdriver (2.31.0) + childprocess (>= 0.2.5) + multi_json (~> 1.0) + rubyzip + websocket (~> 1.0.4) simple-navigation (3.9.0) activesupport (>= 2.3.2) simple-navigation-bootstrap (0.0.4) @@ -264,12 +281,15 @@ GEM uniform_notifier (1.1.1) vegas (0.1.11) rack (>= 1.0.0) + websocket (1.0.7) whenever (0.8.1) activesupport (>= 2.3.4) chronic (>= 0.6.3) wikicloth (0.8.0) builder expression_parser + xpath (1.0.0) + nokogiri (~> 1.3) PLATFORMS ruby @@ -284,6 +304,7 @@ DEPENDENCIES bullet capistrano (= 2.13.5) capistrano-ext + capybara client_side_validations coffee-rails (~> 3.2.1) daemons diff --git a/spec/integration/session_spec.rb b/spec/integration/session_spec.rb new file mode 100644 index 00000000..81eb65d9 --- /dev/null +++ b/spec/integration/session_spec.rb @@ -0,0 +1,21 @@ +require 'spec_helper' + +describe 'the session', :type => :feature do + let(:user) { FactoryGirl.create :user } + + describe 'login page', :type => :feature do + it 'is accesible' do + get login_path + expect(response).to be_success + end + it 'logs me in' do + login user.nick, user.password + expect(page).to_not have_selector('.alert-error') + end + it 'does not log me in with wrong password' do + login user.nick, 'XX'+user.password + expect(page).to have_selector('.alert-error') + end + end + +end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 5bf80082..36cda713 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -4,6 +4,9 @@ require File.expand_path("../../config/environment", __FILE__) require 'rspec/rails' require 'rspec/autorun' +require 'capybara/rails' +require 'capybara/rspec' + # 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 } @@ -17,9 +20,6 @@ RSpec.configure do |config| # config.mock_with :flexmock # config.mock_with :rr - # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures - config.fixture_path = "#{::Rails.root}/spec/fixtures" - # If you're not using ActiveRecord, or you'd prefer not to run each of your # examples within a transaction, remove the following line or assign false # instead of true. @@ -35,6 +35,8 @@ RSpec.configure do |config| # the seed, which is printed after each run. # --seed 1234 config.order = "random" + + config.include(SessionHelper) end module Faker @@ -46,3 +48,12 @@ module Faker end end end + +# include default foodsoft scope in urls, so that *_path works +ActionDispatch::Integration::Runner.class_eval do + undef default_url_options + def default_url_options(options={}) + {foodcoop: FoodsoftConfig.scope}.merge(options) + end +end + diff --git a/spec/support/session_helper.rb b/spec/support/session_helper.rb new file mode 100644 index 00000000..c54d3362 --- /dev/null +++ b/spec/support/session_helper.rb @@ -0,0 +1,15 @@ + +module SessionHelper + + def login(nick=nil, password=nil) + visit login_path + if nick.nil? + user = FactoryGirl.create :user + nick, password = user.nick, user.password + end + fill_in 'nick', :with => nick + fill_in 'password', :with => password + find('input[type=submit]').click + end + +end From a858ceedeae97b042bc32f80c23b3ac7a65f82e1 Mon Sep 17 00:00:00 2001 From: wvengen Date: Wed, 24 Jul 2013 01:11:36 +0200 Subject: [PATCH 13/59] more flexible login in spec helper --- spec/integration/session_spec.rb | 2 +- spec/support/session_helper.rb | 8 +++----- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/spec/integration/session_spec.rb b/spec/integration/session_spec.rb index 81eb65d9..f86c2e59 100644 --- a/spec/integration/session_spec.rb +++ b/spec/integration/session_spec.rb @@ -9,7 +9,7 @@ describe 'the session', :type => :feature do expect(response).to be_success end it 'logs me in' do - login user.nick, user.password + login user expect(page).to_not have_selector('.alert-error') end it 'does not log me in with wrong password' do diff --git a/spec/support/session_helper.rb b/spec/support/session_helper.rb index c54d3362..66f7f19f 100644 --- a/spec/support/session_helper.rb +++ b/spec/support/session_helper.rb @@ -1,12 +1,10 @@ module SessionHelper - def login(nick=nil, password=nil) + def login(user=nil, password=nil) visit login_path - if nick.nil? - user = FactoryGirl.create :user - nick, password = user.nick, user.password - end + user = FactoryGirl.create :user if user.nil? + nick, password = user.nick, user.password if user.instance_of? ::User fill_in 'nick', :with => nick fill_in 'password', :with => password find('input[type=submit]').click From 0d33922ed9c6b05bccdeda41a9d39c0af9d929c0 Mon Sep 17 00:00:00 2001 From: wvengen Date: Wed, 24 Jul 2013 02:57:45 +0200 Subject: [PATCH 14/59] make integration spec work with javascript driver too --- Gemfile | 2 ++ Gemfile.lock | 10 ++++++++++ spec/spec_helper.rb | 17 ++++++++++++++++- spec/support/session_helper.rb | 6 +++++- 4 files changed, 33 insertions(+), 2 deletions(-) diff --git a/Gemfile b/Gemfile index 5f58bf54..8a38467c 100644 --- a/Gemfile +++ b/Gemfile @@ -71,4 +71,6 @@ group :development, :test do gem 'factory_girl_rails', '~> 4.0' gem 'faker' gem 'capybara' + gem 'poltergeist' + gem 'database_cleaner' end diff --git a/Gemfile.lock b/Gemfile.lock index 2ce2d80c..fa887893 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -90,6 +90,7 @@ GEM coffee-script-source (1.3.3) commonjs (0.2.6) daemons (1.1.9) + database_cleaner (0.7.1) diff-lcs (1.2.4) erubis (2.7.0) eventmachine (1.0.3) @@ -105,6 +106,8 @@ GEM railties (>= 3.0.0) faker (1.1.2) i18n (~> 0.5) + faye-websocket (0.4.7) + eventmachine (>= 0.12.0) ffi (1.4.0) haml (3.1.7) haml-rails (0.3.5) @@ -116,6 +119,7 @@ GEM hashery (2.0.1) highline (1.6.19) hike (1.2.1) + http_parser.rb (0.5.3) i18n (0.6.1) inherited_resources (1.3.1) has_scope (~> 0.5.0) @@ -168,6 +172,10 @@ GEM Ascii85 (~> 1.0.0) hashery (~> 2.0) ruby-rc4 + poltergeist (1.1.2) + capybara (~> 2.0.1) + faye-websocket (~> 0.4.4) + http_parser.rb (~> 0.5.3) polyamorous (0.5.0) activerecord (~> 3.0) polyglot (0.3.3) @@ -308,6 +316,7 @@ DEPENDENCIES client_side_validations coffee-rails (~> 3.2.1) daemons + database_cleaner exception_notification factory_girl_rails (~> 4.0) faker @@ -319,6 +328,7 @@ DEPENDENCIES mailcatcher meta_search mysql2 + poltergeist prawn quiet_assets rails (~> 3.2.9) diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 36cda713..5ebaa11f 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -6,6 +6,8 @@ require 'rspec/autorun' require 'capybara/rails' require 'capybara/rspec' +require 'capybara/poltergeist' +Capybara.javascript_driver = :poltergeist # Requires supporting ruby files with custom matchers and macros, etc, # in spec/support/ and its subdirectories. @@ -23,7 +25,15 @@ RSpec.configure do |config| # If you're not using ActiveRecord, or you'd prefer not to run each of your # examples within a transaction, remove the following line or assign false # instead of true. - config.use_transactional_fixtures = true + #config.use_transactional_fixtures = true + # We use capybara with selenium, and need database_cleaner + config.before(:each) do + DatabaseCleaner.strategy = (example.metadata[:js] ? :truncation : :transaction) + DatabaseCleaner.start + end + config.after(:each) do + DatabaseCleaner.clean + end # If true, the base class of anonymous controllers will be inferred # automatically. This will be the default behavior in future versions of @@ -57,3 +67,8 @@ ActionDispatch::Integration::Runner.class_eval do end end +# debug driver for tests requiring javascript +#Capybara.javascript_driver = :poltergeist_debug +#Capybara.register_driver :poltergeist_debug do |app| +# Capybara::Poltergeist::Driver.new(app, :debug => true, :inspector => true) +#end diff --git a/spec/support/session_helper.rb b/spec/support/session_helper.rb index 66f7f19f..dcfddeac 100644 --- a/spec/support/session_helper.rb +++ b/spec/support/session_helper.rb @@ -4,7 +4,11 @@ module SessionHelper def login(user=nil, password=nil) visit login_path user = FactoryGirl.create :user if user.nil? - nick, password = user.nick, user.password if user.instance_of? ::User + if user.instance_of? ::User + nick, password = user.nick, user.password + else + nick = user + end fill_in 'nick', :with => nick fill_in 'password', :with => password find('input[type=submit]').click From 8af04e01120281d0cbd6bf09f4ce51c9c47cca3e Mon Sep 17 00:00:00 2001 From: wvengen Date: Wed, 24 Jul 2013 04:04:59 +0200 Subject: [PATCH 15/59] add product distribution integration test --- .../product_distribution_example_spec.rb | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 spec/integration/product_distribution_example_spec.rb diff --git a/spec/integration/product_distribution_example_spec.rb b/spec/integration/product_distribution_example_spec.rb new file mode 100644 index 00000000..283be85e --- /dev/null +++ b/spec/integration/product_distribution_example_spec.rb @@ -0,0 +1,49 @@ +require 'spec_helper' + +describe 'product distribution', :type => :feature do + let(:admin) { FactoryGirl.create :admin } + let(:user_a) { FactoryGirl.create :user, groups: [FactoryGirl.create(:ordergroup)] } + let(:user_b) { FactoryGirl.create :user, groups: [FactoryGirl.create(:ordergroup)] } + let(:supplier) { FactoryGirl.create :supplier } + let(:article) { FactoryGirl.create :article, supplier: supplier, unit_quantity: 5 } + let(:order) { FactoryGirl.create(:order, supplier: supplier, article_ids: [article.id]) } + let(:oa) { order.order_articles.first } + + describe :type => :feature do + it 'agrees to documented example', :js => true do + # gruppe a bestellt 2(3), weil sie auf jeden fall was von x bekommen will + login user_a + visit new_group_order_path(:order_id => order.id) + find("[data-increase_quantity='#{oa.id}']").click + find("[data-increase_quantity='#{oa.id}']").click + find("[data-increase_tolerance='#{oa.id}']").click + find("[data-increase_tolerance='#{oa.id}']").click + find("[data-increase_tolerance='#{oa.id}']").click + find('input[type=submit]').click + # gruppe b bestellt 2(0) + login user_b + visit new_group_order_path(:order_id => order.id) + find("[data-increase_quantity='#{oa.id}']").click + find("[data-increase_quantity='#{oa.id}']").click + find('input[type=submit]').click + # gruppe a faellt ein dass sie doch noch mehr braucht von x und aendert auf 4(1). + login user_a + visit edit_group_order_path(order.group_order(user_a.ordergroup), :order_id => order.id) + find("[data-increase_quantity='#{oa.id}']").click + find("[data-increase_quantity='#{oa.id}']").click + find("[data-decrease_tolerance='#{oa.id}']").click + find("[data-decrease_tolerance='#{oa.id}']").click + # die zuteilung + order.close!(admin) + # Endstand: insg. Bestellt wurden 6(1) + expect(oa.result).to == 6 + # Gruppe a bekommt 3 einheiten. + goa_a = oa.group_order_articles.where(:ordergroup_id => user_a.ordergroup.id).first + expect(goa_a.result).to == 3 + # gruppe b bekommt 2 einheiten. + goa_b = oa.group_order_articles.where(:ordergroup_id => user_b.ordergroup.id).first + expect(goa_b.result).to == 2 + end + end + +end From 62682b7e640db9f961f507d412d4e734e8c2b4c9 Mon Sep 17 00:00:00 2001 From: wvengen Date: Wed, 24 Jul 2013 12:37:20 +0200 Subject: [PATCH 16/59] make integration test work --- Gemfile | 2 +- Gemfile.lock | 8 ----- spec/factories/user.rb | 3 ++ .../product_distribution_example_spec.rb | 34 +++++++++---------- spec/spec_helper.rb | 8 ----- 5 files changed, 21 insertions(+), 34 deletions(-) diff --git a/Gemfile b/Gemfile index 8a38467c..4f8cab3e 100644 --- a/Gemfile +++ b/Gemfile @@ -71,6 +71,6 @@ group :development, :test do gem 'factory_girl_rails', '~> 4.0' gem 'faker' gem 'capybara' - gem 'poltergeist' + # webkit and poltergeist don't seem to work yet gem 'database_cleaner' end diff --git a/Gemfile.lock b/Gemfile.lock index fa887893..09f0d284 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -106,8 +106,6 @@ GEM railties (>= 3.0.0) faker (1.1.2) i18n (~> 0.5) - faye-websocket (0.4.7) - eventmachine (>= 0.12.0) ffi (1.4.0) haml (3.1.7) haml-rails (0.3.5) @@ -119,7 +117,6 @@ GEM hashery (2.0.1) highline (1.6.19) hike (1.2.1) - http_parser.rb (0.5.3) i18n (0.6.1) inherited_resources (1.3.1) has_scope (~> 0.5.0) @@ -172,10 +169,6 @@ GEM Ascii85 (~> 1.0.0) hashery (~> 2.0) ruby-rc4 - poltergeist (1.1.2) - capybara (~> 2.0.1) - faye-websocket (~> 0.4.4) - http_parser.rb (~> 0.5.3) polyamorous (0.5.0) activerecord (~> 3.0) polyglot (0.3.3) @@ -328,7 +321,6 @@ DEPENDENCIES mailcatcher meta_search mysql2 - poltergeist prawn quiet_assets rails (~> 3.2.9) diff --git a/spec/factories/user.rb b/spec/factories/user.rb index 0453d3e1..6f7e9e4d 100644 --- a/spec/factories/user.rb +++ b/spec/factories/user.rb @@ -27,6 +27,9 @@ FactoryGirl.define do factory :ordergroup do type 'Ordergroup' sequence(:name) {|n| "Order group ##{n}"} + # workaround to avoid needing to save the ordergroup + # avoids e.g. error after logging in related to applebar + after :create do |group| Ordergroup.find(group.id).update_stats! end end end diff --git a/spec/integration/product_distribution_example_spec.rb b/spec/integration/product_distribution_example_spec.rb index 283be85e..4190bd87 100644 --- a/spec/integration/product_distribution_example_spec.rb +++ b/spec/integration/product_distribution_example_spec.rb @@ -14,35 +14,35 @@ describe 'product distribution', :type => :feature do # gruppe a bestellt 2(3), weil sie auf jeden fall was von x bekommen will login user_a visit new_group_order_path(:order_id => order.id) - find("[data-increase_quantity='#{oa.id}']").click - find("[data-increase_quantity='#{oa.id}']").click - find("[data-increase_tolerance='#{oa.id}']").click - find("[data-increase_tolerance='#{oa.id}']").click - find("[data-increase_tolerance='#{oa.id}']").click + 2.times { find("[data-increase_quantity='#{oa.id}']").click } + 3.times { find("[data-increase_tolerance='#{oa.id}']").click } find('input[type=submit]').click + expect(page).to have_selector('body') # gruppe b bestellt 2(0) login user_b visit new_group_order_path(:order_id => order.id) - find("[data-increase_quantity='#{oa.id}']").click - find("[data-increase_quantity='#{oa.id}']").click + 2.times { find("[data-increase_quantity='#{oa.id}']").click } find('input[type=submit]').click + expect(page).to have_selector('body') # gruppe a faellt ein dass sie doch noch mehr braucht von x und aendert auf 4(1). login user_a visit edit_group_order_path(order.group_order(user_a.ordergroup), :order_id => order.id) - find("[data-increase_quantity='#{oa.id}']").click - find("[data-increase_quantity='#{oa.id}']").click - find("[data-decrease_tolerance='#{oa.id}']").click - find("[data-decrease_tolerance='#{oa.id}']").click + 2.times { find("[data-increase_quantity='#{oa.id}']").click } + 2.times { find("[data-decrease_tolerance='#{oa.id}']").click } + find('input[type=submit]').click + expect(page).to have_selector('body') # die zuteilung - order.close!(admin) + order.finish!(admin) + oa.reload # Endstand: insg. Bestellt wurden 6(1) - expect(oa.result).to == 6 + expect(oa.quantity).to eq(6) + expect(oa.tolerance).to eq(1) # Gruppe a bekommt 3 einheiten. - goa_a = oa.group_order_articles.where(:ordergroup_id => user_a.ordergroup.id).first - expect(goa_a.result).to == 3 + 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.where(:ordergroup_id => user_b.ordergroup.id).first - expect(goa_b.result).to == 2 + 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/spec_helper.rb b/spec/spec_helper.rb index 5ebaa11f..7cf48c9c 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -6,8 +6,6 @@ require 'rspec/autorun' require 'capybara/rails' require 'capybara/rspec' -require 'capybara/poltergeist' -Capybara.javascript_driver = :poltergeist # Requires supporting ruby files with custom matchers and macros, etc, # in spec/support/ and its subdirectories. @@ -66,9 +64,3 @@ ActionDispatch::Integration::Runner.class_eval do {foodcoop: FoodsoftConfig.scope}.merge(options) end end - -# debug driver for tests requiring javascript -#Capybara.javascript_driver = :poltergeist_debug -#Capybara.register_driver :poltergeist_debug do |app| -# Capybara::Poltergeist::Driver.new(app, :debug => true, :inspector => true) -#end From 6da2fdee6d6a58e2f4a2f8285a201dce5f005e23 Mon Sep 17 00:00:00 2001 From: wvengen Date: Wed, 24 Jul 2013 13:21:52 +0200 Subject: [PATCH 17/59] add travis-ci configuration --- .travis.yml | 11 +++++++++++ lib/tasks/foodsoft_setup.rake | 9 +++++++++ 2 files changed, 20 insertions(+) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 00000000..7dd5cd81 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,11 @@ +language: ruby +rvm: + - 1.9.3 +services: + - redis-server +before_install: + - "export DISPLAY=:99.0" + - "sh -e /etc/init.d/xvfb start" + - "bundle exec rake foodsoft:setup:stock_config" + - 'printf "test:\r\n adapter:mysql2\r\n database:foodsoft_test\r\n username:travis\r\n encoding:utf8\r\n" >config/database.yml' +script: bundle exec rake spec diff --git a/lib/tasks/foodsoft_setup.rake b/lib/tasks/foodsoft_setup.rake index 6a239c63..5e7ba088 100644 --- a/lib/tasks/foodsoft_setup.rake +++ b/lib/tasks/foodsoft_setup.rake @@ -38,6 +38,15 @@ namespace :foodsoft do puts yellow "All done! Your foodcoft should be running smoothly." start_server end + + namespace :setup do + desc "Initialize stock configuration" + task :stock_config do + setup_app_config + setup_development + setup_secret_token + end + end end def setup_bundler From 23a08b2ac8f86fcca91724ff1265b16941a24697 Mon Sep 17 00:00:00 2001 From: wvengen Date: Wed, 24 Jul 2013 20:44:07 +0200 Subject: [PATCH 18/59] cleaner way to set foodcoop scope --- spec/spec_helper.rb | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 7cf48c9c..52b55af3 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -44,6 +44,11 @@ RSpec.configure do |config| # --seed 1234 config.order = "random" + config.before(:each) do + # include default foodsoft scope in urls, so that *_path works + default_url_options[:foodcoop] = FoodsoftConfig.scope + end + config.include(SessionHelper) end @@ -56,11 +61,3 @@ module Faker end end end - -# include default foodsoft scope in urls, so that *_path works -ActionDispatch::Integration::Runner.class_eval do - undef default_url_options - def default_url_options(options={}) - {foodcoop: FoodsoftConfig.scope}.merge(options) - end -end From a6114f137b7bf119eed05ddd4673dd8bf05f12cd Mon Sep 17 00:00:00 2001 From: wvengen Date: Wed, 24 Jul 2013 21:25:57 +0200 Subject: [PATCH 19/59] add order integration spec --- spec/integration/supplier_spec.rb | 63 +++++++++++++++++++++++++++++++ spec/spec_helper.rb | 2 +- 2 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 spec/integration/supplier_spec.rb diff --git a/spec/integration/supplier_spec.rb b/spec/integration/supplier_spec.rb new file mode 100644 index 00000000..c93a810c --- /dev/null +++ b/spec/integration/supplier_spec.rb @@ -0,0 +1,63 @@ +require 'spec_helper' + +describe 'supplier', :type => :feature do + let(:supplier) { FactoryGirl.create :supplier } + + describe :type => :feature, :js => true do + let(:user) { FactoryGirl.create :user, groups:[FactoryGirl.create(:workgroup, role_suppliers: true)] } + before { login user } + + it 'can be created' do + visit suppliers_path + click_on I18n.t('suppliers.index.action_new') + supplier = FactoryGirl.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 + find('input[type="submit"]').click + end + expect(page).to have_content(supplier.name) + end + + it 'is included in supplier list' do + supplier + visit suppliers_path + expect(page).to have_content(supplier.name) + end + end + + describe :type => :feature, :js => true do + let(:article_category) { FactoryGirl.create :article_category } + let(:user) { FactoryGirl.create :user, groups:[FactoryGirl.create(:workgroup, role_article_meta: true)] } + before { login user } + + it 'can visit supplier articles path' do + visit supplier_articles_path(supplier) + expect(page).to have_content(supplier.name) + expect(page).to have_content(I18n.t('articles.index.edit_all')) + end + + it 'can create a new article' do + article_category.save! + visit supplier_articles_path(supplier) + click_on I18n.t('articles.index.new') + expect(page).to have_selector('form#new_article') + article = FactoryGirl.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 + # "Element cannot be scrolled into view" error, js as workaround + #find('input[type="submit"]').click + page.execute_script('$("form#new_article").submit();') + end + expect(page).to have_content(article.name) + end + end + +end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 52b55af3..25e445bc 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -49,7 +49,7 @@ RSpec.configure do |config| default_url_options[:foodcoop] = FoodsoftConfig.scope end - config.include(SessionHelper) + config.include SessionHelper end module Faker From c1147306beb5f09f3d4a181872e727c2379a9a42 Mon Sep 17 00:00:00 2001 From: wvengen Date: Wed, 24 Jul 2013 21:28:42 +0200 Subject: [PATCH 20/59] fix travis.yml --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 7dd5cd81..0da7f171 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,6 +6,7 @@ services: before_install: - "export DISPLAY=:99.0" - "sh -e /etc/init.d/xvfb start" +before_script: - "bundle exec rake foodsoft:setup:stock_config" - 'printf "test:\r\n adapter:mysql2\r\n database:foodsoft_test\r\n username:travis\r\n encoding:utf8\r\n" >config/database.yml' script: bundle exec rake spec From 71d25c5ebb21ec78526f9f603a8bf218c6e73fc4 Mon Sep 17 00:00:00 2001 From: wvengen Date: Wed, 24 Jul 2013 21:40:36 +0200 Subject: [PATCH 21/59] travis.yml fix --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 0da7f171..5fddc935 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,5 +8,5 @@ before_install: - "sh -e /etc/init.d/xvfb start" before_script: - "bundle exec rake foodsoft:setup:stock_config" - - 'printf "test:\r\n adapter:mysql2\r\n database:foodsoft_test\r\n username:travis\r\n encoding:utf8\r\n" >config/database.yml' + - 'printf "test:\n adapter: mysql2\n database: foodsoft_test\n username: travis\n encoding: utf8\n" >config/database.yml' script: bundle exec rake spec From 63a0c0cff6dc638602563d06ee1a5cc35b684d76 Mon Sep 17 00:00:00 2001 From: wvengen Date: Wed, 24 Jul 2013 21:47:27 +0200 Subject: [PATCH 22/59] travis create database before running tests --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 5fddc935..42e88229 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,5 +8,6 @@ before_install: - "sh -e /etc/init.d/xvfb start" before_script: - "bundle exec rake foodsoft:setup:stock_config" + - "mysql -e 'create database foodsoft_test;'" - 'printf "test:\n adapter: mysql2\n database: foodsoft_test\n username: travis\n encoding: utf8\n" >config/database.yml' script: bundle exec rake spec From f0c831ccd989c456d6dcd620c3f5cddf726f32b1 Mon Sep 17 00:00:00 2001 From: wvengen Date: Wed, 24 Jul 2013 21:57:17 +0200 Subject: [PATCH 23/59] initialize database on travis --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 42e88229..3e24f134 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,4 +10,5 @@ before_script: - "bundle exec rake foodsoft:setup:stock_config" - "mysql -e 'create database foodsoft_test;'" - 'printf "test:\n adapter: mysql2\n database: foodsoft_test\n username: travis\n encoding: utf8\n" >config/database.yml' + - 'bundle exec rake db:schema:load RAILS_ENV=test' script: bundle exec rake spec From 0be3955cd77f16bb8f2dcdbaaad9be330213a43d Mon Sep 17 00:00:00 2001 From: wvengen Date: Wed, 24 Jul 2013 22:06:53 +0200 Subject: [PATCH 24/59] Revert "cleaner way to set foodcoop scope" This reverts commit 23a08b2ac8f86fcca91724ff1265b16941a24697. Conflicts: spec/spec_helper.rb --- spec/spec_helper.rb | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 25e445bc..69668880 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -44,11 +44,6 @@ RSpec.configure do |config| # --seed 1234 config.order = "random" - config.before(:each) do - # include default foodsoft scope in urls, so that *_path works - default_url_options[:foodcoop] = FoodsoftConfig.scope - end - config.include SessionHelper end @@ -61,3 +56,11 @@ module Faker end end end + +# include default foodsoft scope in urls, so that *_path works +ActionDispatch::Integration::Runner.class_eval do + undef default_url_options + def default_url_options(options={}) + {foodcoop: FoodsoftConfig.scope}.merge(options) + end +end From d602b7cd0d1c1a75ffdbb22b195dc065710fb7a0 Mon Sep 17 00:00:00 2001 From: wvengen Date: Wed, 24 Jul 2013 22:46:25 +0200 Subject: [PATCH 25/59] use expect instead of should in specs --- spec/models/article_spec.rb | 22 +++++++-------- spec/models/group_order_article_spec.rb | 28 +++++++++---------- spec/models/group_order_spec.rb | 6 ++--- spec/models/order_spec.rb | 24 ++++++++--------- spec/models/supplier_spec.rb | 4 +-- spec/models/user_spec.rb | 36 ++++++++++++------------- 6 files changed, 60 insertions(+), 60 deletions(-) diff --git a/spec/models/article_spec.rb b/spec/models/article_spec.rb index 5df322a3..8fa6723a 100644 --- a/spec/models/article_spec.rb +++ b/spec/models/article_spec.rb @@ -6,39 +6,39 @@ describe Article do it 'has a unique name' do article2 = FactoryGirl.build :article, supplier: supplier, name: article.name - article2.should_not be_valid + expect(article2).to be_invalid end it 'computes the gross price correctly' do article.deposit = 0 article.tax = 12 - article.gross_price.should == (article.price * 1.12).round(2) + expect(article.gross_price).to eq((article.price * 1.12).round(2)) article.deposit = 1.20 - article.gross_price.should == ((article.price + 1.20) * 1.12).round(2) + expect(article.gross_price).to eq(((article.price + 1.20) * 1.12).round(2)) end it 'gross price >= net price' do - article.gross_price.should >= article.price + expect(article.gross_price).to be >= article.price end it 'fc-price > gross price' do - article.fc_price.should > article.gross_price + expect(article.fc_price).to be > article.gross_price end it 'knows when it is deleted' do - supplier.deleted?.should be_false + expect(supplier.deleted?).to be_false supplier.mark_as_deleted - supplier.deleted?.should be_true + expect(supplier.deleted?).to be_true end it 'keeps a price history' do - article.article_prices.count.should == 1 + expect(article.article_prices.count).to eq(1) oldprice = article.price article.price += 1 article.save! - article.article_prices.count.should == 2 - article.article_prices[0].price.should == article.price - article.article_prices[-1].price.should == oldprice + expect(article.article_prices.count).to eq(2) + expect(article.article_prices[0].price).to eq(article.price) + expect(article.article_prices[-1].price).to eq(oldprice) end end diff --git a/spec/models/group_order_article_spec.rb b/spec/models/group_order_article_spec.rb index e9b9046f..84e5627f 100644 --- a/spec/models/group_order_article_spec.rb +++ b/spec/models/group_order_article_spec.rb @@ -7,11 +7,11 @@ describe GroupOrderArticle do let(:go) { FactoryGirl.create :group_order, order: order, ordergroup: user.ordergroup } let(:goa) { FactoryGirl.create :group_order_article, group_order: go, order_article: order.order_articles.first } - it 'has zero quantity by default' do goa.quantity.should == 0 end - it 'has zero tolerance by default' do goa.tolerance.should == 0 end - it 'has zero result by default' do goa.result.should == 0 end - it 'is not ordered by default' do GroupOrderArticle.ordered.where(:id => goa.id).exists?.should be_false end - it 'has zero total price by default' do goa.total_price.should == 0 end + 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 + it 'has zero result by default' do expect(goa.result).to eq(0) end + it 'is not ordered by default' do expect(GroupOrderArticle.ordered.where(:id => goa.id).exists?).to be_false end + it 'has zero total price by default' do expect(goa.total_price).to eq(0) end describe do let(:article) { FactoryGirl.create :article, supplier: supplier, unit_quantity: 1 } @@ -19,28 +19,28 @@ describe GroupOrderArticle do it 'can be ordered by piece' do goa.update_quantities(1, 0) - goa.quantity.should == 1 - goa.tolerance == 0 + expect(goa.quantity).to eq(1) + expect(goa.tolerance).to eq(0) end it 'can be ordered in larger amounts' do quantity, tolerance = rand(13..100), rand(0..100) goa.update_quantities(quantity, tolerance) - goa.quantity.should == quantity - goa.tolerance.should == tolerance + expect(goa.quantity).to eq(quantity) + expect(goa.tolerance).to eq(tolerance) end it 'has a proper total price' do quantity = rand(1..100) goa.update_quantities(quantity, 0) - goa.total_price.should == quantity * goa.order_article.price.fc_price + expect(goa.total_price).to eq(quantity * goa.order_article.price.fc_price) end it 'can unorder a product' do goa.update_quantities(rand(1..100), rand(0..100)) goa.update_quantities(0, 0) - goa.quantity.should == 0 - goa.tolerance.should == 0 + expect(goa.quantity).to eq(0) + expect(goa.tolerance).to eq(0) end it 'keeps track of article quantities' do @@ -53,8 +53,8 @@ describe GroupOrderArticle do startt.nil? and startt = tolerance end goaq = goa.group_order_article_quantities.last - goaq.quantity.should == startq - goaq.tolerance.should == startt + expect(goaq.quantity).to eq(startq) + expect(goaq.tolerance).to eq(startt) end end diff --git a/spec/models/group_order_spec.rb b/spec/models/group_order_spec.rb index 5c2138dd..cfde0f64 100644 --- a/spec/models/group_order_spec.rb +++ b/spec/models/group_order_spec.rb @@ -6,18 +6,18 @@ describe GroupOrder do let(:order) { FactoryGirl.create(:order, supplier: supplier, article_ids: supplier.articles.map(&:id)).reload } it 'needs an order' do - FactoryGirl.build(:group_order, ordergroup: user.ordergroup).should_not be_valid + expect(FactoryGirl.build(:group_order, ordergroup: user.ordergroup)).to be_invalid end it 'needs an ordergroup' do - FactoryGirl.build(:group_order, order: order).should_not be_valid + expect(FactoryGirl.build(:group_order, order: order)).to be_invalid end describe do let(:go) { FactoryGirl.create :group_order, order: order, ordergroup: user.ordergroup } it 'has zero price initially' do - go.price.should == 0 + expect(go.price).to eq(0) end end diff --git a/spec/models/order_spec.rb b/spec/models/order_spec.rb index 0d7a1d9f..486996a5 100644 --- a/spec/models/order_spec.rb +++ b/spec/models/order_spec.rb @@ -3,45 +3,45 @@ require 'spec_helper' describe Order do it 'needs a supplier' do - FactoryGirl.build(:order).should_not be_valid + expect(FactoryGirl.build(:order)).to be_invalid end it 'needs order articles' do supplier = FactoryGirl.create :supplier, article_count: 0 - FactoryGirl.build(:order, supplier: supplier).should_not be_valid + expect(FactoryGirl.build(:order, supplier: supplier)).to be_invalid end it 'can be created' do supplier = FactoryGirl.create :supplier, article_count: 1 - FactoryGirl.build(:order, supplier: supplier, article_ids: supplier.articles.map(&:id)).should be_valid + expect(FactoryGirl.build(:order, supplier: supplier, article_ids: supplier.articles.map(&:id))).to be_valid end describe 'with articles' do let(:supplier) { FactoryGirl.create :supplier, article_count: true } let(:order) { FactoryGirl.create(:order, supplier: supplier, article_ids: supplier.articles.map(&:id)).reload } - it 'is open by default' do order.open?.should be_true end - it 'is not finished by default' do order.finished?.should be_false end - it 'is not closed by default' do order.closed?.should be_false end + 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 'has valid order articles' do - order.order_articles.all.each {|oa| oa.should be_valid } + order.order_articles.all.each {|oa| expect(oa).to be_valid } end it 'can be finished' do # TODO randomise user order.finish!(User.first) - order.open?.should be_false - order.finished?.should be_true - order.closed?.should be_false + expect(order).to_not be_open + expect(order).to be_finished + expect(order).to_not be_closed end it 'can be closed' do # TODO randomise user order.finish!(User.first) order.close!(User.first) - order.open?.should be_false - order.closed?.should be_true + expect(order).to_not be_open + expect(order).to be_closed end end diff --git a/spec/models/supplier_spec.rb b/spec/models/supplier_spec.rb index 3457e2da..db01b148 100644 --- a/spec/models/supplier_spec.rb +++ b/spec/models/supplier_spec.rb @@ -5,12 +5,12 @@ describe Supplier do it 'has a unique name' do supplier2 = FactoryGirl.build :supplier, name: supplier.name - supplier2.should_not be_valid + expect(supplier2).to be_invalid end it 'has valid articles' do supplier = FactoryGirl.create :supplier, article_count: true - supplier.articles.all.each {|a| a.should be_valid } + supplier.articles.all.each {|a| expect(a).to be_valid } end end diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 91e4abe7..d679bea8 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -6,54 +6,54 @@ describe User do user = FactoryGirl.create :user, nick: 'johnnydoe', first_name: 'Johnny', last_name: 'DoeBar', email: 'johnnydoe@foodcoop.test', phone: '+1234567890' - user.nick.should == 'johnnydoe' - user.first_name.should == 'Johnny' - user.last_name.should == 'DoeBar' - user.name.should == 'Johnny DoeBar' - user.email.should == 'johnnydoe@foodcoop.test' - user.phone.should == '+1234567890' + expect(user.nick).to eq('johnnydoe') + expect(user.first_name).to eq('Johnny') + expect(user.last_name).to eq('DoeBar') + expect(user.name).to eq('Johnny DoeBar') + expect(user.email).to eq('johnnydoe@foodcoop.test') + expect(user.phone).to eq('+1234567890') end describe 'does not have the role' do let(:user) { FactoryGirl.create :user } - it 'admin' do user.role_admin?.should be_false end - it 'finance' do user.role_finance?.should be_false end - it 'article_meta' do user.role_article_meta?.should be_false end - it 'suppliers' do user.role_suppliers?.should be_false end - it 'orders' do user.role_orders?.should be_false end + it 'admin' do expect(user.role_admin?).to be_false end + it 'finance' do expect(user.role_finance?).to be_false end + it 'article_meta' do expect(user.role_article_meta?).to be_false end + it 'suppliers' do expect(user.role_suppliers?).to be_false end + it 'orders' do expect(user.role_orders?).to be_false end end describe do let(:user) { FactoryGirl.create :user, password: 'blahblah' } it 'can authenticate with correct password' do - User.authenticate(user.nick, 'blahblah').should be_true + expect(User.authenticate(user.nick, 'blahblah')).to be_true end it 'can not authenticate with incorrect password' do - User.authenticate(user.nick, 'foobar').should be_nil + expect(User.authenticate(user.nick, 'foobar')).to be_nil end it 'can not set a password without matching confirmation' do user.password = 'abcdefghij' user.password_confirmation = 'foobarxyz' - user.should_not be_valid + expect(user).to be_invalid end it 'can set a password with matching confirmation' do user.password = 'abcdefghij' user.password_confirmation = 'abcdefghij' - user.should be_valid + expect(user).to be_valid end it 'has a unique nick' do - FactoryGirl.build(:user, nick: user.nick, email: "x-#{user.email}").should_not be_valid + expect(FactoryGirl.build(:user, nick: user.nick, email: "x-#{user.email}")).to be_invalid end it 'has a unique email' do - FactoryGirl.build(:user, email: "#{user.email}").should_not be_valid + expect(FactoryGirl.build(:user, email: "#{user.email}")).to be_invalid end end describe 'admin' do let(:user) { FactoryGirl.create :admin } - it 'default admin role' do user.role_admin?.should be_true end + it 'default admin role' do expect(user.role_admin?).to be_true end end end From ebf71ad494b35a808ba4d29540ac843295974de7 Mon Sep 17 00:00:00 2001 From: wvengen Date: Thu, 25 Jul 2013 00:01:58 +0200 Subject: [PATCH 26/59] fix price history spec --- spec/models/article_spec.rb | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/spec/models/article_spec.rb b/spec/models/article_spec.rb index 8fa6723a..884c5ab7 100644 --- a/spec/models/article_spec.rb +++ b/spec/models/article_spec.rb @@ -32,13 +32,12 @@ describe Article do end it 'keeps a price history' do - expect(article.article_prices.count).to eq(1) + expect(article.article_prices.all.map(&:price)).to eq([article.price]) oldprice = article.price + sleep 1 # so that the new price really has a later creation time article.price += 1 article.save! - expect(article.article_prices.count).to eq(2) - expect(article.article_prices[0].price).to eq(article.price) - expect(article.article_prices[-1].price).to eq(oldprice) + expect(article.article_prices.all.map(&:price)).to eq([article.price, oldprice]) end end From 1e986e704aa2e4767e035c4d072d11cbd26f7b94 Mon Sep 17 00:00:00 2001 From: wvengen Date: Thu, 25 Jul 2013 00:07:39 +0200 Subject: [PATCH 27/59] remove spec test that is broken and not really useful --- spec/models/group_order_article_spec.rb | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/spec/models/group_order_article_spec.rb b/spec/models/group_order_article_spec.rb index 84e5627f..c20542a7 100644 --- a/spec/models/group_order_article_spec.rb +++ b/spec/models/group_order_article_spec.rb @@ -43,20 +43,6 @@ describe GroupOrderArticle do expect(goa.tolerance).to eq(0) end - it 'keeps track of article quantities' do - startq = startt = nil - for i in 0..6 do - goa.group_order_article_quantities.count == i - quantity, tolerance = rand(1..100), rand(0..100) - goa.update_quantities(quantity, tolerance) - startq.nil? and startq = quantity - startt.nil? and startt = tolerance - end - goaq = goa.group_order_article_quantities.last - expect(goaq.quantity).to eq(startq) - expect(goaq.tolerance).to eq(startt) - end - end end From 06d39f52ca0239de04adb0955e43bc3bd59a2dc2 Mon Sep 17 00:00:00 2001 From: wvengen Date: Thu, 25 Jul 2013 00:35:42 +0200 Subject: [PATCH 28/59] try to fix integration spec on travis --- spec/integration/product_distribution_example_spec.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/spec/integration/product_distribution_example_spec.rb b/spec/integration/product_distribution_example_spec.rb index 4190bd87..ce0cee83 100644 --- a/spec/integration/product_distribution_example_spec.rb +++ b/spec/integration/product_distribution_example_spec.rb @@ -26,6 +26,7 @@ describe 'product distribution', :type => :feature do expect(page).to have_selector('body') # gruppe a faellt ein dass sie doch noch mehr braucht von x und aendert auf 4(1). login user_a + order.reload # to make sure all group_order changes are included visit edit_group_order_path(order.group_order(user_a.ordergroup), :order_id => order.id) 2.times { find("[data-increase_quantity='#{oa.id}']").click } 2.times { find("[data-decrease_tolerance='#{oa.id}']").click } From 9a12ea9efc3cb9e52a3d02827226a33fe45b1005 Mon Sep 17 00:00:00 2001 From: wvengen Date: Thu, 25 Jul 2013 00:52:41 +0200 Subject: [PATCH 29/59] fix uniquess spec problems --- spec/factories/article.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/factories/article.rb b/spec/factories/article.rb index 04144b24..19f41529 100644 --- a/spec/factories/article.rb +++ b/spec/factories/article.rb @@ -3,7 +3,7 @@ require 'factory_girl' FactoryGirl.define do factory :article do - name { Faker::Lorem.words(rand(2..5)).join(' ') } + sequence(:name) { |n| Faker::Lorem.words(rand(2..4)).join(' ') + " ##{n}" } unit { Faker::Unit.unit } price { rand(2600) / 100 } tax { [6, 21].sample } @@ -14,7 +14,7 @@ FactoryGirl.define do end factory :article_category do - name { Faker::Lorem.characters(rand(2..20)) } + sequence(:name) { |n| Faker::Lorem.characters(rand(2..12)) + " ##{n}" } end end From c753ae04715fe577559dd6530f7601f07a8fde78 Mon Sep 17 00:00:00 2001 From: wvengen Date: Thu, 25 Jul 2013 01:07:41 +0200 Subject: [PATCH 30/59] comment tests that are unclear how they should behave --- spec/models/group_order_spec.rb | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/spec/models/group_order_spec.rb b/spec/models/group_order_spec.rb index cfde0f64..ebb0eae4 100644 --- a/spec/models/group_order_spec.rb +++ b/spec/models/group_order_spec.rb @@ -5,13 +5,15 @@ describe GroupOrder do let(:supplier) { FactoryGirl.create :supplier, article_count: true } let(:order) { FactoryGirl.create(:order, supplier: supplier, article_ids: supplier.articles.map(&:id)).reload } - it 'needs an order' do - expect(FactoryGirl.build(:group_order, ordergroup: user.ordergroup)).to be_invalid - end + # the following two tests are currently disabled - https://github.com/foodcoops/foodsoft/issues/158 - it 'needs an ordergroup' do - expect(FactoryGirl.build(:group_order, order: order)).to be_invalid - end + #it 'needs an order' do + # expect(FactoryGirl.build(:group_order, ordergroup: user.ordergroup)).to be_invalid + #end + + #it 'needs an ordergroup' do + # expect(FactoryGirl.build(:group_order, order: order)).to be_invalid + #end describe do let(:go) { FactoryGirl.create :group_order, order: order, ordergroup: user.ordergroup } From e9ed6f8c0f2544c77a7c9404ed16d53301f6c387 Mon Sep 17 00:00:00 2001 From: wvengen Date: Thu, 25 Jul 2013 01:25:08 +0200 Subject: [PATCH 31/59] Revert "try to fix integration spec on travis" This reverts commit 06d39f52ca0239de04adb0955e43bc3bd59a2dc2. --- spec/integration/product_distribution_example_spec.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/spec/integration/product_distribution_example_spec.rb b/spec/integration/product_distribution_example_spec.rb index ce0cee83..4190bd87 100644 --- a/spec/integration/product_distribution_example_spec.rb +++ b/spec/integration/product_distribution_example_spec.rb @@ -26,7 +26,6 @@ describe 'product distribution', :type => :feature do expect(page).to have_selector('body') # gruppe a faellt ein dass sie doch noch mehr braucht von x und aendert auf 4(1). login user_a - order.reload # to make sure all group_order changes are included visit edit_group_order_path(order.group_order(user_a.ordergroup), :order_id => order.id) 2.times { find("[data-increase_quantity='#{oa.id}']").click } 2.times { find("[data-decrease_tolerance='#{oa.id}']").click } From b302cbde4f66514e9079a6a871327a8c8113309a Mon Sep 17 00:00:00 2001 From: wvengen Date: Thu, 25 Jul 2013 09:42:29 +0200 Subject: [PATCH 32/59] make sure price spec works when price is zero --- spec/models/article_spec.rb | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/spec/models/article_spec.rb b/spec/models/article_spec.rb index 884c5ab7..45b802b4 100644 --- a/spec/models/article_spec.rb +++ b/spec/models/article_spec.rb @@ -21,8 +21,12 @@ describe Article do expect(article.gross_price).to be >= article.price end - it 'fc-price > gross price' do - expect(article.fc_price).to be > article.gross_price + it 'fc-price >= gross price' do + if article.gross_price > 0 + expect(article.fc_price).to be > article.gross_price + else + expect(article.fc_price).to be >= article.gross_price + end end it 'knows when it is deleted' do From 7dafcf714a6a5496193857afe1effe214a38ba40 Mon Sep 17 00:00:00 2001 From: wvengen Date: Thu, 25 Jul 2013 11:16:39 +0200 Subject: [PATCH 33/59] spec move functionality into factory --- spec/factories/order.rb | 15 ++++++++++++++- spec/models/group_order_article_spec.rb | 8 ++++---- spec/models/group_order_spec.rb | 3 +-- spec/models/order_spec.rb | 8 +++----- 4 files changed, 22 insertions(+), 12 deletions(-) diff --git a/spec/factories/order.rb b/spec/factories/order.rb index ac2182b5..27af29d6 100644 --- a/spec/factories/order.rb +++ b/spec/factories/order.rb @@ -2,12 +2,25 @@ require 'factory_girl' FactoryGirl.define do - # requires articles from single supplier, or supplier (with all its articles) factory :order do starts { Time.now } + supplier { FactoryGirl.create :supplier, article_count: (article_count.nil? ? true : article_count) } + article_ids { supplier.articles.map(&:id) unless supplier.nil? } + ignore do + article_count true + end + + # for an order from stock; need to add articles factory :stock_order do supplier_id 0 + # article_ids needs to be supplied + end + + # In the order's after_save callback order articles are created, so + # until the order is saved, these articles do not yet exist. + after :create do |order| + order.reload end end diff --git a/spec/models/group_order_article_spec.rb b/spec/models/group_order_article_spec.rb index c20542a7..759e2afc 100644 --- a/spec/models/group_order_article_spec.rb +++ b/spec/models/group_order_article_spec.rb @@ -2,8 +2,7 @@ require 'spec_helper' describe GroupOrderArticle do let(:user) { FactoryGirl.create :user, groups: [FactoryGirl.create(:ordergroup)] } - let(:supplier) { FactoryGirl.create :supplier, article_count: true } - let(:order) { FactoryGirl.create(:order, supplier: supplier, article_ids: supplier.articles.map(&:id)).reload } + let(:order) { FactoryGirl.create(:order).reload } let(:go) { FactoryGirl.create :group_order, order: order, ordergroup: user.ordergroup } let(:goa) { FactoryGirl.create :group_order_article, group_order: go, order_article: order.order_articles.first } @@ -14,8 +13,9 @@ describe GroupOrderArticle do it 'has zero total price by default' do expect(goa.total_price).to eq(0) end describe do - let(:article) { FactoryGirl.create :article, supplier: supplier, unit_quantity: 1 } - let(:goa) { article; FactoryGirl.create :group_order_article, group_order: go, order_article: order.order_articles.find_by_article_id(article.id) } + let(:article) { FactoryGirl.create :article, supplier: order.supplier, unit_quantity: 1 } + let(:oa) { order.order_articles.create(:article => article) } + let(:goa) { FactoryGirl.create :group_order_article, group_order: go, order_article: oa } it 'can be ordered by piece' do goa.update_quantities(1, 0) diff --git a/spec/models/group_order_spec.rb b/spec/models/group_order_spec.rb index ebb0eae4..04f69c33 100644 --- a/spec/models/group_order_spec.rb +++ b/spec/models/group_order_spec.rb @@ -2,8 +2,7 @@ require 'spec_helper' describe GroupOrder do let(:user) { FactoryGirl.create :user, groups: [FactoryGirl.create(:ordergroup)] } - let(:supplier) { FactoryGirl.create :supplier, article_count: true } - let(:order) { FactoryGirl.create(:order, supplier: supplier, article_ids: supplier.articles.map(&:id)).reload } + let(:order) { FactoryGirl.create :order } # the following two tests are currently disabled - https://github.com/foodcoops/foodsoft/issues/158 diff --git a/spec/models/order_spec.rb b/spec/models/order_spec.rb index 486996a5..4a8b7ebc 100644 --- a/spec/models/order_spec.rb +++ b/spec/models/order_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' describe Order do it 'needs a supplier' do - expect(FactoryGirl.build(:order)).to be_invalid + expect(FactoryGirl.build(:order, supplier: nil)).to be_invalid end it 'needs order articles' do @@ -12,13 +12,11 @@ describe Order do end it 'can be created' do - supplier = FactoryGirl.create :supplier, article_count: 1 - expect(FactoryGirl.build(:order, supplier: supplier, article_ids: supplier.articles.map(&:id))).to be_valid + expect(FactoryGirl.build(:order, article_count: 1)).to be_valid end describe 'with articles' do - let(:supplier) { FactoryGirl.create :supplier, article_count: true } - let(:order) { FactoryGirl.create(:order, supplier: supplier, article_ids: supplier.articles.map(&:id)).reload } + let(:order) { FactoryGirl.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 From 50f5064d8e75c5b470fc989125bd2d78174dde69 Mon Sep 17 00:00:00 2001 From: wvengen Date: Thu, 25 Jul 2013 13:08:38 +0200 Subject: [PATCH 34/59] fix product distribution integration test --- spec/factories/group_order.rb | 3 ++- spec/integration/product_distribution_example_spec.rb | 8 ++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/spec/factories/group_order.rb b/spec/factories/group_order.rb index ed6b6017..0b9983e6 100644 --- a/spec/factories/group_order.rb +++ b/spec/factories/group_order.rb @@ -2,8 +2,9 @@ require 'factory_girl' FactoryGirl.define do - # requires order and ordergroup + # requires order factory :group_order do + ordergroup { FactoryGirl.create(:user, groups: [FactoryGirl.create(:ordergroup)]).ordergroup } end end diff --git a/spec/integration/product_distribution_example_spec.rb b/spec/integration/product_distribution_example_spec.rb index 4190bd87..12fd84f5 100644 --- a/spec/integration/product_distribution_example_spec.rb +++ b/spec/integration/product_distribution_example_spec.rb @@ -10,6 +10,14 @@ describe 'product distribution', :type => :feature do let(:oa) { order.order_articles.first } describe :type => :feature do + # make sure users have enough money to order + before do + [user_a, user_b].each do |user| + ordergroup = Ordergroup.find(user.ordergroup.id) + ordergroup.add_financial_transaction! 5000, 'for ordering', admin + end + end + it 'agrees to documented example', :js => true do # gruppe a bestellt 2(3), weil sie auf jeden fall was von x bekommen will login user_a From 0f01b87e3b250651b018620d8472b7842e8c27b1 Mon Sep 17 00:00:00 2001 From: wvengen Date: Thu, 25 Jul 2013 13:21:24 +0200 Subject: [PATCH 35/59] do not exceed 99 articles when ordering in specs --- spec/factories/order.rb | 4 ++++ spec/factories/supplier.rb | 2 +- spec/models/group_order_article_spec.rb | 6 +++--- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/spec/factories/order.rb b/spec/factories/order.rb index 27af29d6..f3bf1bde 100644 --- a/spec/factories/order.rb +++ b/spec/factories/order.rb @@ -24,4 +24,8 @@ FactoryGirl.define do end end + # requires order and article + factory :order_article do + end + end diff --git a/spec/factories/supplier.rb b/spec/factories/supplier.rb index fdb2fa03..e4a1c18b 100644 --- a/spec/factories/supplier.rb +++ b/spec/factories/supplier.rb @@ -13,7 +13,7 @@ FactoryGirl.define do after :create do |supplier, evaluator| article_count = evaluator.article_count - article_count = rand(1..100) if article_count == true + article_count = rand(1..99) if article_count == true FactoryGirl.create_list :article, article_count, supplier: supplier end end diff --git a/spec/models/group_order_article_spec.rb b/spec/models/group_order_article_spec.rb index 759e2afc..160b312f 100644 --- a/spec/models/group_order_article_spec.rb +++ b/spec/models/group_order_article_spec.rb @@ -24,20 +24,20 @@ describe GroupOrderArticle do end it 'can be ordered in larger amounts' do - quantity, tolerance = rand(13..100), rand(0..100) + quantity, tolerance = rand(13..99), rand(0..99) goa.update_quantities(quantity, tolerance) expect(goa.quantity).to eq(quantity) expect(goa.tolerance).to eq(tolerance) end it 'has a proper total price' do - quantity = rand(1..100) + quantity = rand(1..99) goa.update_quantities(quantity, 0) expect(goa.total_price).to eq(quantity * goa.order_article.price.fc_price) end it 'can unorder a product' do - goa.update_quantities(rand(1..100), rand(0..100)) + goa.update_quantities(rand(1..99), rand(0..99)) goa.update_quantities(0, 0) expect(goa.quantity).to eq(0) expect(goa.tolerance).to eq(0) From 7c65995b623cb3a25b679b7bd021aa4c0621ce1f Mon Sep 17 00:00:00 2001 From: wvengen Date: Thu, 25 Jul 2013 13:31:59 +0200 Subject: [PATCH 36/59] add travis to README [ci skip] --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 7f447972..e74ea2e8 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,7 @@ We changed the branch structure. The rails3 branch is now master. But you can sa FoodSoft ========= +[![Build Status](https://travis-ci.org/foodcoops/foodsoft.png?branch=tests-rspec)](https://travis-ci.org/foodcoops/foodsoft) [![Code Climate](https://codeclimate.com/github/foodcoops/foodsoft.png)](https://codeclimate.com/github/foodcoops/foodsoft) [![Dependency Status](https://gemnasium.com/foodcoops/foodsoft.png)](https://gemnasium.com/foodcoops/foodsoft) From ca500062350bab06bcfaf22b627ea00f915145e9 Mon Sep 17 00:00:00 2001 From: wvengen Date: Thu, 25 Jul 2013 13:59:55 +0200 Subject: [PATCH 37/59] add coverage report, set COVERAGE=1 in env when running specs --- Gemfile | 1 + Gemfile.lock | 5 +++++ spec/spec_helper.rb | 1 + spec/support/coverage.rb | 14 ++++++++++++++ 4 files changed, 21 insertions(+) create mode 100644 spec/support/coverage.rb diff --git a/Gemfile b/Gemfile index 4a10aac9..2e4afaa1 100644 --- a/Gemfile +++ b/Gemfile @@ -76,6 +76,7 @@ group :development, :test do gem 'capybara' # webkit and poltergeist don't seem to work yet gem 'database_cleaner' + gem 'simplecov', require: false end # Gems left for backwards compatibility diff --git a/Gemfile.lock b/Gemfile.lock index 0c643e7d..2faaccac 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -251,6 +251,10 @@ GEM simple_form (2.1.0) actionpack (~> 3.0) activemodel (~> 3.0) + simplecov (0.7.1) + multi_json (~> 1.0) + simplecov-html (~> 0.7.1) + simplecov-html (0.7.1) sinatra (1.3.6) rack (~> 1.4) rack-protection (~> 1.3) @@ -339,6 +343,7 @@ DEPENDENCIES simple-navigation simple-navigation-bootstrap simple_form + simplecov sqlite3 therubyracer thin diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 69668880..1324abca 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,5 +1,6 @@ # This file is copied to spec/ when you run 'rails generate rspec:install' ENV["RAILS_ENV"] ||= 'test' +require 'support/coverage' # needs to be first require File.expand_path("../../config/environment", __FILE__) require 'rspec/rails' require 'rspec/autorun' diff --git a/spec/support/coverage.rb b/spec/support/coverage.rb new file mode 100644 index 00000000..c67e3172 --- /dev/null +++ b/spec/support/coverage.rb @@ -0,0 +1,14 @@ +# optional test coverage +# needs to be loaded first, e.g. add a require at top of spec_helper +if ENV['COVERAGE'] + require 'simplecov' + SimpleCov.start do + add_filter '/spec/' + add_filter '/test/' + add_group 'Models', '/app/models/' + add_group 'Controllers', '/app/controllers/' + add_group 'Helpers', '/app/helpers/' + add_group 'Documents', '/app/documents/' + add_group 'Libraries', '/lib/' + end +end From eac8260b381999bf64917d3fe8a3afdf891698ce Mon Sep 17 00:00:00 2001 From: wvengen Date: Thu, 25 Jul 2013 14:46:25 +0200 Subject: [PATCH 38/59] add i18n tests --- Gemfile | 7 +++++++ Gemfile.lock | 7 +++++++ spec/i18n_spec.rb | 12 ++++++++++++ 3 files changed, 26 insertions(+) create mode 100644 spec/i18n_spec.rb diff --git a/Gemfile b/Gemfile index 2e4afaa1..ba7bd657 100644 --- a/Gemfile +++ b/Gemfile @@ -70,6 +70,9 @@ end group :development, :test do gem 'ruby-prof' +end + +group :test do gem 'rspec-rails' gem 'factory_girl_rails', '~> 4.0' gem 'faker' @@ -77,6 +80,10 @@ group :development, :test do # webkit and poltergeist don't seem to work yet gem 'database_cleaner' gem 'simplecov', require: false + # need to include rspec components before i18n-spec or rake fails in test environment + gem 'rspec-core' + gem 'rspec-expectations' + gem 'i18n-spec' end # Gems left for backwards compatibility diff --git a/Gemfile.lock b/Gemfile.lock index 2faaccac..f6c33e69 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -118,9 +118,13 @@ GEM highline (1.6.19) hike (1.2.3) i18n (0.6.1) + i18n-spec (0.4.0) + iso inherited_resources (1.3.1) has_scope (~> 0.5.0) responders (~> 0.6) + iso (0.2.0) + i18n journey (1.0.4) jquery-rails (2.1.3) railties (>= 3.1.0, < 5.0) @@ -324,6 +328,7 @@ DEPENDENCIES factory_girl_rails (~> 4.0) faker haml-rails + i18n-spec inherited_resources jquery-rails kaminari @@ -336,6 +341,8 @@ DEPENDENCIES rails (~> 3.2.9) rails-settings-cached (= 0.2.4) resque + rspec-core + rspec-expectations rspec-rails ruby-prof sass-rails (~> 3.2.3) diff --git a/spec/i18n_spec.rb b/spec/i18n_spec.rb new file mode 100644 index 00000000..e07d74b9 --- /dev/null +++ b/spec/i18n_spec.rb @@ -0,0 +1,12 @@ +require 'spec_helper' +require 'i18n-spec' + +Dir.glob('config/locales/*.yml').each do |locale_file| + describe "#{locale_file}" do + it_behaves_like 'a valid locale file', locale_file + # We're currently allowing both German and English as source language + # besides, we're using localeapp, so that it's ok if pull requests + # don't have this - a localapp pull will fix that right away. + #it { expect(locale_file).to be_a_subset_of 'config/locales/en.yml' } + end +end From 37e5b0c25cab67d60ab14a63bb6ad9320af3f55b Mon Sep 17 00:00:00 2001 From: wvengen Date: Fri, 26 Jul 2013 18:34:03 +0200 Subject: [PATCH 39/59] add balancing integration spec --- app/views/finance/balancing/new.html.haml | 2 +- spec/integration/balancing_spec.rb | 55 +++++++++++++++++++++++ 2 files changed, 56 insertions(+), 1 deletion(-) create mode 100644 spec/integration/balancing_spec.rb diff --git a/app/views/finance/balancing/new.html.haml b/app/views/finance/balancing/new.html.haml index 7384f50a..b8f08129 100644 --- a/app/views/finance/balancing/new.html.haml +++ b/app/views/finance/balancing/new.html.haml @@ -12,7 +12,7 @@ .well.well-small %h3= t('.notes_and_journal') #note - - unless @order.note.empty? + - unless @order.note.blank? = simple_format @order.note - else %p= t('.comment_on_transaction') diff --git a/spec/integration/balancing_spec.rb b/spec/integration/balancing_spec.rb new file mode 100644 index 00000000..75133131 --- /dev/null +++ b/spec/integration/balancing_spec.rb @@ -0,0 +1,55 @@ +require 'spec_helper' + +describe 'settling an order', :type => :feature do + let(:admin) { FactoryGirl.create :user, groups:[FactoryGirl.create(:workgroup, role_finance: true)] } + let(:supplier) { FactoryGirl.create :supplier } + let(:article) { FactoryGirl.create :article, supplier: supplier, unit_quantity: 1 } + let(:order) { FactoryGirl.create :order, supplier: supplier, article_ids: [article.id] } # need to ref article + let(:go1) { FactoryGirl.create :group_order, order: order } + let(:go2) { FactoryGirl.create :group_order, order: order } + let(:oa) { order.order_articles.find_by_article_id(article.id) } + let(:goa1) { FactoryGirl.create :group_order_article, group_order: go1, order_article: oa } + let(:goa2) { FactoryGirl.create :group_order_article, group_order: go2, order_article: oa } + before do + goa1.update_quantities(3, 0) + goa2.update_quantities(1, 0) + oa.update_results! + order.finish!(admin) + goa1.reload + goa2.reload + end + + it 'has correct order result' do + expect(oa.quantity).to eq(4) + expect(oa.tolerance).to eq(0) + expect(goa1.result).to eq(3) + expect(goa2.result).to eq(1) + end + + describe :type => :feature, :js => true do + 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}") + end + + it 'shows order result' do + click_link article.name + expect(page).to have_selector("#group_order_articles_#{oa.id}") + within("#group_order_articles_#{oa.id}") do + # make sure these ordergroup names are in the list for this product + expect(page).to have_content(go1.ordergroup.name) + expect(page).to have_content(go2.ordergroup.name) + # and that their order results match what we expect + expect(page).to have_selector("#group_order_article_#{goa1.id}_quantity") + expect(find("#group_order_article_#{goa1.id}_quantity").text.to_f).to eq(3) + expect(page).to have_selector("#group_order_article_#{goa2.id}_quantity") + expect(find("#group_order_article_#{goa2.id}_quantity").text.to_f).to eq(1) + end + end + + end + +end From 4ea940e4a36f9717484a9c032cf953b3ee26c20a Mon Sep 17 00:00:00 2001 From: Benjamin Meichsner Date: Mon, 2 Sep 2013 10:03:12 +0200 Subject: [PATCH 40/59] Removed unused acts_as_configurable gem. --- Gemfile | 6 +- Gemfile.lock | 8 --- .../20130718183101_migrate_user_settings.rb | 62 +++++++++++-------- db/schema.rb | 12 ---- 4 files changed, 38 insertions(+), 50 deletions(-) diff --git a/Gemfile b/Gemfile index babdca6f..4a71e04b 100644 --- a/Gemfile +++ b/Gemfile @@ -70,8 +70,4 @@ group :development do #gem 'common_deploy', require: false, path: '../../common_deploy' # pending foodcoops/foodsoft#34, git: 'git://github.com/fsmanuel/common_deploy.git' # Avoid having content-length warnings gem 'thin' -end - -# Gems left for backwards compatibility -gem 'acts_as_configurable', git: 'git://github.com/bwalding/acts_as_configurable.git' # user settings migration needs it - +end \ No newline at end of file diff --git a/Gemfile.lock b/Gemfile.lock index a425f25f..52b3bd39 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -4,13 +4,6 @@ GIT specs: localize_input (0.1.0) -GIT - remote: git://github.com/bwalding/acts_as_configurable.git - revision: cdf6f6f979019275b523d10684b748f08e2dd8e8 - specs: - acts_as_configurable (0.0.1) - rake - GIT remote: git://github.com/technoweenie/acts_as_versioned.git revision: 63b1fc8529d028fae632fe80ec0cb25df56cd76b @@ -263,7 +256,6 @@ PLATFORMS ruby DEPENDENCIES - acts_as_configurable! acts_as_tree acts_as_versioned! better_errors diff --git a/db/migrate/20130718183101_migrate_user_settings.rb b/db/migrate/20130718183101_migrate_user_settings.rb index a9722f1b..428608d0 100644 --- a/db/migrate/20130718183101_migrate_user_settings.rb +++ b/db/migrate/20130718183101_migrate_user_settings.rb @@ -1,34 +1,46 @@ class MigrateUserSettings < ActiveRecord::Migration def up - old_settings = ConfigurableSetting.all - - old_settings.each do |old_setting| - # get target (user) - type = old_setting.configurable_type - id = old_setting.configurable_id - user = type.constantize.find(id) - - # get the data (settings) - name = old_setting.name - namespace = name.split('.')[0] - key = name.split('.')[1].underscore # Camelcase to underscore - - # prepare value - value = YAML.load(old_setting.value) - value = value.nil? ? false : value - - # set the settings_attributes (thanks to settings.merge! we can set them one by one) - user.settings_attributes = { - "#{namespace}" => { - "#{key}" => value + say_with_time 'Save old user settings in new RailsSettings module' do + old_settings = ConfigurableSetting.all + + old_settings.each do |old_setting| + # get target (user) + type = old_setting.configurable_type + id = old_setting.configurable_id + begin + user = type.constantize.find(id) + rescue ActiveRecord::RecordNotFound + Rails.logger.debug "Can't find configurable object with type: #{type.inspect}, id: #{id.inspect}" + next + end + + # get the data (settings) + name = old_setting.name + namespace = name.split('.')[0] + key = name.split('.')[1].underscore # Camelcase to underscore + + # prepare value + value = YAML.load(old_setting.value) + value = value.nil? ? false : value + + # set the settings_attributes (thanks to settings.merge! we can set them one by one) + user.settings_attributes = { + "#{namespace}" => { + "#{key}" => value + } } - } - - # save the user to apply after_save callback - user.save + + # save the user to apply after_save callback + user.save + end end + + drop_table :configurable_settings end def down end end + +# this is the base class of all configurable settings +class ConfigurableSetting < ActiveRecord::Base; end \ No newline at end of file diff --git a/db/schema.rb b/db/schema.rb index 03d86aba..0d5b1326 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -66,18 +66,6 @@ ActiveRecord::Schema.define(:version => 20130718183101) do add_index "assignments", ["user_id", "task_id"], :name => "index_assignments_on_user_id_and_task_id", :unique => true - create_table "configurable_settings", :force => true do |t| - t.integer "configurable_id" - t.string "configurable_type" - t.integer "targetable_id" - t.string "targetable_type" - t.string "name", :default => "", :null => false - t.string "value_type" - t.text "value" - end - - add_index "configurable_settings", ["name"], :name => "index_configurable_settings_on_name" - create_table "deliveries", :force => true do |t| t.integer "supplier_id" t.date "delivered_on" From c7cdcf2b823d3dde68ffe46b33dbc80d8b59987d Mon Sep 17 00:00:00 2001 From: Benjamin Meichsner Date: Mon, 2 Sep 2013 10:42:05 +0200 Subject: [PATCH 41/59] Allow setting default locale in user settings migration. Use DEFAULT_LOCALE=de to have german enabled for all users. --- db/migrate/20130718183101_migrate_user_settings.rb | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/db/migrate/20130718183101_migrate_user_settings.rb b/db/migrate/20130718183101_migrate_user_settings.rb index 428608d0..73f30acf 100644 --- a/db/migrate/20130718183101_migrate_user_settings.rb +++ b/db/migrate/20130718183101_migrate_user_settings.rb @@ -1,6 +1,13 @@ class MigrateUserSettings < ActiveRecord::Migration def up say_with_time 'Save old user settings in new RailsSettings module' do + + # Allow setting default locale via env parameter + # This is used, when setting users language settings + default_locale = I18n.default_locale + tmp_locale = ENV['DEFAULT_LOCALE'].present? ? ENV['DEFAULT_LOCALE'].to_sym : default_locale + I18n.default_locale = tmp_locale + old_settings = ConfigurableSetting.all old_settings.each do |old_setting| @@ -33,6 +40,8 @@ class MigrateUserSettings < ActiveRecord::Migration # save the user to apply after_save callback user.save end + + I18n.default_locale = default_locale end drop_table :configurable_settings From 27c006443f152eb75c4376d1aec1985b7da02ce3 Mon Sep 17 00:00:00 2001 From: Benjamin Meichsner Date: Mon, 2 Sep 2013 13:33:14 +0200 Subject: [PATCH 42/59] (git)Ignore localeapp config. --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 2bd55feb..d26b8ce7 100644 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,4 @@ doc/app/ Capfile config/deploy.rb config/deploy/* +.localeapp \ No newline at end of file From 51a91f376d34b5d7ead00398a973185a59507c7e Mon Sep 17 00:00:00 2001 From: Benjamin Meichsner Date: Mon, 2 Sep 2013 13:34:30 +0200 Subject: [PATCH 43/59] Updated locales from localeapp. --- config/locales/de.yml | 1 + config/locales/en.yml | 5 +++-- config/locales/nl.yml | 1 + 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/config/locales/de.yml b/config/locales/de.yml index 11abe693..847c3229 100644 --- a/config/locales/de.yml +++ b/config/locales/de.yml @@ -1772,6 +1772,7 @@ de: shared_suppliers: body:

Hier werden die Lieferantinnen der externen Datenbank angezeigt.

Ihr könnt externe Lieferantinnen importieren, indem ihr sie einfach abonniert. (siehe unten)

Damit wird eine neue Lieferantin angelegt und mit der externen Datenbank verknüpft.

subscribe: abonnieren + subscribe_again: erneut abonnieren supplier: Lieferantin title: Externe Listen show: diff --git a/config/locales/en.yml b/config/locales/en.yml index c9eecb77..fe7f6e2a 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -236,7 +236,7 @@ en: option_available: Make articles available option_delete: Delete article option_not_available: Make articles unavailable - option_select: Choose special offer ... + option_select: Select action ... price_netto: Price unit_quantity_desc: Unit quantity unit_quantity_short: Quantity @@ -440,7 +440,7 @@ en: article: Article category: Category create_from_blank: Create new article - create_stock_article: Create stock articles + create_stock_article: Create stock article price: Netprice quantity: Quantity title_fill_quantities: 2. Set delivery quantities @@ -1774,6 +1774,7 @@ en: shared_suppliers: body:

Suppliers of the external database are displayed here.

You can import external suppliers by subscribing (see below).

A new supplier will be created and connected to the external database.

subscribe: Subscribe + subscribe_again: Subscribe again supplier: Supplier title: External lists show: diff --git a/config/locales/nl.yml b/config/locales/nl.yml index 4b50508d..f5e1f5dc 100644 --- a/config/locales/nl.yml +++ b/config/locales/nl.yml @@ -1663,6 +1663,7 @@ nl: shared_suppliers: body: subscribe: + subscribe_again: supplier: title: show: From a1d85d0dd79ff1ccb85a69336011f0f21edbf3a4 Mon Sep 17 00:00:00 2001 From: Benjamin Meichsner Date: Mon, 2 Sep 2013 14:19:44 +0200 Subject: [PATCH 44/59] Changed API of multicoops rake tasks. Use TASK=sample:task Fixed running rake task without multicoops wrapper. --- lib/tasks/multicoops.rake | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/lib/tasks/multicoops.rake b/lib/tasks/multicoops.rake index ccd16f6f..621a0d54 100644 --- a/lib/tasks/multicoops.rake +++ b/lib/tasks/multicoops.rake @@ -1,17 +1,21 @@ +# This namespace is used for a collection of tasks to maintain a hosting environment with multiple foodcoops +# This tasks are a kind of wrapper for other tasks. The wrapper makes sure, that the appropriate database and config +# for each foodcoop is used. + namespace :multicoops do - desc 'Runs a specific rake task for each registered foodcoop, use rake multicoops:run db:migrate' + desc 'Runs a specific rake task for each registered foodcoop, use rake multicoops:run TASK=db:migrate' task :run => :environment do - task_to_run = ARGV[1] + task_to_run = ENV['TASK'] FoodsoftConfig.each_coop do |coop| puts "Run '#{task_to_run}' for #{coop}" Rake::Task[task_to_run].execute end end - desc 'Runs a specific rake task for a single coop, use rake mutlicoops:run_single db:migrate FOODCOOP=demo' + desc 'Runs a specific rake task for a single coop, use rake mutlicoops:run_single TASK=db:migrate FOODCOOP=demo' task :run_single => :environment do - task_to_run = ARGV[1] + task_to_run = ENV['TASK'] FoodsoftConfig.select_foodcoop ENV['FOODCOOP'] puts "Run '#{task_to_run}' for #{ENV['FOODCOOP']}" Rake::Task[task_to_run].execute From 5883bf50f3d785e9e78d9f3dd8df1a89faa73540 Mon Sep 17 00:00:00 2001 From: Benjamin Meichsner Date: Mon, 2 Sep 2013 14:41:16 +0200 Subject: [PATCH 45/59] Removed rails3 branch and updated Readme. --- README.md | 5 ----- 1 file changed, 5 deletions(-) diff --git a/README.md b/README.md index 7f447972..57982933 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,3 @@ -Important --------- - -We changed the branch structure. The rails3 branch is now master. But you can safely send pull requests to rails3. It'll remain there for a couple of weeks. - FoodSoft ========= [![Code Climate](https://codeclimate.com/github/foodcoops/foodsoft.png)](https://codeclimate.com/github/foodcoops/foodsoft) From bf1c2b5ed278bdef1c5a2107d9847eb63918bcb4 Mon Sep 17 00:00:00 2001 From: Benjamin Meichsner Date: Mon, 2 Sep 2013 15:42:03 +0200 Subject: [PATCH 46/59] Handle missing due_date in weekly tasks migration. --- db/migrate/20130622095040_move_weekly_tasks.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/db/migrate/20130622095040_move_weekly_tasks.rb b/db/migrate/20130622095040_move_weekly_tasks.rb index be316c5c..f9f363fd 100644 --- a/db/migrate/20130622095040_move_weekly_tasks.rb +++ b/db/migrate/20130622095040_move_weekly_tasks.rb @@ -35,6 +35,8 @@ class MoveWeeklyTasks < ActiveRecord::Migration private def weekly_task?(workgroup, task) + return false if task.due_date.nil? + group_task = { weekday: workgroup.weekday, name: workgroup.task_name, From 3792069fdaaf760643a9a3b9e9a1016a1421e9d5 Mon Sep 17 00:00:00 2001 From: Benjamin Meichsner Date: Mon, 2 Sep 2013 16:46:44 +0200 Subject: [PATCH 47/59] Fxed encoding error when uploading files with non-ascii characters. --- db/migrate/20130622095040_move_weekly_tasks.rb | 2 +- lib/foodsoft_file.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/db/migrate/20130622095040_move_weekly_tasks.rb b/db/migrate/20130622095040_move_weekly_tasks.rb index f9f363fd..e8dc8384 100644 --- a/db/migrate/20130622095040_move_weekly_tasks.rb +++ b/db/migrate/20130622095040_move_weekly_tasks.rb @@ -36,7 +36,7 @@ class MoveWeeklyTasks < ActiveRecord::Migration private def weekly_task?(workgroup, task) return false if task.due_date.nil? - + group_task = { weekday: workgroup.weekday, name: workgroup.task_name, diff --git a/lib/foodsoft_file.rb b/lib/foodsoft_file.rb index 1aa40dfb..0ef6367c 100644 --- a/lib/foodsoft_file.rb +++ b/lib/foodsoft_file.rb @@ -11,7 +11,7 @@ module FoodsoftFile def self.parse(file) articles, outlisted_articles = Array.new, Array.new row_index = 2 - ::CSV.parse(file.read, {:col_sep => ";", :headers => true}) do |row| + ::CSV.parse(file.read.force_encoding('utf-8'), {:col_sep => ";", :headers => true}) do |row| # check if the line is empty unless row[2] == "" || row[2].nil? article = {:number => row[1], From 9f22615a252e03930060acbe3eddf5b69d34dadc Mon Sep 17 00:00:00 2001 From: Robert Waltemath Date: Thu, 5 Sep 2013 10:16:57 +0200 Subject: [PATCH 48/59] Order tasks with same date by name. --- app/models/workgroup.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/workgroup.rb b/app/models/workgroup.rb index 819c75bd..3bcf124d 100644 --- a/app/models/workgroup.rb +++ b/app/models/workgroup.rb @@ -3,7 +3,7 @@ class Workgroup < Group has_many :tasks # returns all non-finished tasks - has_many :open_tasks, :class_name => 'Task', :conditions => ['done = ?', false], :order => 'due_date ASC' + has_many :open_tasks, :class_name => 'Task', :conditions => ['done = ?', false], order: 'due_date ASC, name ASC' validates_uniqueness_of :name validate :last_admin_on_earth, :on => :update From a0760ebfdbda58430c3a8202e9fb74348806025e Mon Sep 17 00:00:00 2001 From: Benjamin Meichsner Date: Fri, 6 Sep 2013 11:40:10 +0200 Subject: [PATCH 49/59] Fixed delivering emails to users. There was a bug in User#receive_email? Return values are now true or false, not '1' or '0'. --- app/models/user.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/user.rb b/app/models/user.rb index ab11da32..2b4a399b 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -66,7 +66,7 @@ class User < ActiveRecord::Base end def receive_email? - settings.messages['send_as_email'] == "1" && email.present? + settings.messages['send_as_email'] && email.present? end # Sets the user's password. It will be stored encrypted along with a random salt. From bdd0f8cbcb44d13053bca2b2cac9405f9b9cb57c Mon Sep 17 00:00:00 2001 From: wvengen Date: Fri, 6 Sep 2013 19:31:15 +0200 Subject: [PATCH 50/59] fix heroku deploy script (also closes #165) --- script/heroku_deploy | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/script/heroku_deploy b/script/heroku_deploy index 2b95ff7b..df7da72d 100755 --- a/script/heroku_deploy +++ b/script/heroku_deploy @@ -55,12 +55,16 @@ fi sed -i "s|^\\(\\s*gem\\s\\+'sqlite3'\\)|#\1|" Gemfile sed -i "s|^\\(\\s*sqlite3\\b\)|#\1|" Gemfile.lock # make sure postgresql db is present, as it is the default heroku db -echo $'\ngem "pg"' >>Gemfile -echo $'\ngem "localeapp"' >>Gemfile +echo " +gem 'pg'" >>Gemfile # always use unicorn -echo $'\ngem "unicorn"' >>Gemfile +echo " +gem 'unicorn'" >>Gemfile echo 'web: bundle exec unicorn -p $PORT -E $RACK_ENV' >Procfile -bundle install --quiet # to update Gemfile.lock +# don't complain when mail cannot be sent, +# XXX when you're hosting a production instance, use a real smtp server instead +sed -i 's|\(#\s*\)\?\(config\.action_mailer\.raise_delivery_errors\)\s*=.*|\2 = false|' config/environments/${RAILS_ENV}.rb +sed -i 's|\(#\s*\)\?\(config\.action_mailer\.delivery_method\)\s*=.*|\2 = :smtp|' config/environments/${RAILS_ENV}.rb # do not ignore deployment files sed -i 's|^\(config/\*.yml\)|#\1|' .gitignore sed -i 's|^\(config/initializers/secret_token.rb\)|#\1|' .gitignore @@ -92,9 +96,13 @@ Localeapp.configure do |config| config.polling_environments = ['$RAILS_ENV'] end EOF + echo " +gem 'localeapp'" >>Gemfile # also do not cache so we get locale updates - sed -i 's|config\.cache_classes\s*=.*|config.cache_classes = false|' config/environments/${RAILS_ENV}.rb + sed -i 's|\(#\s*\)\?\(config\.cache_classes\)\s*=.*|\2 = false|' config/environments/${RAILS_ENV}.rb fi +# update Gemfile.lock after Gemfile updates (required by heroku) +bundle install --quiet # TODO add more extensive database seed # and push = deploy From 9922c0322a3443072adb9f1dc8dea261cb600169 Mon Sep 17 00:00:00 2001 From: wvengen Date: Fri, 6 Sep 2013 19:41:24 +0200 Subject: [PATCH 51/59] first version of new translation: French --- config/locales/de.yml | 1 + config/locales/en.yml | 1 + config/locales/fr.yml | 1916 +++++++++++++++++++++++++++++++++++++++++ config/locales/nl.yml | 1 + 4 files changed, 1919 insertions(+) create mode 100644 config/locales/fr.yml diff --git a/config/locales/de.yml b/config/locales/de.yml index 847c3229..650dc27b 100644 --- a/config/locales/de.yml +++ b/config/locales/de.yml @@ -1669,6 +1669,7 @@ de: language: de: Deutsch en: English + fr: Französisch nl: Niederländisch required: mark: ! '*' diff --git a/config/locales/en.yml b/config/locales/en.yml index fe7f6e2a..55b7190b 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -1671,6 +1671,7 @@ en: language: de: German en: English + fr: French nl: Dutch required: mark: ! '*' diff --git a/config/locales/fr.yml b/config/locales/fr.yml new file mode 100644 index 00000000..aa01d181 --- /dev/null +++ b/config/locales/fr.yml @@ -0,0 +1,1916 @@ +fr: + activemodel: + errors: + format: ! '%{attribute} %{message}' + general: Un problème a été rencontré. + general_again: Une erreur s'est produite. Merci de réessayer. + general_msg: ! 'Une erreur s''est produite: %{msg}' + messages: + accepted: doit obligatoirement être accepté + blank: doit obligatoirement être complété + confirmation: ne correspond pas avec le champ de confirmation + empty: doit obligatoirement être complété + equal_to: doit obligatoirement être égal à %{count} + even: doit obligatoirement être pair + exclusion: n'est pas disponible + greater_than: doit obligatoirement être supérieur à %{count} + greater_than_or_equal_to: doit obligatoirement être supérieur ou égal à %{count} + inclusion: n'est pas une valeur valide + invalid: n'est pas valide + less_than: doit obligatoirement être inférieur à %{count} + less_than_or_equal_to: doit obligatoirement être inférieur à %{count} + not_a_number: n'est pas un nombre + not_an_integer: doit être un nombre entier + odd: doit obligatoirement être impair + record_invalid: ! 'la vérification a échoué: %{errors}' + taken: a déjà été attribué + taken_with_deleted: a déjà été attribué (à une cellule supprimée depuis) + too_long: est trop long (%{count} signes autorisés au maximum) + too_short: est trop court (%{count} signes au minimum doivent être présents) + wrong_length: n'est pas de la bonne longueur (exactement %{count} signes doivent être présents) + template: + body: ! 'Merci de contrôler le contenu des champs suivants:' + header: + one: ! '%{model} n''a pas pu être sauvegardé à cause de la présence d''une erreur.' + other: ! '%{model} n''a pas pu être sauvegardé car %{count} erreurs ont été trouvées.' + activerecord: + attributes: + article: + article_category: catégorie + availability: l'article est-il disponible? + deposit: consigne + fc_price: prix final + fc_share: prélèvement pour la coop + gross_price: prix brut + price: prix net + tax: TVA + unit: unité + unit_quantity: unités par lot + financial_transaction: + amount: montant + note: note + stock_article: + price: Prix net + user: + first_name: Prénom + password: Mot de passe + errors: + format: ! '%{attribute} %{message}' + general: Une problème a été rencontré. + general_again: Une erreur s'est produite. Merci de réessayer. + general_msg: ! 'Un problème a été rencontré: %{msg}' + has_many_left: est encore associé à une %{collection}! + messages: + accepted: doit obligatoirement être accepté + blank: doit obligatoirement être complété + confirmation: ne correspond pas au champ de confirmation + empty: doit obligatoirement être complété + equal_to: doit obligatoirement être égal à %{count} + even: doit être un nombre pair + exclusion: n'est pas disponible + greater_than: doit obligatoirement être supérieur à %{count} + greater_than_or_equal_to: doit obligatoirement être supérieur ou égal à %{count} + inclusion: n'est pas un valeur valide + invalid: est invalide + less_than: doit obligatoirement être inférieur à %{count} + less_than_or_equal_to: doit obligatoirement être inférieur ou égal à %{count} + not_a_number: n'est pas un nombre + not_an_integer: doit obligatoirement être un nombre entier + odd: doit obligaroirement être un nombre impair + record_invalid: ! 'la vérification a échoué: %{errors}' + taken: a déjà été attribué + taken_with_deleted: a déjà été attribué (à une cellule supprimée depuis) + too_long: est trop long (au maximum %{count} signes sont autorisés) + too_short: est trop court (au minimum %{count} signes doivent être présents) + wrong_length: n'a pas la bonne longueur (exactement %{count} signes doivent être présents) + models: + task: + attributes: + done: + exclusion: répétition hebdomadaire invalide pour un boulot déjà effectué + template: + body: ! 'Merci de vérifier le contenu des champs suivants:' + header: + one: ! '%{model} n''a pu être sauvegardé à cause de la présence d''une erreur.' + other: ! '%{model} n''a pu être sauvegardé à cause de %{count} erreurs.' + models: + article: Article + article_category: Catégorie d'article + delivery: Livraison + financial_transaction: Opération de trésorerie + invoice: Facture + message: Message + order: Commande + order_article: Article à commander + order_comment: Commentaire + ordergroup: Cellule + stock_article: Article en stock + stock_taking: Inventaire + supplier: FournisseusE_r + task: Boulot + user: Utilisatrices + workgroup: Equipe + admin: + access_to: accès à + actions: Actions + base: + index: + all_ordergroups: Toutes les cellules + all_users: Toutes les utilisatrices + all_workgroups: Toutes les équipes + created_at: créé le + first_paragraph: Les cellules et les utilisateurs du Foodsoft peuvent être administrés sur cette page. + groupname: nom de la cellule + members: membres + name: nom + new_ordergroup: Nouvelle cellule + new_user: Nouvelle utilisatrice + new_workgroup: Nouvelle équipe + newest_groups: cellules les plus récentes + newest_users: utilisateurs les plus récents + title: Administration + type: type + username: identifiant + confirm: Veux-tu vraiment supprimer %{name}? + ordergroups: + destroy: + error: ! 'La cellule n''a pas pu être supprimée: %{error}' + notice: La cellule a été supprimée + edit: + title: Modifier les informations sur la cellule + form: + first_paragraph: Invite des nouveaux membres %{url}. + here: ici + index: + first_paragraph: Sur cette page, %{url} peut être ajouté, et des cellules peuvent être modifiées ou supprimées. + new_ordergroup: Créer une nouvelle cellule + new_ordergroups: nouvelles cellules + second_paragraph: ! 'Attention à bien noter la différence entre une équipe et une cellule: une cellule est toujours associée à un compte de crédit et sert à passer des commandes, tandis qu''une %{url} (par exemple l''équipe distribution) s''occupe des boulots utiles à la coop. Les utilisatrices appartiennent toujours à une et une seule cellule, mais peuvent faire partie de plusieurs équipes.' + title: Cellules + workgroup: équipe + new: + title: Créer une nouvelle cellule + ordergroups: + address: Adresse + contact: Contact + members: Membres + name: Nom + show: + confirm: T'es sûrE de ton coup? + edit: Modifier les données sur les cellules et/ou leurs membres + send_message: Envoyer un message + title: Cellule %{name} + search_placeholder: nom ... + users: + edit: + title: modifier les données sur l'utilisatrice + index: + first_paragraph: Sur cette page, tu peux %{url}, modifier ou bien supprimer des utilisatrices. + new_user: Ajouter une nouvelle utilisatrice + new_users: ajouter + title: Administration des utilisatrices + new: + title: Ajouter une nouvelle utilisatrice + show: + confirm: Veux-tu vraiment expulser %{user}? + email: Email + groupabos: Participation à des équipes + member_since: Membre depuis %{time} + name: Nom + nick: Identifiant + person: Personne + phone: Numéro de téléphone + preference: Préférences + send_message: Envoyer un message + users: + email: email + last_login: dernière connection + login: identifiant + name: nom + workgroups: + destroy: + error: ! 'Cette équipe n''a pas pu être supprimée: %{error}' + notice: L'équipe a bien été supprimée + edit: + title: Modifier les données sur l'équipe + form: + first_paragraph: Des nouveaux membres peuvent être invités %{url}. + here: ici + index: + first_paragraph: Sur cette page, tu peux ajouter, modifier et supprimer %{url}. + new_workgroup: Créer une nouvelle équipe + new_workgroups: nouvelles équipes + ordergroup: cellule + second_paragraph: ! 'Attention à bien noter la différence entre une équipe et une cellule: une cellule est toujours associée à un compte de crédit et sert à passer des commandes, tandis qu''une %{url} (par exemple l''équipe distribution) s''occupe des boulots utiles à la coop. Les utilisatrices appartiennent toujours à une et une seule cellule, mais peuvent faire partie de plusieurs équipes.' + title: Equipes + new: + title: Créer une nouvelle équipe + show: + confirm: T'es sûrE de ton coup? + edit: Modifier les données sur l'équipe et/ou ses membres + title: Equipe %{name} + workgroups: + members: membres + name: nom + article_categories: + create: + notice: Catégorie sauvegardée + destroy: + error: ! 'Cette catégorie n''a pas pu être supprimée: %{message}' + edit: + title: Modifier la catégorie + index: + confirm_delete: T'es sûrE de ton coup? + new: Créer une nouvelle catérogie + title: Catégories d'articles + new: + title: Créer une nouvelle catégorie + update: + notice: La catégorie a été mise à jour + articles: + article: + confirm_delete: T'es sûrE de ton coup? + last_update: ! 'dernière modification: %{last_update} | brut: %{gross_price}' + articles: + confirm_delete: Tu veux vraiment supprimer tous ces articles? + option_available: Ces articles sont disponible + option_delete: Supprimer ces articles + option_not_available: Marquer ces articles comme indisponibles + option_select: Choisir une action... + price_netto: Prix + unit_quantity_desc: Unités par lot + unit_quantity_short: U/L + controller: + create_from_upload: + notice: ! '%{count} nouveaux articles on été sauvegardés.' + error_invalid: La description des articles comporte des erreurs. + error_nosel: Aucun article n'a été sélectionné + error_parse: ! '%{msg} ... à la ligne %{line}' + error_update: ! 'Une erreur s''est produite lors de la mise à jour de l''article "%{article}": %{msg}' + parse_upload: + notice: ! '%{count} articles ont été examinés avec succès.' + sync: + notice: Le catalogue est à jour + shared_alert: ! '%{supplier} n''est pas associé à une base de données extérieure.' + update_all: + notice: Les articles et les prix ont été mis à jour. + update_sel: + notice_avail: Les articles sélectionnés ont été marqués comme disponibles. + notice_destroy: Les articles sélectionnés ont été supprimés. + notice_noaction: Aucune action n'a été spécifiée! + notice_unavail: Les articles sélectionnés ont été marqués comme indisponibles. + update_sync: + notice: Les articles et les prix ont été mis à jour. + destroy_active_article: + drop: supprimer + note: ! '%{article} apparaît dans des listes de commande en cours et ne peut donc être supprimé. Il faut d''abord %{drop_link} des listes de commande.' + edit_all: + note: ! 'Les champs obligatoires sont: le nom, l''unité, le prix net et le numéro de commande.' + submit: Mettre à jour tous les articles + title: Modifier tous les articles de %{supplier} + warning: Attention, tous les articles sont en train d'être mis à jour! + edit_all_table: + available_desc: disponible + available_short: disp. + order_number_desc: numéro de commande + order_number_short: n° + price_desc: Prix net + price_short: Prix + unit_quantity_desc: Unités par lot + unit_quantity_short: U/L + form: + title: Ajouter un nouvel article + import_search_results: + action_import: importer + already_imported: déjà importé + not_found: Aucun article n'a été trouvé + index: + change_supplier: Changer de fournisseusE_r... + edit_all: Tout modifier + ext_db: + import: Rechercher/Importer + sync: Synchroniser + title: Base de données externe + import: + placeholder: Nom... + restrict_region: Seulement les articles régionaux + title: Importer cet article + new: Nouvel article + new_order: Créer une nouvelle liste de commande + search_placeholder: Nom... + title: Articles de %{supplier} (%{count}) + upload: Transférer les articles + model: + error_in_use: ! '%{article} ne peut pas être supprimé car il fait partie d''une liste de commande en cours!' + error_nosel: Aucun article n'a été sélectionné + parse_upload: + body: ! '

Merci de vérifier les articles importés.

+ +

Attention, les doublons ne sont pas automatiquement détectés.

.' + outlist: + body: ! 'Les articles suivants ne sont plus dans la liste et seront donc supprimés:' + body_skip: Aucun article à supprimer. + title: Exclure de la liste... + price_short: Prix + submit: Tout supprimer ou mettre à jour. + title: Synchroniser les articles avec la base de données extérieure + unit_quantity_short: U/L + update: + body:

Chaque article apparaît deux fois. Les anciennes données sont rappelées en gris, et les champs du formulaire ont été préremplis avec les nouvelles valeurs.

Les changements sont marqués en jaune.

+ title: Mettre à jour... + update_msg: ! 'Ces articles doivent être mis à jour:' + upload: + body: ! '

Le fichier doit être au format texte et son nom doit se terminer par l''extension ".csv". La première ligne sera ignorée lors de l''importation.

+ +

Les champs doivent être délimités par des points-virgules ('';''), et le texte compris entre guillemets ("texte...")

+ +

L''encodage du fichier doit être UTF-8. L''ordre des colonnes est:

' + fields: + season_amount: Quantité échelonnée + season_price: Prix échelonné + status: Statut (x=exclu) + file_label: Merci de choisir un fichier compatible + submit: Transférer le fichier + title: ! '%{supplier} / Transférer les données sur l''article' + date: + abbr_day_names: + - Lun + - Mar + - Mer + - Jeu + - Ven + - Sam + - Dim + abbr_month_names: + - + - Janvier + - Février + - Mars + - Avril + - Mai + - Juin + - Juillet + - Août + - Septembre + - Octobre + - Novembre + - Décembre + day_names: + - Dimanche + - Lundi + - Mardi + - Mercredi + - Jeudi + - Vendredi + - Samedi + formats: + default: ! '%d.%m.%Y' + long: ! '%e.%B %Y' + short: ! '%e. %b' + month_names: + - + - Janvier + - Février + - Mars + - Avril + - Mai + - Juin + - Juillet + - Août + - Septembre + - Octobre + - Novembre + - Décembre + order: + - :day + - :month + - :year + datetime: + distance_in_words: + about_x_hours: + one: environ une heure + other: environ %{count} heures + about_x_months: + one: environ un mois + other: environ %{count} mois + about_x_years: + one: environ un an + other: environ %{count} ans + almost_x_years: + one: presque un an + other: presque %{count} ans + half_a_minute: une demi-minute + less_than_x_minutes: + one: moins d'une minute + other: moins de %{count} minutes + less_than_x_seconds: + one: moins d'une seconde + other: moins de %{count} secondes + over_x_years: + one: plus d'un an + other: plus de %{count} ans + x_days: + one: un jour + other: ! '%{count} jours' + x_minutes: + one: une minute + other: ! '%{count} minutes' + x_months: + one: un mois + other: ! '%{count} mois' + x_seconds: + one: une seconde + other: ! '%{count} secondes' + prompts: + day: jour + hour: heures + minute: minute + month: mois + second: secondes + year: an + deliveries: + add_stock_change: + how_many_units: Combien d'unites (%{unit}) de l'article "%{name}" doivent être livrées? + create: + notice: La livraison a été créée. Attention à ne pas oublier de déposer la facture correspondante! + create_stock_article: + notice: Le nouvel article en stock "%{name}" a été sauvegardé. + destroy: + notice: La livraison a été annulée. + edit: + title: Modifier la livraison + form: + actions: Options + article: Article + category: Catégorie + create_from_blank: Ajouter un nouvel article quelconque + create_stock_article: Ajouter un nouvel article en stock + price: Prix net + quantity: Quantité + title_fill_quantities: 2. Définir la quantité à livrer + title_finish_delivery: 3. Terminer la livraison + title_select_stock_articles: 1. Choisir les articles en stock + unit: Unité + index: + confirm_delete: T'es sûrE de ton coup? + new_delivery: Définir une nouvelle livraison de %{supplier} + title: ! '%{supplier}/Livraisons' + invoice_amount: Montant de la facture + invoice_net_amount: Montant net de la facture + new: + title: Nouvelle livraison de %{supplier} + show: + amount: Quantité + article: Article + price: Prix net + sum: Prix total + sum_diff: montant brut - montant net + sum_gross: prix total brut + sum_net: prix total net + title: Afficher la livraison + title_articles: Article + unit: Unité + stock_article_for_adding: + action_add_to_delivery: Commander + action_edit: Modifier + action_other_price: Copier + stock_article_form: + copy_stock_article: Copier l'article en stock + stock_change_fields: + remove_article: Retirer l'article de cette commande + suppliers_overview: Liste des fournisseusEs_rs + update: + notice: La commande a été actualisée + update_stock_article: + notice: Les données de l'article en stock "%{name}" ont été mises à jour. + documents: + order_by_articles: + filename: Commande %{name}-%{date} - Trier par + rows: + - Cellule + - Quantité + - Prix + title: ! 'Ordre des articles pour la commande: %{name}, terminée le %{date}' + order_by_groups: + filename: Commande %{name}-%{date} - Répartition par cellules + rows: + - Nom de l'article + - Quantité + - Prix unitaire + - Unités par lot + - Unité + - Prix total + sum: prix total + title: ! 'Répartition par cellules pour la commande: %{name}, terminée le %{date}' + order_fax: + filename: Commande %{name}-%{date} - Fax + rows: + - Numéro + - Quantité + - Nom + - Nombre de lots + - Unité + - Prix unitaire + order_matrix: + filename: Commande %{name}-%{date} - Tableau de répartition + heading: Liste des articles + rows: + - Article + - Unité + - Nombre de lots + - Prix coop + - Quantité + title: ! 'Tableau de répartition pour la commande: %{name}; terminée le %{date}' + total: + one: Un seul article + other: ! '%{count} articles au total' + errors: + format: ! '%{attribute} %{message}' + general: Un problème a été rencontré. + general_again: Une erreur s'est produite. Merci de réessayer. + general_msg: ! 'Une erreur s''est produite: %{msg}' + messages: + accepted: doit obligatoirement être accepté + blank: doit obligatoirement être complété + confirmation: ! ' ne correspond pas au champ de confirmatio' + empty: doit obligatoirement être complété + equal_to: doit obligatoirement être égal à %{count} + even: doit obligatoirement être un nombre pair + exclusion: n'est pas disponible + greater_than: doit obligatoirement être supérieur à %{count} + greater_than_or_equal_to: doit obligatoirement être supérieur ou égal à %{count} + inclusion: n'est pas une valeur valide + invalid: n'est pas valide + less_than: doit obligatoirement être inférieur à %{count} + less_than_or_equal_to: doit obligatoirement être inférieur ou égal à %{count} + not_a_number: n'est pas un nombre + not_an_integer: doit obligatoirement être un nombre entier + odd: doit obligatoirement être un nombre impair + record_invalid: ! 'La vérification a échoué: %{errors}' + taken: a déjà été attribué + taken_with_deleted: a déjà été attribué (à une cellule supprimée depuis) + too_long: est trop long (au maximum %{count} signes sont autorisés) + too_short: est trop court (au minimum %{count} signes doivent être présents) + wrong_length: n'a pas la bonne longueur (exactement %{count} signes doivent être présents) + template: + body: ! 'Merci de contrôler le contenu des champs suivants:' + header: + one: ! '%{model} n''a pas pu être sauvegardé: une erreur trouvée.' + other: ! '%{model} n''a pas pu être sauvegardé: %{count} erreurs trouvées.' + feedback: + create: + notice: Ton commentaire a été transmis avec succès. Merci + new: + first_paragraph: Tu as trouvé une erreur? Tu as une proposition, une idée, une critique? Envoie un commentaire! + second_paragraph: ! 'Petite remarque: l''équipe de Foodsoft s''occupe seulement de la maintenance du logiciel. + + Pour les questions concernants l''organisation de ta coop, il faut contacter les personnes concernées.' + send: Transmettre + title: Laisser un commentaire + finance: + balancing: + close: + alert: ! 'Une erreur s''est produite lors du décompte: %{message}' + notice: La commande a été décomptée avec succès, et les comptes des utilisateurs ont été mis à jour. + close_direct: + alert: ! 'Impossible de terminer cette commande: %{message}' + notice: La commande a été terminée avec succès. + confirm: + clear: Terminer + first_paragraph: ! 'Lorsque la commande sera terminée, les comptes seront mis à jour en conséquence. + +
+ + Les prélèvements pour cette commande s''élèveront comme suit: ' + or_cancel: ou retourner au décompte + title: Décompter la commande + edit_results_by_articles: + add_article: Ajouter un article + amount: Quantité + amount_per_unit: Poids d'un lot + article: Article + gross: Brut + net: Net + number: Numéro + refund: Consigne + tax: TVA + group_order_articles: + add_group: Créer un nouveau groupe + group: Groupe + total: Prix total + total_fc: Prix total (pour la coop) + units: Nombre d'unités + index: + title: Commandes terminée + invoice: + edit: Modifier la facture + invoice_amount: ! 'Montant de la facture:' + invoice_date: ! 'Date de la facture:' + invoice_number: ! 'Numéro de la facture:' + minus_refund_calculated: ! 'Prix de la consigne:' + new: Créer une nouvelle facture + new_body: Ajouter une facture pour cette commande + plus_refund_credited: Remboursement de la consigne + refund_adjusted_amount: Montant recalculé en excluant les consignes + new: + alert: Attention, cette commande a déjà été décomptée + articles_overview: Aperçu des article + comment_on_transaction: Ici, tu peux faire part de tes commentaires concernant le décompte de la facture + comments: Commentaire + confirm_order: Terminer la commande + create_invoice: Ajouter une facture + edit_note: Modifier la note + edit_order: Modifier la commande + groups_overview: Aperçu des cellule + invoice: Facture + notes_and_journal: Notes/Remarques + summary: Résumé + title: décompter %{name} + view_options: Préférences d'affichage + order_article: + confirm: T'es sûrE de ton coup? + orders: + clear: décompter + cleared: déjà décompté (%{amount}) + close: fermer maintenant + confirm: Veux-tu vraiment terminer la commande? + end: Fin + ended: expiré + last_edited_by: Dernières modifications effectuées par + name: FournisseusE_r + no_closed_orders: Aucune commande n'a pour le moment été terminée. + state: Statut + summary: + changed: Les données ont été modifiées! + duration: von %{starts} bis %{ends} + fc_amount: ! 'Montant coop:' + fc_profit: Part de la coop + gross_amount: Montant brut + groups_amount: ! 'Montant pour chaque cellule:' + net_amount: ! 'Montant net:' + reload: Actualiser le résumé + with_extra_charge: ! 'avec supplément:' + without_extra_charge: ! 'sans supplément:' + create: + notice: La facture a été générée. + financial_transactions: + create: + notice: La transaction a été sauvegardée. + create_collection: + alert: ! 'Une erreur s''est produite: %{error}' + notice: Les transactions ont été sauvegardées. + index: + balance: ! 'Solde: %{balance}' + last_updated_at: (dernière mis à jour avant le %{when}) + new_transaction: Ajouter une nouvelle transaction + search_placeholder: Rechercher ... + title: Relevé de compte pour %{name} + new: + paragraph: Cet espace permet de rajouter ou d'enlever du crédit à la cellule %{name}. + title: Nouvelle transaction + new_collection: + amount: Montant + new_ordergroup: Ajouter de nouvelles cellules + note: Note + ordergroup: Cellule + save: Sauvegarder les transactions + sidebar: ! "Cet espace permet de mettre à jour plusieurs comptes simultanément, \npar exemple pour saisir les versements des cellules sur leurs comptes à partir d'un relevé." + title: Mettre à jour plusieurs comptes + ordergroup: + remove: Supprimer + remove_group: Supprimer cette cellule + transactions: + amount: Montant + date: Date + note: Note + who: Qui? + group_order_articles: + form: + amount_change_for: Modification de la quantité de %{article} + index: + amount: Montant + amount_fc: Montant(coop) + clear: Décompter + date: Date + end: Fin + everything_cleared: Super, tout est a déjà été décompté! + group: Cellule + last_transactions: Dernières transactions + note: Note + open_transactions: Pas encore décompté + show_all: tout afficher + supplier: FournisseusE_r + title: Espace trésorerie + unpaid_invoices: Factures pas encore réglées + invoices: + edit: + title: Modifier cette facture + index: + action_new: Créer une nouvelle facture + title: Facture + invoices: + confirm_delete: T'es sûrE de ton coup? + delivery: Livraison + linked: Cette facture est associée à %{what_link}. + linked_delivery: une livraison + linked_order: une commande + new: + back: Retour + title: Créer une nouvelle facture + show: + back: Retour + title: Facture %{number} + order_articles: + edit: + title: Mettre à jour la liste des article + new: + title: + ordergroups: + index: + new_transaction: Saisir une nouvelle transaction + search_placeholder: Rechercher ... + title: Gestion des crédits + ordergroups: + account_balance: Crédit disponible + account_statement: Relevé de compte + name: Nom + new_transaction: Nouvelle transaction + update: + notice: La facture a été mise à jour. + foodcoop: + ordergroups: + index: + name: Nom ... + only_active: Seulement les cellules en activité + only_active_desc: (ayant commandé au moins une fois dans les 3 derniers mois) + title: Cellule + ordergroups: + last_ordered: dernière commande + name: Nom + user: Membres + users: + index: + body: ! '

Cette page sert à envoyer des messages aux autres membres de la coop.

+ +

Si tu veux que ton identité soit visible par les autres, il faut le spécifier sur ton profil %{profile_link}.

' + ph_name: Nom ... + ph_ordergroup: Cellule ... + profile_link: Préférence + title: Membre + workgroups: + edit: + invite_link: ici + invite_new: Tu peux engrainer des nouveaux membres %{invite_link}. + title: Modifier cette équipe + index: + body: ! '

Seuls les membres d''une équipe peuvent la modifier.

+ +

Tu peux rejoindre une équipe en contactant un de ses membres.

' + title: Equipes + workgroup: + edit: Modifier la cellule + show_tasks: Afficher tous les boulots + group_orders: + archive: + desc: Accéder à toutes les %{link}. + open_orders: commandes en cours + title: commandes de %{group} + title_closed: décomptée + title_open: terminée/pas décomptée + create: + error_general: Suite à une erreur, la commande n'a pu être mise à jour. + error_stale: La commande n'a pas pu être mise à jour car quelqu'un d'autre a commandé entre temps. + notice: La commande a bien été enregistrée. + errors: + closed: La commande est déjà terminée. + no_member: Tu n'es encore membre d'aucune cellule. + notfound: ! ' Mauvaise adresse, ce n''est pas ta commande.' + form: + action_save: Enregistrer la commande + amount: Quantité + available: Disponible + available_funds: Crédit disponible + created_by: Établi par + ending: Fin + funds: Crédit + last_update: Dernière commande + manufacturer: Produit par + min_quantity: Quantité minimale + name: Nom + new_funds: Nouveau solde + note: Note + price: Prix + sum: Prix total + sum_amount: ! 'Quantité déjà commandée:' + supplier: Fourni par + title: Commander + tolerance: Tolérance + total_sum_amount: Montant total + total_tolerance: Tolérance totale + unit: Unité + unit_missing: Unités manquantes + units: Lots + units_full: Lots complet + units_total: Unités déjà commandées + index: + closed_orders: + more: suite... + title: Commandes décomptées + finished_orders: + title: Commandes par encore décomptées + total_sum: Total + funds: + account_balance: Crédit initial + available_funds: Crédit disponible + finished_orders: montant prévu des commandes non décomptées + open_orders: montant des commandes en cours + title: Crédit + title: Aperçu des commandes + messages: + not_enough_apples: ! 'Il faut que ta cellule ait au moins %{stop_ordering_under} glands pour pouvoir commander, + + alors que vous n''en avez que %{apples} pour le moment.' + order: + title: Article + orders: + ending: Fi + sum: Total + supplier: FournisseusE_r + show: + articles: + edit_order: Adapter la commande + name: Nom + not_ordered_msg: Tu n'as pas encore commandé + order_closed_msg: Désolé, cette commande a déjà été fermée. Il faudra se réveiller plus tôt la prochaine fois. + order_nopen_title: En tenant compte des commandes en cours de toutes les cellules + order_not_open: Déjà reçu + order_now: Voilà ta chance! + order_open: Commande en cours + ordered: Commandé + ordered_title: Quantité + tolérance + show_hide: Montrer/cacher les articles non commandés + sum: Total + title: Aperçu des article + total_price: Prix total + unit_price: Prix unitaire + units: Lots + closed_by: Décompté par %{user} + comment: Lire/écrire des commentaire + comments: + title: Commentaire + ending: Fin + not_ordered: Tu n'as pas commandé. + note: Note + order_sum: Total de la commande + sum: Total + supplier: Fourni par + title: Ta part de la commande %{order} + switch_order: + remaining: encore %{remaining} + title: Commandes en cours + update: + error_general: Suite à une erreur, la commande n'a pu être mise à jour. + error_stale: La commande n'a pas pu être mise à jour, car quelqu'un d'autre a commandé entre temps. + notice: La commande a bien été enregistrée. + helpers: + application: + edit_user: Modifier la liste des membres + role_admin: Administrateur + role_article_meta: Article + role_finance: Finances + role_orders: Commande + role_suppliers: FournisseusEs_rs + show_google_maps: Afficher la position sur Google maps + sort_by: Trier par %{text} + write_message: Écrire un message + deliveries: + new_invoice: Ajouter une nouvelle facture + show_invoice: Afficher la facture + orders: + option_choose: Choix d'unE fournisseusE_r + option_stock: Stock + order_pdf: Générer un PDF + select: + prompt: Faire un choix + submit: + create: sauvegarder %{model} + invite: + create: Envoyer une invitatio + message: + create: Envoyer un message + update: Sauvergarder les modifications + tasks: + required_users: Il manque encore %{count} camarades! + home: + apple_bar: + desc: ! 'Ce système de glands sert à comparer la durée du travail collectif auquel ta cellule a contribué (rapportée à la quantité commandée) avec + + la moyenne du travail effectué par toutes les cellules. + + Actuellement, cette moyenne est d''une heure de boulot pour %{amount} commandés.' + more_info: Plus d'informations + points: ! 'Nombre de glands: %{points}' + warning: ! 'Attention, si ta cellule a moins de %{threshold} glands, tu ne pourras plus commander! + + (ce seuil est fixé par la coop)' + changes_saved: Les modifications ont été sauvegardées. + index: + due_date_format: ! '%A, %d. %b' + messages: + title: Derniers messages reçus + view_all: Afficher tous les messages + my_ordergroup: + funds: ! '| Crédit disponible:' + last_update: La dernière mise à jour date du %{when} + title: Ma cellule + transactions: + amount: Montant + note: Note + title: Dernière transactio + view: Afficher un relevé de compte + when: Quand? + where: Qui? + ordergroup: + title: Niveau de participation de ta cellule + tasks_move: + action: accepter/refuser des boulots + desc: Tu as du boulot de prévu. + title: Accepter des boulot + tasks_open: + action: boulots disponibles + desc: Il y a %{size} + title: Boulots disponibles + title: Page d'accueil + your_tasks: Voilà le boulot que tu as accepté en ce moment + no_ordergroups: Tu ne fais encore partie d'aucune cellule + ordergroup: + account_summary: Relevé de compte + description: Description + funds: ! 'Crédit disponible:' + invite: Engrainer une nouvelle personne + people: Personnes + search: Rechercher ... + title: Ta cellule + ordergroup_cancelled: Tu ne fais plus partie de la cellule %{group}. + profile: + groups: + cancel: Quitter la coop + cancel_confirm: T'es sûrE de vouloir partir? + invite: Engrainer des nouveaux membres + title: Tu fais partie des équipes suivantes + title: Ton profil + user: + since: ! '(Membre depuis: %{when})' + title: ! '%{user}' + start_nav: + admin: Administration + finances: + accounts: Mettre à jour les compte + settle: Décompter des commandes + title: Espace trésorerie + foodcoop: Coop + members: Membre + new_ordergroup: Créer une nouvelle cellule + new_user: Ajouter un nouveau membre + orders: + end: Terminer des commandes + overview: Aperçu des commandes + title: Commandes + products: + edit: Mettre à jour les articles + edit_stock: Gérer les stocks + edit_suppliers: Gérer les fournisseusEs_rs + title: Gérer les articles + tasks: Ton boulot + title: Aller à... + write_message: Écrire un message + invites: + errors: + already_member: est déjà membre de la Boufcoop + modal_form: + body: Sur cette page, tu peux inviter une personne dans la cellule %{group} qui n'est pas encore membre de la Boufcoop.

Après sa première connexion elle sera automatiquement membre de la cellule.

+ title: Engrainer une personne + new: + action: Engrainer! + back: ou revenir en arrière + body:

Sur cette page, tu peux engrainer une personne qui ne fait pas encore partie de la Boufcoop à rejoindre la cellule %{group} + success: L'utilisatrice a été engrainée avec succès! + layouts: + application1: + title: Foodsoft - %{title} + email: + footer: ! '-- + + Foodsoft: %{foodsoft} + + Accueil de la Boufcoop: %{foodcoop} + + Aide: %{help}' + foodsoft: Foodsoft + header: + feedback: + desc: Tu as trouvé une erreur? Tu as des propositions, des idées, des critiques? + title: Retours + footer: Foodsoft, un logiciel libre pour gérer les Boufcoops. + help: Aide + logout: Déconnexion + ordergroup: Ta cellule + profile: Modifier ton profil + logo: coop + lib: + order_pdf: + page: page %{number} + login: + accept_invitation: + body: ! '

Tu viens d''être invité à rejoindre la cellule "%{group}" de la coopérative d''approvisionnement (bouffe-coop) %{foodcoop} !

+ +

Remplis ce formulaire si tu es d''accord pour être de la partie.

+ +

Ces données ne seront en aucun cas publiées, ou transmises à quiconque d''extérieur à la coop. + + Pour des raisons techniques, les membres de la coop qui s''occupent du site internet ont accès aux données, + + mais en ce qui concerne les autres membres de la coop, tu pourras choisir quelles données leurs sont visibles. + +' + submit: Créer un compte Foodsoft + title: Invitation chez les %{name} + controller: + accept_invitation: + notice: Ton compte vient d'être créé. Bienvenue! Tu peux maintenant te connecter. + error_group_invalid: Désolé, la cellule par laquelle tu as été invité a été supprimée entre temps. + 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: ! "Si tu as donné ton adresse email, tu vas maintenant recevoir un message \ncontenant 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: + body: ! '

Pas de problème, nous pouvons générer un nouveau mot de passe pour toi.

+ +

Pour cela, commence par saisir ci-dessous l''adresse email que tu as donné lors de ton inscription. + + Tu recevras ensuite un message avec de plus amples instructions.

' + submit: Demander un nouveau mot de passe + title: Mot de passe oublié? + new_password: + body:

Merci de saisir le nouveau mot de passe souhaité pour l'utilisateur %{user}

+ submit: Sauvegarder le nouveau mot de passe + title: Nouveau mot de passe + mailer: + dateformat: ! '%d %b' + feedback: + header: ! 'Le %{date}, %{user} a écrit:' + subject: Retour de %{email} + foodsoft_message: + footer: ! 'Répondre: %{reply_url} + + Afficher ce message dans ton navigateur: %{msg_url} + + Préférences des messages: %{profile_url}' + invite: + subject: Invitation à participer à une Bouffecoop + text: ! 'Salut! + + %{user} <%{mail}> vient de t''engrainer à rejoindre la cellule "%{group}". + + Pour accepter cet engrenage et ainsi faire partie de notre Boufcoop, visite: %{link} + + Ce lien ne sera valide que pour une seule visite et s''autodétruira le %{expires}.' + negative_balance: + subject: Compte dans le rouge! + text: ! 'CherEs %{group}, + + + Votre compte sur la bouffecoop est passé au rouge le %{when}, et son solde actuel est %{balance}. + + %{amount} ont été prélevés par %{user} en règlement de "%{note}". + + Il faudrait penser rapidement à remettre du crédit! + + + Message automatisé de %{foodcoop}' + not_enough_users_assigned: + subject: Il y a encore besoin de monde pour "%{task}" + text: ! 'CherE %{user}, + + + Il manque encore du monde le %{when} pour le boulot "%{task}" dont ton équipe est responsable. + + Si tu es dispo et ne t''es pas encore inscritE, c''est le moment de le faire: + + %{workgroup_tasks_url} + + + Pour voir ton agenda complet: %{user_tasks_url} + +' + order_result: + subject: ! 'Commande terminée: %{name}' + text0: ! 'CherEs %{ordergroup}, + + + La commande pour "%{order}" a été fermée le %{when} par %{user}. + + Voilà la liste des articles qui ont été commandés pour vous:' + text1: ! 'Prix total: %{sum} + + Afficher sur le site: %{order_url} + + + Message envoyé automatiquement par %{foodcoop}' + reset_password: + subject: Nouveau mot de passe pour %{username} + text: ! 'Salut %{user}, + + + Toi (ou quelqu''un d''autre) vient de demander un nouveau mot de passe sur le site de la bouffecoop. + + Pour le choisir, va sur la page suivante: %{link}. + + Ce lien n''est valide que pour une seule utilisation et expirera le %{expires}. + + Si tu as changé d''avis ou si tu n''es pas à l''origine de ce mail, aucune action n''est requise de ta part, et ton mot de passe restera inchangé. + + + Message automatiquement envoyé par Foodsoft.' + upcoming_tasks: + nextweek: ! 'Agenda de la semaine prochaine:' + subject: Tu as du boulot! + text0: ! 'CherE %{user}, + + + Tu t''es inscritE pour le boulot "%{task}", qui aura lieu demain (%{when}). + +' + text1: ! 'Mes boulots: %{user_tasks_url} + + + Ceci est un rappel automatisé envoyé par %{foodcoop}.' + messages: + create: + notice: Le message a bien été sauvegardé et est en cours d'envoi. + index: + new: Nouveau message + title: Messages + messages: + reply: Répondre + model: + reply_header: ! 'Le %{when}, %{user} a écrit:' + reply_indent: ! '> %{line}' + reply_subject: ! 'Re: %{subject}' + new: + list: + desc: Pour envoyer un message à tout le monde, passe par la mailing list "%{list}" + mail: par exemple en envoyant un email à %{email} + subscribe: Pour plus d'explications concernant la mailing list, consulte le %{link} + subscribe_msg: Il faudra peut être d'abord t'inscrire à la mailing list. + wiki: wiki (section mailing list) + no_user_found: ! 'Aucune utilisatrice correspondante n''a été trouvée ' + search: Rechercher ... + search_user: Rechercher une utilisatrice + title: Nouveau message + show: + all_messages: Aperçu des messages + from: ! 'De:' + reply: Répondre + sent_on: ! 'Envoyé le:' + subject: ! 'Sujet:' + title: Afficher le contenu du message + model: + delivery: + each_stock_article_must_be_unique: Chaque article en stock ne peut être listé qu'une seule fois dans la commande. + membership: + no_admin_delete: ! 'Pas moyen de quitter le navire: tu es le ou la dernièrE administratrice à bord!' + order_article: + error_price: doit être saisi et avoir un prix à jour + page: + redirect: Redirection vers [[%{title}]]... + user: + no_ordergroup: aucune cellule + navigation: + admin: + home: Aperçu + ordergroups: Cellules + title: Administration + users: Utilisatrices + workgroups: Équipes de travail + articles: + categories: Catégories + stock: Stock + suppliers: FournisseusEs_rs/Article + title: Article + dashboard: Tableau de bord + finances: + accounts: gérer la trésorerie + balancing: Décompter des commandes + home: Aperçu + invoices: Factures + title: Trésorerie + foodcoop: Boufcoop + members: Membre + messages: Messages + ordergroups: Cellule + orders: + archive: Mes commandes + manage: Gestion des commandes + ordering: Commander! + title: Commande + tasks: Boulots + wiki: + all_pages: Toutes les pages + home: Page d'accueil + title: Wiki + workgroups: Equipe + number: + currency: + format: + delimiter: . + format: ! '%n %u' + precision: 2 + separator: ! ',' + significant: false + strip_insignificant_zeros: false + unit: € + format: + delimiter: . + precision: 2 + separator: ! ',' + significant: false + strip_insignificant_zeros: false + human: + decimal_units: + format: ! '%n %u' + units: + billion: + one: milliard + other: milliards + million: millions + quadrillion: + one: billiard + other: billiards + thousand: mille + trillion: billions + unit: + format: + delimiter: + precision: 1 + significant: true + strip_insignificant_zeros: true + storage_units: + format: ! '%n %u' + units: + byte: + one: Octet + other: Octets + gb: Go + kb: kB + mb: MB + tb: TB + percentage: + format: + delimiter: + precision: + format: + delimiter: + ordergroups: + edit: + title: Modifier les cellules + index: + title: Cellule + model: + error_single_group: ! '%{user} fait déjà partie d''une autre cellule' + invalid_balance: n'est pas un nombre valide + orders: + articles: + article_count: ! 'Nombre d''articles commandés:' + name: Nom + prices: Prix net/brut + prices_sum: Totaux (des prix nets/bruts) + unit_quantity: Nombre de lots + units_full: Nombre de lots complet + units_ordered: Nombre d'unités commandées + create: + notice: La liste de commande a été créée. + edit: + title: Modifier la liste de commande. + fax: + amount: Quantité + articles: Article + customer_number: Numéro de client + delivery_day: Jour de livraison + heading: Commande pour %{name} + name: Nom + number: Numéro + to_address: Adresse du destinataire + finish: + notice: La commande a été terminée. + form: + name: Nom + note: Note + origin: Origine + prices: Prix (net/coop) + select_all: Tout sélectionner + stockit: Disponible + supplier: Productrice_teur + title: Article + unit_quantity: Lots + index: + action_end: Terminer + confirm_delete: Vraiment supprimer la commande? + confirm_end: Veux tu vraiment mettre fin à la commande %{order}? Attention, il n'y aura pas d'annulation possible. + ended_orders: Commandes terminées + ending: Fin + new_order: Créer une nouvelle commande + no_open_orders: Il n'y a aucune commande en cours en ce moment. + note: Note + open_orders: Commandes en cours + supplier: FournisseusE_r + title: Gérer les commande + model: + error_closed: Cette commande a déjà été décomptée + error_nosel: Au minimum un article doit être sélectionné + error_starts_before_ends: doit être postérieur à la date de début de la commande (ou bien être laissé vierge) + notice_close: ! 'Commande: %{name}, jusqu''au %{ends}' + stock: Stock + new: + title: Créer une nouvelle commande + orders: + ending: Fin + start: Début + status: Statut + supplier: FournisseurE + show: + action_end: Terminer! + amounts: ! 'Total net/brut:' + articles: Aperçu des article + articles_ordered: ! 'Articles commandés:' + begin: ! 'Début:' + comments: + title: Commentaire + comments_link: Commenaire + confirm_delete: Veux-tu vraiment supprimer la commande? + confirm_end: Veux tu vraiment terminer la commande %{order}? Pas d'annulation possible. + created_by: ! 'Créée par:' + download: + article_pdf: Liste des articles en PDF + download_file: Télécharger + fax_pdf: Fax au format PDF + fax_txt: Fax au format texte + group_pdf: Liste des cellules en PDF + matrix_pdf: Matrice de distribution en PDF + title: Télécharger + ending: ! 'Fin:' + group_orders: ! 'Commandes des cellules:' + note: ! 'Note:' + sort_article: Trié par article + sort_group: Trié par cellules + supplier: FournisseurE + title: ! 'Commande: %{name}' + warn_not_closed: Attention, cette commande n'a pas encore été décomptée! + state: + closed: décomptée + finished: terminée + open: en cours + update: + notice: La commande a été mise à jour. + pages: + all: + new_page: Créer une nouvelle page + recent_changes: Changement récents + search: + action: Recherche + placeholder: Titre de la page ... + site_map: Aide à la navigation + title: Toutes les pages du wiki + title_list: Liste des pages + body: + title_toc: Contenu + create: + notice: La page a bien été créée. + cshow: + error_noexist: Cette page n'existe pas! + redirect_notice: Redirigé à partir de %{page}... + destroy: + notice: La page '%{page}' et toutes ses descendantes ont bien été supprimées. + edit: + title: Modifier cette page + error_stale_object: Cette page est en cours de modification par un autre utilisateur. Merci de réessayer plus tard. + form: + help: + bold: gra + external_link_ex: Pages extérieures + external_links: Liens externes + heading: Plan %{level} + headings: En-tête + italic: italique + list_item_1: Premier item + list_item_2: Deuxième item + noformat: Pas de formatage + ordered_list: Enumérations + section_block: Format de paragraphe + section_character: Format de charactère + section_link: Format des lien + section_table: Format du tableau + see_tables: Voir %{tables_link} + tables_link: Tableaux + text: texte + title: Assistant de mise en forme rapide + unordered_list: Liste non ordonnée + wiki_link_ex: Page de wiki du Foodsoft + wiki_links: Liens Wiki + preview: Aperçu + last_updated: Dernièrement mis à jour + new: + title: Ajouter une nouvelle page au Wiki + page_list_item: + date_format: ! '%a, %d. %B %Y %H:%M:%S' + show: + date_format: ! '%d.%m.%y %H:%M' + delete: Supprimer la page + delete_confirm: Attention, tous les contenus seront aussi supprimés. T'es sûrE de ton coup? + edit: Modifier la page + last_updated: Dernière modification le %{when} par %{user} + subpages: Sous-pages + title_versions: Versions + versions: Versions (%{count}) + title: Titre + update: + notice: La page a été mise à jour + version: + author: ! 'Auteur: %{user}' + date_format: ! '%a, %d.%m.%Y, %H:%M heure' + revert: Revenir à cette version + title: ! '%{title} - Version %{version}' + title_version: Versio + view_current: Afficher la version actuelle + sessions: + logged_in: Connecté! + logged_out: Déconnecté! + login_invalid: Identifiant ou mot de passe invalide + new: + forgot_password: Mot de passe oublié? + login: Te connecter + nojs: Attention, les cookies et le javascript doivent être activés! Merci de désactiver %{link}. + noscript: NoScript + password: Mot de pass + title: Te connecter à Foodsoft + user: Utilisatrice + shared: + articles_by_articles: + ordered: Commandé (Quantité + Tolérance) + ordergroup: Cellul + price: Prix total + received: Reçu + articles_by_groups: + fc_price: Prix coop + fc_price_desc: Prix avec TVA, consigne et part de la coop inclus. + name: Nom + price: Prix total + unit: Unité + unit_quantity: U/L + unit_quantity_desc: Unités par lot + units: Quantité + units_desc: Unités assignées + group: + access: Accès à + activated: activé + address: Adresse + apple_limit: Minimum de glands + contact: Contact + deactivated: désactivé + description: Description + members: Membre + no_weekly_job: aucun boulot hebdomadaire n'a été défini + weekly_job: Boulot hebdomadaire + group_form_fields: + search: Recherche... + search_user: Rechercher par utilisatrice + title: Boulots hebdomadaires + user_not_found: Aucune utilisatrice n'a été trouvée. + loginInfo: + edit_profile: Modifier le profil + feedback: + desc: Tu as détecté une erreur? Tu as des propositions, des idées, des critiques? + title: Retours + help: Aide + homepage_title: Vers la page d'accueil de la bouffecoop + logout: Te déconnecter + profile: Profil + memberships: + current_members: + drop: désinscrire + no_members: ! '%{group} n''a aucun membre pour le moment.' + members: + already_members: Sont déjà membre + desc: Sur cette page, tu peux gérer les membres de l'équipe, et aussi %{link} un nouveau membre. + invite: engrainer + invite_someone: Inviter quelqu'unE + no_members_yet: Ne sont pas encore membre + title: Membre de %{group} + non_members: + add: ajouter + open_orders: + ending: Fin + no_open_orders: Il n'y a aucune commande en cours en ce moment + not_enough_apples: Désolé, ta cellule n'a pas assez de glands pour pouvoir commander! + supplier: FournisseurE + title: Commandes en cours + total: Total + total_sum: Total + who_ordered: Qui a commandé? + workgroup_members: + title: Membres des cellules + simple_form: + error_notification: + default_message: Une erreur s'est produite. Merci de vérifier le formulaire. + hints: + article: + unit: par exemple. kg ou 1l ou 500g + message: + private: Le message n'apparaît pas sur la boîte de réception du Foodsoft + order_article: + units_to_order: Nombre de lots livrés + update_current_price: Modifie aussi le prix des commandes en cours + stock_article: + copy_stock_article: + name: Merci de modifier + edit_stock_article: + price:
  • Modification du prix enregistrée.
  • Si nécessaire %{stock_article_copy_link}.
+ supplier: + supplier: + min_order_quantity: La quantité minimum à commander est affichée pendant la commande et doit motiver + task: + duration: Combien de temps dure le boulot, 1 à 3 heures + required_users: De combien d'utilisatrices avons-nous besoin au total!, + tax: En pourcentage, le standard est de 7,0 + labels: + article: + article_category: Catégorie + manufacturer: Producteur + name: Nom + note: Note + origin: Lieu de productio + unit: Unité + article_category: + description: Description + name: Nom + defaults: + amount: Montant + date: Date + deposit: Consigne + description: Description + email: Email + note: Note + order_number: ! 'Numéro ' + ordergroup: Cellule + password: Mot de passe + password_confirmation: Confirmation du mot de passe + phone: Téléphone + price: Prix (net) + tax: TVA + title: Titre + unit_quantity: Unités par lot + user_tokens: Membres + delivery: + delivered_on: Date de livraison + supplier: Fournisseuse_r + group_order_article: + ordergroup_id: Cellul + result: Quantité + invoice: + amount: Montant + date: Date de facturation + delivery: Réapprovisionnement + deposit: Consigne facturée + deposit_credit: Consigne remboursée + note: Note + number: Numéro + order: Commande + paid_on: Payée le + supplier: Fournisseuse_r + message: + body: Contenu + group_id: Groupe + private: Privé + recipient_tokens: Destinataires + sent_to_all: Envoyer à tous les membres + subject: Sujet + order: + ends: Terminée le + starts: Commence le + order_article: + units_to_order: Quantité + update_current_price: Mettre à jour le prix global + order_comment: + text: Commenter cette commande... + ordergroup: + contact_address: Adress + contact_person: Personne à contacter + contact_phone: Téléphone + ignore_apple_restriction: Ne pas interdire la commande aux cellules pauvres en glands + page: + body: Contenu + parent_id: Page parente + settings: + messages: + send_as_email: Recevoir les messages par email + notify: + negative_balance: Envoyer un avertissement si ta cellule est dans le rouge. + order_finished: Envoyer un résumé de la commande finale (après la fermeture) + upcoming_tasks: Envoyer un rappel des prochains boulots auxquels tu es inscritE + profile: + email_is_public: Permettre aux autres membres de voir ton adresse email. + language: Langue + name_is_public: Permettre aux autres membres de voir ton nom. + phone_is_public: Permettre aux autres membres de voir ton numéro de téléphone. + settings_group: + messages: Messages + privacy: Confidentialité + stock_article: + supplier: FournisseurE + supplier: + address: Adresse + contact_person: Contact + customer_number: Numéro de client + delivery_days: Jours de livraison + email: Email + fax: Fa + is_subscribed: abonné? + min_order_quantity: Quantité minimale à commander + name: Nom + note: Note + order_howto: Comment commander + phone: Téléphone + phone2: Autre téléphone + url: Site web + task: + done: Fait? + due_date: Pour quand? + duration: Durée + name: Nom + required_users: Nombre de personnes nécessaires + user_list: Responsables inscritEs + workgroup: Equipe + user: + email: Email + last_name: Nom de famille + name: Nom + nick: Identifiant + ordergroup: Cellul + phone: Téléphone + workgroup: + one: Cellule + other: Cellule + workgroup: + next_weekly_tasks_number: Combien de temps en avance les boulots doivent ils être visibles sur le site? + role_admin: Administration + role_article_meta: Base de données des article + role_finance: Trésorerie + role_orders: Gestion des commande + role_suppliers: Contact avec les fournisseusEs_rs + 'no': Non + options: + settings: + profile: + language: + de: Allemand + en: Anglais + fr: Français + nl: Néerlandais + required: + mark: ! '*' + text: requis + 'yes': Oui + stock_takings: + create: + notice: L'inventaire a été créé avec succès. + edit: + title: Modifier les données de l'inventaire + index: + new_inventory: Commencer un nouvel inventaire + title: Aperçu de l'inventaire + new: + create: créer + stock_articles: Articles en stock + temp_inventory: inventaire provisoire + text_deviations: ! 'Saisir ici les déviations constatées par rapport à %{inv_link}. + + En cas de manque, utiliser un signe ''-''.' + text_need_articles: ! 'Pour pouvoir prendre un compte de nouveaux articles en stock, + + ils doivent d''abord être %{create_link}.' + title: Commencer un nouvel inventaire + show: + amount: Quantité + article: Article + confirm_delete: Vraiment annuler cet inventaire? + date: Date + note: Note + overview: Aperçu de l'inventaire + supplier: FournisseusE_r + title: Afficher l'inventaire + unit: Unité + stock_takings: + confirm_delete: T'es sûrE de ton coup? + date: Date + note: Note + update: + notice: Les données de l'inventaire ont été mises à jour. + stockit: + check: + not_empty: ! '%{name} ne peut pas être supprimé, car il y en a encore en stock.' + destroy: + notice: L'article en stock %{name} a bien été supprimé. + edit: + title: Modifier l'article + form: + price_hint: Pour éviter que ça soit le bazar, les prix des articles en stock ne peuvent plus être modifiés. + history: + change_quantity: Modification + datetime: Temps + delivery: Livraison + new_quantity: Nouveau stock + order: Commande + reason: Raison + stock_changes: Afficher l'historique pour "%{article_name}" + stock_taking: Inventaire + index: + article: + article: Article + available: disponible + category: Catégorie + ordered: commandés + price: Prix + stock: en Stock + supplier: FournisseusE_r + unit: Unité + vat: TVA + confirm_delete: T'es sûrE de ton coup? + new_delivery: Nouvelle livraison... + new_stock_article: Créer un nouvel article en stock + new_stock_taking: Commencer un inventaire + order_online: Mettre la commande de renouvellement du stock en ligne + show_stock_takings: Aperçu des inventaire + stock_count: ! 'Nombre d''articles:' + stock_worth: ! 'Valeur actuelle du stock:' + toggle_unavailable: Afficher/cacher les articles actuellement indisponible + view_options: Préférences d'affichage + new: + search_text: ! 'Rechercher des articles dans tous les catalogues:' + title: Créer un nouvel article en stock + stock_create: + notice: L'article a été sauvegardé. + stock_update: + notice: L'article a été sauvegardé. + suppliers: + create: + notice: FournisseusE_r misE à jour + destroy: + notice: FournisseusE_r suppriméE + edit: + title: Modifier le/la fournisseurE + index: + action_import: Importer unE fournisseurE d'une base de données extérieure + action_new: Ajouter unE fournisseurE + articles: Articles (%{count}) + confirm_del: Attention, veux-tu vraiment supprimer le/la fournisseurE %{name}? + deliveries: Livraisons (%{count}) + stock: en stock (%{count}) + title: FournisseurEs + new: + title: Ajouter unE fournisseurE + shared_supplier_note: Le/la fournisseurE a été associé a la base de données extérieure. + shared_suppliers: + body: ! '

Les fournisseurEs de la base de données extérieure sont affichéEs ici.

+ +

Tu peux encore en importer des nouveaux, en t''y abonnant ci-dessous.

+ +

De cette façon, le/la fournisseurE est automatiquement ajoutéE à la base de données.

' + subscribe: s'abonner + subscribe_again: s'abonner à nouveau + supplier: FournisseurE + title: Listes externes + show: + confirm_delete: Tu es sûrE de ton coup? + last_deliveries: Dernières livraisons + new_delivery: Commencer un nouveau réapprovisionnement + show_deliveries: Afficher tous les réapprovisionnements + update: + notice: Les données du_de la fournisseurE ont été mises à jour + support: + array: + last_word_connector: et + two_words_connector: et + words_connector: ! ',' + tasks: + accept: + notice: Tu as accepté ce boulot + archive: + title: Historique du boulot + archive_tasks: + due_date: Échéance + task: Sujet + task_format: ! '%{name} (%{duration}h)' + who: Personnes en charge + create: + notice: Le boulot a été généré + destroy: + notice: Le boulot a été supprimé + edit: + title: Modifier les données du boulot + warning_periodic: ! 'Avertissement: + + Ce boulot fait partie d''une série de boulots hebdomadaires. + + Si les modifications sont enregistrées, il sera retiré de la série et converti en boulot ordinaire.' + error_not_found: Aucune équipe n'a été trouvée. + form: + search: + hint: Rechercher par utilisatrice_teur + noresult: AucunE utilisatricE_teur n'a été trouvéE + placeholder: Recherche... + submit: + periodic: Sauvegarder le boulot hebdomadaire + index: + show_group_tasks: Afficher les boulots pour cette équipe + title: Boulots + title_non_group: Boulots ouverts à tous + list: + accept_task: Te charger de ce boulot + done: Effectué + done_q: Effectué? + due_date: A faire pour le + mark_done: Marquer ce boulot comme étant effectué + reject_task: Refuser ce boulot + task: Descriptio + task_format: ! '%{name} (%{duration}h)' + who: Qui le fait? + who_hint: (Combien manquent encore?) + nav: + all_tasks: Tous les boulots + archive: Boulots déjà effectués (archive) + group_tasks: Boulots d'équipe + my_tasks: Mes boulots + new_task: Définir un nouveau boulot + new: + title: Définition d'un nouveau boulot + repeated: Ce boulot a lieu toutes les semaines. + set_done: + notice: L'agenda a été mis à jour. + show: + accept_task: Te charger de ce boulot. + confirm_delete_group: Veux-tu vraiment supprimer ce boulot hebdomadaire? + delete_group: Supprimer ce boulot + due_date: Echéance + hours: ! '%{count}h' + mark_done: Marquer comme effectué + reject_task: Refuser ce boulot + title: Afficher la description du boulot + update: + 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}. ' + tasks_link: par là-bas. + title: Ton boulot + title_accepted: Boulots acceptés + title_open: Boulots disponible + workgroup: + title: Boulots pour l'%{workgroup} + title_all: Boulot de l'équipe + time: + am: le matin + formats: + default: ! '%A, %d. %B %Y, %Hh%M' + long: ! '%A, %d. %B %Y, %Hh%M' + short: ! '%d. %B, %Hh%M ' + pm: après-midi + ui: + close: Fermer + delete: Supprimer + edit: Modifier + history: Afficher l'historique + marks: + close: ! '×' + success: + or_cancel: ou supprimer + please_wait: Merci de patienter... + save: Sauvegarder + show: Afficher + views: + pagination: + first: ! '«' + last: ! '»' + next: ! '›' + previous: ! '‹' + truncate: ! '...' + workgroups: + 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. ' + index: + title: Équipes + update: + notice: L'équipe a été mise à jour diff --git a/config/locales/nl.yml b/config/locales/nl.yml index f5e1f5dc..983b4321 100644 --- a/config/locales/nl.yml +++ b/config/locales/nl.yml @@ -1560,6 +1560,7 @@ nl: language: de: Duits en: Engels + fr: Frans nl: Nederlands required: mark: ! '*' From 707f4871285e027bed2bb22fd49bc766417891ec Mon Sep 17 00:00:00 2001 From: wvengen Date: Sat, 7 Sep 2013 01:34:34 +0200 Subject: [PATCH 52/59] update spec gems to make tests work again --- Gemfile | 4 +++- Gemfile.lock | 22 ++++++++++++---------- lib/tasks/rspec.rake | 3 +++ 3 files changed, 18 insertions(+), 11 deletions(-) create mode 100644 lib/tasks/rspec.rake diff --git a/Gemfile b/Gemfile index 634eda63..e80314ed 100644 --- a/Gemfile +++ b/Gemfile @@ -76,8 +76,10 @@ group :test do gem 'rspec-rails' gem 'factory_girl_rails', '~> 4.0' gem 'faker' - gem 'capybara' + # version requirements to avoid problem http://stackoverflow.com/questions/18114544 + gem 'capybara', '~> 2.1.0' # webkit and poltergeist don't seem to work yet + gem 'selenium-webdriver', '~> 2.35.1' gem 'database_cleaner' gem 'simplecov', require: false # need to include rspec components before i18n-spec or rake fails in test environment diff --git a/Gemfile.lock b/Gemfile.lock index d19faceb..be91e252 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -62,13 +62,12 @@ GEM net-ssh-gateway (>= 1.1.0) capistrano-ext (1.2.1) capistrano (>= 1.0.0) - capybara (2.0.2) + capybara (2.1.0) mime-types (>= 1.16) nokogiri (>= 1.3.3) rack (>= 1.0.0) rack-test (>= 0.5.4) - selenium-webdriver (~> 2.0) - xpath (~> 1.0.0) + xpath (~> 2.0) childprocess (0.3.9) ffi (~> 1.0, >= 1.0.11) chronic (0.9.0) @@ -99,7 +98,7 @@ GEM railties (>= 3.0.0) faker (1.1.2) i18n (~> 0.5) - ffi (1.4.0) + ffi (1.9.0) haml (3.1.7) haml-rails (0.3.5) actionpack (>= 3.1, < 4.1) @@ -151,8 +150,9 @@ GEM activesupport (~> 3.1) polyamorous (~> 0.5.0) mime-types (1.21) + mini_portile (0.5.1) mono_logger (1.1.0) - multi_json (1.7.6) + multi_json (1.7.9) mysql2 (0.3.11) net-scp (1.1.1) net-ssh (>= 2.6.5) @@ -161,7 +161,8 @@ GEM net-ssh (2.6.7) net-ssh-gateway (1.2.0) net-ssh (>= 2.6.5) - nokogiri (1.5.10) + nokogiri (1.6.0) + mini_portile (~> 0.5.0) pdf-reader (1.2.0) Ascii85 (~> 1.0.0) hashery (~> 2.0) @@ -236,10 +237,10 @@ GEM select2-rails (3.4.2) sass-rails thor (~> 0.14) - selenium-webdriver (2.31.0) + selenium-webdriver (2.35.1) childprocess (>= 0.2.5) multi_json (~> 1.0) - rubyzip + rubyzip (< 1.0.0) websocket (~> 1.0.4) simple-navigation (3.9.0) activesupport (>= 2.3.2) @@ -296,7 +297,7 @@ GEM wikicloth (0.8.0) builder expression_parser - xpath (1.0.0) + xpath (2.0.0) nokogiri (~> 1.3) PLATFORMS @@ -311,7 +312,7 @@ DEPENDENCIES bullet capistrano (= 2.13.5) capistrano-ext - capybara + capybara (~> 2.1.0) client_side_validations coffee-rails (~> 3.2.1) daemons @@ -339,6 +340,7 @@ DEPENDENCIES ruby-prof sass-rails (~> 3.2.3) select2-rails + selenium-webdriver (~> 2.35.1) simple-navigation simple-navigation-bootstrap simple_form diff --git a/lib/tasks/rspec.rake b/lib/tasks/rspec.rake new file mode 100644 index 00000000..45a78604 --- /dev/null +++ b/lib/tasks/rspec.rake @@ -0,0 +1,3 @@ +require 'rspec/core/rake_task' +RSpec::Core::RakeTask.new(:spec) +task :default => :spec From 12c0636941da2fef748d52498c7ed32fec7fa7f8 Mon Sep 17 00:00:00 2001 From: wvengen Date: Tue, 10 Sep 2013 10:27:13 +0200 Subject: [PATCH 53/59] fix i18n buglets (closes #167) --- app/views/finance/ordergroups/_ordergroups.html.haml | 4 ++-- app/views/pages/_form.html.haml | 2 +- app/views/stock_takings/edit.html.haml | 2 +- app/views/stock_takings/new.html.haml | 2 +- app/views/stockit/index.html.haml | 2 +- app/views/tasks/_nav.haml | 2 +- app/views/tasks/user.html.haml | 2 +- config/locales/de.yml | 5 +++++ 8 files changed, 13 insertions(+), 8 deletions(-) diff --git a/app/views/finance/ordergroups/_ordergroups.html.haml b/app/views/finance/ordergroups/_ordergroups.html.haml index a273979d..4e67df73 100644 --- a/app/views/finance/ordergroups/_ordergroups.html.haml +++ b/app/views/finance/ordergroups/_ordergroups.html.haml @@ -5,7 +5,7 @@ %thead %tr %th= sort_link_helper t('.name'), "name", :per_page => @per_page - %th Kontakt + %th= t '.contact' %th.numeric= sort_link_helper t('.account_balance'), "account_balance", :per_page => @per_page %th %tbody @@ -17,4 +17,4 @@ %td = link_to t('.new_transaction'), new_finance_ordergroup_transaction_path(ordergroup), class: 'btn btn-mini' = link_to t('.account_statement'), finance_ordergroup_transactions_path(ordergroup), class: 'btn btn-mini' - \ No newline at end of file + diff --git a/app/views/pages/_form.html.haml b/app/views/pages/_form.html.haml index a3de5652..5b84baa9 100644 --- a/app/views/pages/_form.html.haml +++ b/app/views/pages/_form.html.haml @@ -56,7 +56,7 @@ %pre * #{t '.help.list_item_1'} %pre - ** #{t '.help_list_item_2'} + ** #{t '.help.list_item_2'} %tr %td= t '.help.ordered_list' %td diff --git a/app/views/stock_takings/edit.html.haml b/app/views/stock_takings/edit.html.haml index 09312f6e..66f5752d 100644 --- a/app/views/stock_takings/edit.html.haml +++ b/app/views/stock_takings/edit.html.haml @@ -4,4 +4,4 @@ = f.input :date = f.input :note = f.submit - = link_to t('ui.cancel'), stock_takings_path + = link_to t('ui.or_cancel'), stock_takings_path diff --git a/app/views/stock_takings/new.html.haml b/app/views/stock_takings/new.html.haml index dfa9e03b..51239ba4 100644 --- a/app/views/stock_takings/new.html.haml +++ b/app/views/stock_takings/new.html.haml @@ -14,4 +14,4 @@ = render :partial => 'stock_change', :collection => @stock_taking.stock_changes .form-actions = f.submit class: 'btn' - = link_to t('ui.cancel'), stock_takings_path + = link_to t('ui.or_cancel'), stock_takings_path diff --git a/app/views/stockit/index.html.haml b/app/views/stockit/index.html.haml index 4673b967..477e5816 100644 --- a/app/views/stockit/index.html.haml +++ b/app/views/stockit/index.html.haml @@ -1,4 +1,4 @@ -- title "Lager (#{StockArticle.available.count})" +- title t('.title', article_count: StockArticle.available.count) - content_for :javascript do :javascript $(function() { diff --git a/app/views/tasks/_nav.haml b/app/views/tasks/_nav.haml index 8fec6188..ecf28c36 100644 --- a/app/views/tasks/_nav.haml +++ b/app/views/tasks/_nav.haml @@ -4,7 +4,7 @@ - content_for :sidebar do .well.well-small %ul.nav.nav-list - %li.nav-header Seiten + %li.nav-header= t '.pages' %li= link_to t('.my_tasks'), user_tasks_path %li= link_to t('.all_tasks'), tasks_path %li= link_to t('.archive'), archive_tasks_path diff --git a/app/views/tasks/user.html.haml b/app/views/tasks/user.html.haml index fd13ce2a..095cd1de 100644 --- a/app/views/tasks/user.html.haml +++ b/app/views/tasks/user.html.haml @@ -1,4 +1,4 @@ -- title "Meine Aufgaben" +- title t('.title') = render 'nav' - unless @unaccepted_tasks.empty? diff --git a/config/locales/de.yml b/config/locales/de.yml index 650dc27b..149bbc26 100644 --- a/config/locales/de.yml +++ b/config/locales/de.yml @@ -719,6 +719,7 @@ de: ordergroups: account_balance: Kontostand account_statement: Kontoauszug + contact: Kontakt name: Name new_transaction: Neue Transaktion update: @@ -1602,6 +1603,7 @@ de: contact_person: Kontaktperson contact_phone: Telefon ignore_apple_restriction: Bestellstop bei zu wenig Äpfeln ignorieren + name: Name page: body: Inhalt parent_id: Oberseite @@ -1743,6 +1745,7 @@ de: show_stock_takings: Inventurübersicht stock_count: ! 'Artikelanzahl:' stock_worth: ! 'Aktueller Lagerwert:' + title: Lager (%{article_count}) toggle_unavailable: Nicht verfügbare Artikel zeigen/verstecken view_options: Ansichtsoptionen new: @@ -1829,6 +1832,7 @@ de: who: Wer machts? who_hint: (Wie viele werden noch benötigt?) nav: + pages: Seiten all_tasks: Alle Aufgaben archive: Erledigte Aufgaben (Archiv) group_tasks: Gruppenaufgaben @@ -1852,6 +1856,7 @@ de: notice: Aufgabe wurde aktualisiert notice_converted: Aufgabe wurde aktualisiert und in eine gewöhnliche Aufgabe umgewandelt user: + title: Meine Aufgaben more: Nichts zu tun? %{tasks_link} gibt es bestimmt Arbeit tasks_link: Hier title: Meine Aufgaben From 6418790ef5db503f8fe257038ee3883d95ee72cb Mon Sep 17 00:00:00 2001 From: wvengen Date: Tue, 10 Sep 2013 10:46:02 +0200 Subject: [PATCH 54/59] localeapp roundtrip, with updated translations --- config/locales/de.yml | 3 +- config/locales/en.yml | 4 + config/locales/fr.yml | 450 +++++++++++++++++++++--------------------- config/locales/nl.yml | 65 +++--- 4 files changed, 270 insertions(+), 252 deletions(-) diff --git a/config/locales/de.yml b/config/locales/de.yml index 149bbc26..43aed756 100644 --- a/config/locales/de.yml +++ b/config/locales/de.yml @@ -1832,12 +1832,12 @@ de: who: Wer machts? who_hint: (Wie viele werden noch benötigt?) nav: - pages: Seiten all_tasks: Alle Aufgaben archive: Erledigte Aufgaben (Archiv) group_tasks: Gruppenaufgaben my_tasks: Meine Aufgaben new_task: Neue Aufgabe erstellen + pages: Seiten new: title: Neue Aufgabe erstellen repeated: Aufgabe wird wöchentlich wiederholt @@ -1856,7 +1856,6 @@ de: notice: Aufgabe wurde aktualisiert notice_converted: Aufgabe wurde aktualisiert und in eine gewöhnliche Aufgabe umgewandelt user: - title: Meine Aufgaben more: Nichts zu tun? %{tasks_link} gibt es bestimmt Arbeit tasks_link: Hier title: Meine Aufgaben diff --git a/config/locales/en.yml b/config/locales/en.yml index 55b7190b..8c655949 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -721,6 +721,7 @@ en: ordergroups: account_balance: Account balance account_statement: Account statement + contact: Contact name: Name new_transaction: New transaction update: @@ -1604,6 +1605,7 @@ en: contact_person: Contact person contact_phone: Phone ignore_apple_restriction: Ignore order stop by apple points restriction + name: Name page: body: Body parent_id: Parent page @@ -1745,6 +1747,7 @@ en: show_stock_takings: Inventory overview stock_count: ! 'Number of articles:' stock_worth: ! 'Current stock value:' + title: Stock (%{article_count}) toggle_unavailable: Show/hide unavailable articles view_options: View options new: @@ -1836,6 +1839,7 @@ en: group_tasks: Group tasks my_tasks: My tasks new_task: Create new task + pages: Pages new: title: Create new tasks repeated: Task is repeated weekly diff --git a/config/locales/fr.yml b/config/locales/fr.yml index aa01d181..1675943d 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -40,7 +40,7 @@ fr: availability: l'article est-il disponible? deposit: consigne fc_price: prix final - fc_share: prélèvement pour la coop + fc_share: supplément boufcoop gross_price: prix brut price: prix net tax: TVA @@ -95,61 +95,61 @@ fr: other: ! '%{model} n''a pu être sauvegardé à cause de %{count} erreurs.' models: article: Article - article_category: Catégorie d'article - delivery: Livraison - financial_transaction: Opération de trésorerie - invoice: Facture + article_category: la nouvelle catégorie + delivery: le nouveau réapprovisionnement + financial_transaction: la transaction + invoice: la nouvelle facture message: Message - order: Commande + order: la nouvelle commande order_article: Article à commander - order_comment: Commentaire - ordergroup: Cellule - stock_article: Article en stock + order_comment: un nouveau commentaire + ordergroup: la nouvelle cellule + stock_article: l'article à stocker stock_taking: Inventaire supplier: FournisseusE_r - task: Boulot - user: Utilisatrices - workgroup: Equipe + task: comme nouveau boulot + user: le nouveau membre + workgroup: la nouvelle équipe admin: access_to: accès à actions: Actions base: index: all_ordergroups: Toutes les cellules - all_users: Toutes les utilisatrices + all_users: TouTEs les membres all_workgroups: Toutes les équipes created_at: créé le - first_paragraph: Les cellules et les utilisateurs du Foodsoft peuvent être administrés sur cette page. + first_paragraph: Les cellules et les membres de la boufcoop peuvent être administrés sur cette page. groupname: nom de la cellule members: membres name: nom new_ordergroup: Nouvelle cellule - new_user: Nouvelle utilisatrice + new_user: NouveLLE_eau membre new_workgroup: Nouvelle équipe - newest_groups: cellules les plus récentes - newest_users: utilisateurs les plus récents + newest_groups: Cellules les plus récentes + newest_users: Membres les plus récents title: Administration type: type username: identifiant confirm: Veux-tu vraiment supprimer %{name}? ordergroups: destroy: - error: ! 'La cellule n''a pas pu être supprimée: %{error}' + error: ! 'La cellule n''a pas pu être dissoute: %{error}' notice: La cellule a été supprimée edit: title: Modifier les informations sur la cellule form: - first_paragraph: Invite des nouveaux membres %{url}. + first_paragraph: Invite de nouveaux membres %{url}. here: ici index: - first_paragraph: Sur cette page, %{url} peut être ajouté, et des cellules peuvent être modifiées ou supprimées. - new_ordergroup: Créer une nouvelle cellule - new_ordergroups: nouvelles cellules - second_paragraph: ! 'Attention à bien noter la différence entre une équipe et une cellule: une cellule est toujours associée à un compte de crédit et sert à passer des commandes, tandis qu''une %{url} (par exemple l''équipe distribution) s''occupe des boulots utiles à la coop. Les utilisatrices appartiennent toujours à une et une seule cellule, mais peuvent faire partie de plusieurs équipes.' + first_paragraph: Sur cette page, des cellules peuvent être %{url}, modifiées ou bien dissoutes. + new_ordergroup: Définir une nouvelle cellule + new_ordergroups: créées + second_paragraph: ! 'Attention à bien noter la différence entre une équipe et une cellule: chaque membre fait partie d''une cellule, qui possède un certain crédit servant à payer les commandes, tandis qu''une %{url} (par exemple l''équipe distribution) s''occupe des boulots utiles à la boufcoop. Les membres appartiennent toujours à une et une seule cellule, mais peuvent faire partie de plusieurs équipes.' title: Cellules workgroup: équipe new: - title: Créer une nouvelle cellule + title: Définir une nouvelle cellule ordergroups: address: Adresse contact: Contact @@ -163,14 +163,14 @@ fr: search_placeholder: nom ... users: edit: - title: modifier les données sur l'utilisatrice + title: modifier les données sur le_la membre index: - first_paragraph: Sur cette page, tu peux %{url}, modifier ou bien supprimer des utilisatrices. - new_user: Ajouter une nouvelle utilisatrice + first_paragraph: Sur cette page, tu peux %{url}, modifier ou bien retirer des membres. + new_user: Ajouter unE nouveLLE_eau membre new_users: ajouter - title: Administration des utilisatrices + title: Administration des membres new: - title: Ajouter une nouvelle utilisatrice + title: Ajouter unE nouveLLE_eau membre show: confirm: Veux-tu vraiment expulser %{user}? email: Email @@ -194,27 +194,27 @@ fr: edit: title: Modifier les données sur l'équipe form: - first_paragraph: Des nouveaux membres peuvent être invités %{url}. + first_paragraph: De nouveaux membres peuvent être invités %{url}. here: ici index: first_paragraph: Sur cette page, tu peux ajouter, modifier et supprimer %{url}. - new_workgroup: Créer une nouvelle équipe + new_workgroup: Définir une nouvelle équipe new_workgroups: nouvelles équipes ordergroup: cellule - second_paragraph: ! 'Attention à bien noter la différence entre une équipe et une cellule: une cellule est toujours associée à un compte de crédit et sert à passer des commandes, tandis qu''une %{url} (par exemple l''équipe distribution) s''occupe des boulots utiles à la coop. Les utilisatrices appartiennent toujours à une et une seule cellule, mais peuvent faire partie de plusieurs équipes.' - title: Equipes + second_paragraph: ! 'Attention à bien noter la différence entre une équipe et une cellule: chaque membre fait partie d''une %{url}, qui possède un certain crédit servant à payer les commandes, tandis qu''une équipe (par exemple l''équipe distribution) s''occupe des boulots utiles à la boufcoop. Les membres appartiennent toujours à une et une seule cellule, mais peuvent faire partie de plusieurs équipes.' + title: Équipes new: - title: Créer une nouvelle équipe + title: Définir une nouvelle équipe show: confirm: T'es sûrE de ton coup? edit: Modifier les données sur l'équipe et/ou ses membres - title: Equipe %{name} + title: Équipe %{name} workgroups: members: membres name: nom article_categories: create: - notice: Catégorie sauvegardée + notice: La catégorie a bien été définie. destroy: error: ! 'Cette catégorie n''a pas pu être supprimée: %{message}' edit: @@ -233,9 +233,9 @@ fr: last_update: ! 'dernière modification: %{last_update} | brut: %{gross_price}' articles: confirm_delete: Tu veux vraiment supprimer tous ces articles? - option_available: Ces articles sont disponible - option_delete: Supprimer ces articles - option_not_available: Marquer ces articles comme indisponibles + option_available: Marquer comme disponible(s) + option_delete: Supprimer + option_not_available: Marquer comme indisponible(s) option_select: Choisir une action... price_netto: Prix unit_quantity_desc: Unités par lot @@ -296,7 +296,7 @@ fr: restrict_region: Seulement les articles régionaux title: Importer cet article new: Nouvel article - new_order: Créer une nouvelle liste de commande + new_order: Définir une nouvelle commande search_placeholder: Nom... title: Articles de %{supplier} (%{count}) upload: Transférer les articles @@ -430,35 +430,35 @@ fr: year: an deliveries: add_stock_change: - how_many_units: Combien d'unites (%{unit}) de l'article "%{name}" doivent être livrées? + how_many_units: Combien d unités (%{unit}) de l article %{name} doivent-elles être livrées? create: - notice: La livraison a été créée. Attention à ne pas oublier de déposer la facture correspondante! + notice: Le réapprovisionnement a bien a été défini. Attention à ne pas oublier de déposer la facture correspondante! create_stock_article: - notice: Le nouvel article en stock "%{name}" a été sauvegardé. + notice: L'article "%{name}" a été ajouté au stock. destroy: - notice: La livraison a été annulée. + notice: Le réapprovisionnement a été annulé. edit: - title: Modifier la livraison + title: Modifier le réapprovisionnement form: actions: Options article: Article category: Catégorie create_from_blank: Ajouter un nouvel article quelconque - create_stock_article: Ajouter un nouvel article en stock + create_stock_article: Ajouter un article au stock price: Prix net quantity: Quantité title_fill_quantities: 2. Définir la quantité à livrer - title_finish_delivery: 3. Terminer la livraison + title_finish_delivery: 3. Clore le réapprovisionnement title_select_stock_articles: 1. Choisir les articles en stock unit: Unité index: confirm_delete: T'es sûrE de ton coup? - new_delivery: Définir une nouvelle livraison de %{supplier} - title: ! '%{supplier}/Livraisons' + new_delivery: Réapprovisionner le stock par %{supplier} + title: ! '%{supplier}/Réapprovisionnements' invoice_amount: Montant de la facture invoice_net_amount: Montant net de la facture new: - title: Nouvelle livraison de %{supplier} + title: Réapprovisionner le stock par %{supplier} show: amount: Quantité article: Article @@ -467,7 +467,7 @@ fr: sum_diff: montant brut - montant net sum_gross: prix total brut sum_net: prix total net - title: Afficher la livraison + title: Afficher le réapprovisionnement title_articles: Article unit: Unité stock_article_for_adding: @@ -475,14 +475,14 @@ fr: action_edit: Modifier action_other_price: Copier stock_article_form: - copy_stock_article: Copier l'article en stock + copy_stock_article: Copier l'article stock_change_fields: remove_article: Retirer l'article de cette commande suppliers_overview: Liste des fournisseusEs_rs update: notice: La commande a été actualisée update_stock_article: - notice: Les données de l'article en stock "%{name}" ont été mises à jour. + notice: Les données de l'article "%{name}" ont été mises à jour. documents: order_by_articles: filename: Commande %{name}-%{date} - Trier par @@ -490,7 +490,7 @@ fr: - Cellule - Quantité - Prix - title: ! 'Ordre des articles pour la commande: %{name}, terminée le %{date}' + title: ! 'Ordre des articles pour la commande: %{name}, close le %{date}' order_by_groups: filename: Commande %{name}-%{date} - Répartition par cellules rows: @@ -501,7 +501,7 @@ fr: - Unité - Prix total sum: prix total - title: ! 'Répartition par cellules pour la commande: %{name}, terminée le %{date}' + title: ! 'Répartition par cellules pour la commande: %{name}, close le %{date}' order_fax: filename: Commande %{name}-%{date} - Fax rows: @@ -520,7 +520,7 @@ fr: - Nombre de lots - Prix coop - Quantité - title: ! 'Tableau de répartition pour la commande: %{name}; terminée le %{date}' + title: ! 'Tableau de répartition pour la commande: %{name}; close le %{date}' total: one: Un seul article other: ! '%{count} articles au total' @@ -564,24 +564,24 @@ fr: first_paragraph: Tu as trouvé une erreur? Tu as une proposition, une idée, une critique? Envoie un commentaire! second_paragraph: ! 'Petite remarque: l''équipe de Foodsoft s''occupe seulement de la maintenance du logiciel. - Pour les questions concernants l''organisation de ta coop, il faut contacter les personnes concernées.' + Pour les questions concernants l''organisation de ta boufcoop, il faut contacter les personnes concernées.' send: Transmettre title: Laisser un commentaire finance: balancing: close: alert: ! 'Une erreur s''est produite lors du décompte: %{message}' - notice: La commande a été décomptée avec succès, et les comptes des utilisateurs ont été mis à jour. + notice: La commande a été décomptée avec succès, et les comptes des membres ont été mis à jour. close_direct: - alert: ! 'Impossible de terminer cette commande: %{message}' - notice: La commande a été terminée avec succès. + alert: ! 'Impossible de clore cette commande: %{message}' + notice: La commande a été close avec succès. confirm: clear: Terminer - first_paragraph: ! 'Lorsque la commande sera terminée, les comptes seront mis à jour en conséquence. + first_paragraph: ! 'Lorsque la commande sera close, les comptes seront mis à jour en conséquence.
- Les prélèvements pour cette commande s''élèveront comme suit: ' + Les décomptes pour cette commande s''élèveront comme suit: ' or_cancel: ou retourner au décompte title: Décompter la commande edit_results_by_articles: @@ -598,23 +598,23 @@ fr: add_group: Créer un nouveau groupe group: Groupe total: Prix total - total_fc: Prix total (pour la coop) + total_fc: Prix total (pour la boufcoop) units: Nombre d'unités index: - title: Commandes terminée + title: Commandes closes invoice: edit: Modifier la facture invoice_amount: ! 'Montant de la facture:' invoice_date: ! 'Date de la facture:' invoice_number: ! 'Numéro de la facture:' minus_refund_calculated: ! 'Prix de la consigne:' - new: Créer une nouvelle facture + new: Saisir une nouvelle facture new_body: Ajouter une facture pour cette commande plus_refund_credited: Remboursement de la consigne refund_adjusted_amount: Montant recalculé en excluant les consignes new: alert: Attention, cette commande a déjà été décomptée - articles_overview: Aperçu des article + articles_overview: Aperçu des articles comment_on_transaction: Ici, tu peux faire part de tes commentaires concernant le décompte de la facture comments: Commentaire confirm_order: Terminer la commande @@ -635,16 +635,16 @@ fr: close: fermer maintenant confirm: Veux-tu vraiment terminer la commande? end: Fin - ended: expiré + ended: closes last_edited_by: Dernières modifications effectuées par name: FournisseusE_r - no_closed_orders: Aucune commande n'a pour le moment été terminée. + no_closed_orders: Aucune commande n'a encore été close. state: Statut summary: changed: Les données ont été modifiées! duration: von %{starts} bis %{ends} - fc_amount: ! 'Montant coop:' - fc_profit: Part de la coop + fc_amount: ! 'Montant boufcoop:' + fc_profit: Gain de la boufcoop gross_amount: Montant brut groups_amount: ! 'Montant pour chaque cellule:' net_amount: ! 'Montant net:' @@ -652,7 +652,7 @@ fr: with_extra_charge: ! 'avec supplément:' without_extra_charge: ! 'sans supplément:' create: - notice: La facture a été générée. + notice: La facture a bien été définie. financial_transactions: create: notice: La transaction a été sauvegardée. @@ -661,7 +661,7 @@ fr: notice: Les transactions ont été sauvegardées. index: balance: ! 'Solde: %{balance}' - last_updated_at: (dernière mis à jour avant le %{when}) + last_updated_at: (dernière mise à jour il y a %{when}) new_transaction: Ajouter une nouvelle transaction search_placeholder: Rechercher ... title: Relevé de compte pour %{name} @@ -670,7 +670,7 @@ fr: title: Nouvelle transaction new_collection: amount: Montant - new_ordergroup: Ajouter de nouvelles cellules + new_ordergroup: Créer d'autres cellules note: Note ordergroup: Cellule save: Sauvegarder les transactions @@ -689,7 +689,7 @@ fr: amount_change_for: Modification de la quantité de %{article} index: amount: Montant - amount_fc: Montant(coop) + amount_fc: Montant(boufcoop) clear: Décompter date: Date end: Fin @@ -697,26 +697,26 @@ fr: group: Cellule last_transactions: Dernières transactions note: Note - open_transactions: Pas encore décompté + open_transactions: à décompter show_all: tout afficher supplier: FournisseusE_r title: Espace trésorerie - unpaid_invoices: Factures pas encore réglées + unpaid_invoices: Factures à régler invoices: edit: title: Modifier cette facture index: - action_new: Créer une nouvelle facture - title: Facture + action_new: Définir une nouvelle facture + title: Factures invoices: confirm_delete: T'es sûrE de ton coup? - delivery: Livraison + delivery: Réapprovisionnement linked: Cette facture est associée à %{what_link}. - linked_delivery: une livraison + linked_delivery: un réapprovisionnement linked_order: une commande new: back: Retour - title: Créer une nouvelle facture + title: Définir une nouvelle facture show: back: Retour title: Facture %{number} @@ -729,10 +729,11 @@ fr: index: new_transaction: Saisir une nouvelle transaction search_placeholder: Rechercher ... - title: Gestion des crédits + title: Crédits des cellules ordergroups: account_balance: Crédit disponible account_statement: Relevé de compte + contact: name: Nom new_transaction: Nouvelle transaction update: @@ -740,10 +741,10 @@ fr: foodcoop: ordergroups: index: - name: Nom ... + name: Rechercher... only_active: Seulement les cellules en activité - only_active_desc: (ayant commandé au moins une fois dans les 3 derniers mois) - title: Cellule + only_active_desc: (ayant commandé au moins une fois au cours des 3 derniers mois) + title: Cellules ordergroups: last_ordered: dernière commande name: Nom @@ -752,21 +753,21 @@ fr: index: body: ! '

Cette page sert à envoyer des messages aux autres membres de la coop.

-

Si tu veux que ton identité soit visible par les autres, il faut le spécifier sur ton profil %{profile_link}.

' +

Si tu veux que tes coordonnées soient visibles par les autres, il faut le spécifier dans tes %{profile_link}.

' ph_name: Nom ... ph_ordergroup: Cellule ... - profile_link: Préférence - title: Membre + profile_link: préférences + title: Membres workgroups: edit: invite_link: ici - invite_new: Tu peux engrainer des nouveaux membres %{invite_link}. + invite_new: Tu peux engrainer de nouveaux membres %{invite_link}. title: Modifier cette équipe index: body: ! '

Seuls les membres d''une équipe peuvent la modifier.

Tu peux rejoindre une équipe en contactant un de ses membres.

' - title: Equipes + title: Équipes workgroup: edit: Modifier la cellule show_tasks: Afficher tous les boulots @@ -775,23 +776,23 @@ fr: desc: Accéder à toutes les %{link}. open_orders: commandes en cours title: commandes de %{group} - title_closed: décomptée - title_open: terminée/pas décomptée + title_closed: déjà décomptées + title_open: closes/pas encore décomptées create: error_general: Suite à une erreur, la commande n'a pu être mise à jour. error_stale: La commande n'a pas pu être mise à jour car quelqu'un d'autre a commandé entre temps. - notice: La commande a bien été enregistrée. + notice: Ta commande a bien été enregistrée. errors: - closed: La commande est déjà terminée. + closed: La commande est déjà close. no_member: Tu n'es encore membre d'aucune cellule. notfound: ! ' Mauvaise adresse, ce n''est pas ta commande.' form: - action_save: Enregistrer la commande + action_save: Enregistrer ta commande amount: Quantité available: Disponible available_funds: Crédit disponible created_by: Établi par - ending: Fin + ending: Clôture le funds: Crédit last_update: Dernière commande manufacturer: Produit par @@ -833,32 +834,32 @@ fr: order: title: Article orders: - ending: Fi + ending: Clôture le sum: Total supplier: FournisseusE_r show: articles: - edit_order: Adapter la commande + edit_order: Modifier ta commande name: Nom not_ordered_msg: Tu n'as pas encore commandé - order_closed_msg: Désolé, cette commande a déjà été fermée. Il faudra se réveiller plus tôt la prochaine fois. + order_closed_msg: Désolé, cette commande a déjà été fermée. Il faudra te réveiller plus tôt la prochaine fois order_nopen_title: En tenant compte des commandes en cours de toutes les cellules order_not_open: Déjà reçu order_now: Voilà ta chance! - order_open: Commande en cours - ordered: Commandé + order_open: Quantité à prévoir + ordered: Quantité souhaitée ordered_title: Quantité + tolérance show_hide: Montrer/cacher les articles non commandés sum: Total - title: Aperçu des article - total_price: Prix total + title: Aperçu des articles + total_price: Prix unit_price: Prix unitaire units: Lots closed_by: Décompté par %{user} comment: Lire/écrire des commentaire comments: title: Commentaire - ending: Fin + ending: Clôture le not_ordered: Tu n'as pas commandé. note: Note order_sum: Total de la commande @@ -871,7 +872,7 @@ fr: update: error_general: Suite à une erreur, la commande n'a pu être mise à jour. error_stale: La commande n'a pas pu être mise à jour, car quelqu'un d'autre a commandé entre temps. - notice: La commande a bien été enregistrée. + notice: Ta commande a bien été enregistrée. helpers: application: edit_user: Modifier la liste des membres @@ -893,7 +894,7 @@ fr: select: prompt: Faire un choix submit: - create: sauvegarder %{model} + create: Définir %{model} invite: create: Envoyer une invitatio message: @@ -922,11 +923,11 @@ fr: my_ordergroup: funds: ! '| Crédit disponible:' last_update: La dernière mise à jour date du %{when} - title: Ma cellule + title: Ta cellule transactions: amount: Montant note: Note - title: Dernière transactio + title: Dernière transactions view: Afficher un relevé de compte when: Quand? where: Qui? @@ -937,7 +938,7 @@ fr: desc: Tu as du boulot de prévu. title: Accepter des boulot tasks_open: - action: boulots disponibles + action: boulot(s) disponible(s) desc: Il y a %{size} title: Boulots disponibles title: Page d'accueil @@ -956,7 +957,7 @@ fr: groups: cancel: Quitter la coop cancel_confirm: T'es sûrE de vouloir partir? - invite: Engrainer des nouveaux membres + invite: Engrainer de nouveaux membres title: Tu fais partie des équipes suivantes title: Ton profil user: @@ -968,9 +969,9 @@ fr: accounts: Mettre à jour les compte settle: Décompter des commandes title: Espace trésorerie - foodcoop: Coop - members: Membre - new_ordergroup: Créer une nouvelle cellule + foodcoop: Boufcoop + members: Membres + new_ordergroup: Définir une nouvelle cellule new_user: Ajouter un nouveau membre orders: end: Terminer des commandes @@ -986,7 +987,7 @@ fr: write_message: Écrire un message invites: errors: - already_member: est déjà membre de la Boufcoop + already_member: est déjà membre de la Boufcoop. modal_form: body: Sur cette page, tu peux inviter une personne dans la cellule %{group} qui n'est pas encore membre de la Boufcoop.

Après sa première connexion elle sera automatiquement membre de la cellule.

title: Engrainer une personne @@ -994,7 +995,7 @@ fr: action: Engrainer! back: ou revenir en arrière body:

Sur cette page, tu peux engrainer une personne qui ne fait pas encore partie de la Boufcoop à rejoindre la cellule %{group} - success: L'utilisatrice a été engrainée avec succès! + success: La_le membre a été engrainéE avec succès! layouts: application1: title: Foodsoft - %{title} @@ -1015,7 +1016,7 @@ fr: help: Aide logout: Déconnexion ordergroup: Ta cellule - profile: Modifier ton profil + profile: Ton profil logo: coop lib: order_pdf: @@ -1042,7 +1043,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: ! "Si tu as donné ton adresse email, tu vas maintenant recevoir un message \ncontenant 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: @@ -1054,7 +1055,7 @@ fr: submit: Demander un nouveau mot de passe title: Mot de passe oublié? new_password: - body:

Merci de saisir le nouveau mot de passe souhaité pour l'utilisateur %{user}

+ body:

Merci de saisir le nouveau mot de passe souhaité pour %{user}

submit: Sauvegarder le nouveau mot de passe title: Nouveau mot de passe mailer: @@ -1106,7 +1107,7 @@ fr: ' order_result: - subject: ! 'Commande terminée: %{name}' + subject: ! 'Commande close: %{name}' text0: ! 'CherEs %{ordergroup}, @@ -1143,7 +1144,7 @@ fr: Tu t''es inscritE pour le boulot "%{task}", qui aura lieu demain (%{when}). ' - text1: ! 'Mes boulots: %{user_tasks_url} + text1: ! 'Ton agenda: %{user_tasks_url} Ceci est un rappel automatisé envoyé par %{foodcoop}.' @@ -1166,9 +1167,9 @@ fr: subscribe: Pour plus d'explications concernant la mailing list, consulte le %{link} subscribe_msg: Il faudra peut être d'abord t'inscrire à la mailing list. wiki: wiki (section mailing list) - no_user_found: ! 'Aucune utilisatrice correspondante n''a été trouvée ' + no_user_found: ! 'AucunE membre correspondantE n''a été trouvéE ' search: Rechercher ... - search_user: Rechercher une utilisatrice + search_user: Rechercher unE membre title: Nouveau message show: all_messages: Aperçu des messages @@ -1179,7 +1180,7 @@ fr: title: Afficher le contenu du message model: delivery: - each_stock_article_must_be_unique: Chaque article en stock ne peut être listé qu'une seule fois dans la commande. + each_stock_article_must_be_unique: Chaque article à stocker ne peut apparaître qu'une seule fois dans la commande. membership: no_admin_delete: ! 'Pas moyen de quitter le navire: tu es le ou la dernièrE administratrice à bord!' order_article: @@ -1193,35 +1194,35 @@ fr: home: Aperçu ordergroups: Cellules title: Administration - users: Utilisatrices - workgroups: Équipes de travail + users: Membres + workgroups: Équipes articles: categories: Catégories - stock: Stock - suppliers: FournisseusEs_rs/Article - title: Article + stock: Gestion du stock + suppliers: FournisseusEs_rs/Articles + title: Articles dashboard: Tableau de bord finances: - accounts: gérer la trésorerie - balancing: Décompter des commandes + accounts: Crédits des cellules + balancing: Décompte des commandes home: Aperçu invoices: Factures title: Trésorerie foodcoop: Boufcoop - members: Membre + members: Membres messages: Messages - ordergroups: Cellule + ordergroups: Cellules orders: - archive: Mes commandes + archive: Historique des commandes manage: Gestion des commandes - ordering: Commander! - title: Commande - tasks: Boulots + ordering: Passer une commande + title: Commandes + tasks: Boulot wiki: all_pages: Toutes les pages home: Page d'accueil title: Wiki - workgroups: Equipe + workgroups: Équipes number: currency: format: @@ -1283,28 +1284,28 @@ fr: invalid_balance: n'est pas un nombre valide orders: articles: - article_count: ! 'Nombre d''articles commandés:' + article_count: ! 'Articles commandés:' name: Nom - prices: Prix net/brut - prices_sum: Totaux (des prix nets/bruts) - unit_quantity: Nombre de lots - units_full: Nombre de lots complet - units_ordered: Nombre d'unités commandées + prices: Prix brut/net + prices_sum: Totaux (des prix bruts/nets) + unit_quantity: Unités par lots x Lots + units_full: Lots complet + units_ordered: Unités commandées create: - notice: La liste de commande a été créée. + notice: La commande a bien été définie. edit: - title: Modifier la liste de commande. + title: Modifier la commande fax: amount: Quantité - articles: Article - customer_number: Numéro de client + articles: Articles + customer_number: Numéro de client de la coop delivery_day: Jour de livraison heading: Commande pour %{name} name: Nom number: Numéro to_address: Adresse du destinataire finish: - notice: La commande a été terminée. + notice: La commande a été close. form: name: Nom note: Note @@ -1319,14 +1320,14 @@ fr: action_end: Terminer confirm_delete: Vraiment supprimer la commande? confirm_end: Veux tu vraiment mettre fin à la commande %{order}? Attention, il n'y aura pas d'annulation possible. - ended_orders: Commandes terminées - ending: Fin - new_order: Créer une nouvelle commande + ended_orders: Commandes closes + ending: Clôture le + new_order: Définir une nouvelle commande no_open_orders: Il n'y a aucune commande en cours en ce moment. note: Note open_orders: Commandes en cours supplier: FournisseusE_r - title: Gérer les commande + title: Gestion des commandes model: error_closed: Cette commande a déjà été décomptée error_nosel: Au minimum un article doit être sélectionné @@ -1334,16 +1335,16 @@ fr: notice_close: ! 'Commande: %{name}, jusqu''au %{ends}' stock: Stock new: - title: Créer une nouvelle commande + title: Définir une nouvelle commande orders: - ending: Fin + ending: Clôture le start: Début status: Statut supplier: FournisseurE show: - action_end: Terminer! + action_end: Clore! amounts: ! 'Total net/brut:' - articles: Aperçu des article + articles: Aperçu des articles articles_ordered: ! 'Articles commandés:' begin: ! 'Début:' comments: @@ -1360,7 +1361,7 @@ fr: group_pdf: Liste des cellules en PDF matrix_pdf: Matrice de distribution en PDF title: Télécharger - ending: ! 'Fin:' + ending: ! 'Clôture le:' group_orders: ! 'Commandes des cellules:' note: ! 'Note:' sort_article: Trié par article @@ -1370,7 +1371,7 @@ fr: warn_not_closed: Attention, cette commande n'a pas encore été décomptée! state: closed: décomptée - finished: terminée + finished: close open: en cours update: notice: La commande a été mise à jour. @@ -1395,7 +1396,7 @@ fr: notice: La page '%{page}' et toutes ses descendantes ont bien été supprimées. edit: title: Modifier cette page - error_stale_object: Cette page est en cours de modification par un autre utilisateur. Merci de réessayer plus tard. + error_stale_object: Cette page est en cours de modification par unE autre membre. Merci de réessayer plus tard. form: help: bold: gra @@ -1407,11 +1408,11 @@ fr: list_item_1: Premier item list_item_2: Deuxième item noformat: Pas de formatage - ordered_list: Enumérations + ordered_list: Énumérations section_block: Format de paragraphe section_character: Format de charactère - section_link: Format des lien - section_table: Format du tableau + section_link: Format des liens + section_table: Format des tableaux see_tables: Voir %{tables_link} tables_link: Tableaux text: texte @@ -1453,9 +1454,9 @@ fr: login: Te connecter nojs: Attention, les cookies et le javascript doivent être activés! Merci de désactiver %{link}. noscript: NoScript - password: Mot de pass + password: Mot de passe title: Te connecter à Foodsoft - user: Utilisatrice + user: Identifiant shared: articles_by_articles: ordered: Commandé (Quantité + Tolérance) @@ -1511,16 +1512,16 @@ fr: non_members: add: ajouter open_orders: - ending: Fin + ending: Clôture le no_open_orders: Il n'y a aucune commande en cours en ce moment not_enough_apples: Désolé, ta cellule n'a pas assez de glands pour pouvoir commander! - supplier: FournisseurE + supplier: FournisseusE_r title: Commandes en cours total: Total total_sum: Total who_ordered: Qui a commandé? workgroup_members: - title: Membres des cellules + title: Membres des équipes simple_form: error_notification: default_message: Une erreur s'est produite. Merci de vérifier le formulaire. @@ -1528,7 +1529,7 @@ fr: article: unit: par exemple. kg ou 1l ou 500g message: - private: Le message n'apparaît pas sur la boîte de réception du Foodsoft + private: Le message n'apparaîtra pas dans la boîte de réception du Foodsoft order_article: units_to_order: Nombre de lots livrés update_current_price: Modifie aussi le prix des commandes en cours @@ -1542,15 +1543,15 @@ fr: min_order_quantity: La quantité minimum à commander est affichée pendant la commande et doit motiver task: duration: Combien de temps dure le boulot, 1 à 3 heures - required_users: De combien d'utilisatrices avons-nous besoin au total!, + required_users: De combien de personnes avons-nous besoin au total? tax: En pourcentage, le standard est de 7,0 labels: article: article_category: Catégorie - manufacturer: Producteur + manufacturer: ProductRICE_eur name: Nom note: Note - origin: Lieu de productio + origin: Lieu de production unit: Unité article_category: description: Description @@ -1573,7 +1574,7 @@ fr: unit_quantity: Unités par lot user_tokens: Membres delivery: - delivered_on: Date de livraison + delivered_on: Date de réapprovisionnement supplier: Fournisseuse_r group_order_article: ordergroup_id: Cellul @@ -1591,39 +1592,40 @@ fr: supplier: Fournisseuse_r message: body: Contenu - group_id: Groupe + group_id: Cellule ou équipe private: Privé recipient_tokens: Destinataires sent_to_all: Envoyer à tous les membres subject: Sujet order: - ends: Terminée le - starts: Commence le + ends: Clôture le + starts: Ouverture le order_article: units_to_order: Quantité update_current_price: Mettre à jour le prix global order_comment: text: Commenter cette commande... ordergroup: - contact_address: Adress + contact_address: Adresse contact_person: Personne à contacter contact_phone: Téléphone - ignore_apple_restriction: Ne pas interdire la commande aux cellules pauvres en glands + ignore_apple_restriction: Pour cette cellule, ne pas bloquer les commandes en cas de manque de glands + name: page: body: Contenu parent_id: Page parente settings: messages: - send_as_email: Recevoir les messages par email + send_as_email: Transmettre les messages de la boufcoop par email notify: - negative_balance: Envoyer un avertissement si ta cellule est dans le rouge. + negative_balance: Envoyer un avertissement si la cellule est dans le rouge. order_finished: Envoyer un résumé de la commande finale (après la fermeture) - upcoming_tasks: Envoyer un rappel des prochains boulots auxquels tu es inscritE + upcoming_tasks: Envoyer un rappel des prochains boulots profile: - email_is_public: Permettre aux autres membres de voir ton adresse email. + email_is_public: Permettre aux autres membres de voir l'adresse email. language: Langue - name_is_public: Permettre aux autres membres de voir ton nom. - phone_is_public: Permettre aux autres membres de voir ton numéro de téléphone. + name_is_public: Permettre aux autres membres de voir le nom. + phone_is_public: Permettre aux autres membres de voir le numéro de téléphone. settings_group: messages: Messages privacy: Confidentialité @@ -1632,7 +1634,7 @@ fr: supplier: address: Adresse contact_person: Contact - customer_number: Numéro de client + customer_number: Numéro de client de la coop delivery_days: Jours de livraison email: Email fax: Fa @@ -1651,23 +1653,23 @@ fr: name: Nom required_users: Nombre de personnes nécessaires user_list: Responsables inscritEs - workgroup: Equipe + workgroup: Équipe user: email: Email last_name: Nom de famille name: Nom nick: Identifiant - ordergroup: Cellul + ordergroup: Cellule phone: Téléphone workgroup: - one: Cellule - other: Cellule + one: Équipe + other: Équipes workgroup: - next_weekly_tasks_number: Combien de temps en avance les boulots doivent ils être visibles sur le site? + next_weekly_tasks_number: Combien de temps en avance les boulots doivent ils être annoncés sur le site? role_admin: Administration - role_article_meta: Base de données des article + role_article_meta: Base de données des articles role_finance: Trésorerie - role_orders: Gestion des commande + role_orders: Gestion des commandes role_suppliers: Contact avec les fournisseusEs_rs 'no': Non options: @@ -1688,19 +1690,17 @@ fr: edit: title: Modifier les données de l'inventaire index: - new_inventory: Commencer un nouvel inventaire + new_inventory: Inventorier le stock title: Aperçu de l'inventaire new: - create: créer + create: ajouter stock_articles: Articles en stock - temp_inventory: inventaire provisoire + temp_inventory: l'inventaire courant text_deviations: ! 'Saisir ici les déviations constatées par rapport à %{inv_link}. En cas de manque, utiliser un signe ''-''.' - text_need_articles: ! 'Pour pouvoir prendre un compte de nouveaux articles en stock, - - ils doivent d''abord être %{create_link}.' - title: Commencer un nouvel inventaire + text_need_articles: Si certains articles n'apparaissent pas sur l'inventaire courant, il faut les y %{create_link} directement. + title: Inventorier le stock show: amount: Quantité article: Article @@ -1721,7 +1721,7 @@ fr: check: not_empty: ! '%{name} ne peut pas être supprimé, car il y en a encore en stock.' destroy: - notice: L'article en stock %{name} a bien été supprimé. + notice: L'article %{name} a bien été supprimé du stock. edit: title: Modifier l'article form: @@ -1729,7 +1729,7 @@ fr: history: change_quantity: Modification datetime: Temps - delivery: Livraison + delivery: Réapprovisionnement new_quantity: Nouveau stock order: Commande reason: Raison @@ -1747,18 +1747,19 @@ fr: unit: Unité vat: TVA confirm_delete: T'es sûrE de ton coup? - new_delivery: Nouvelle livraison... - new_stock_article: Créer un nouvel article en stock - new_stock_taking: Commencer un inventaire - order_online: Mettre la commande de renouvellement du stock en ligne - show_stock_takings: Aperçu des inventaire + new_delivery: Réapprovisionner le stock... + new_stock_article: Ajouter un article au stock + new_stock_taking: Inventorier le stock + order_online: Définir une commande à partir du stock + show_stock_takings: Historique des inventaires stock_count: ! 'Nombre d''articles:' stock_worth: ! 'Valeur actuelle du stock:' - toggle_unavailable: Afficher/cacher les articles actuellement indisponible + title: + toggle_unavailable: Afficher/cacher les articles actuellement indisponibles view_options: Préférences d'affichage new: search_text: ! 'Rechercher des articles dans tous les catalogues:' - title: Créer un nouvel article en stock + title: Ajouter un article au stock stock_create: notice: L'article a été sauvegardé. stock_update: @@ -1794,7 +1795,7 @@ fr: show: confirm_delete: Tu es sûrE de ton coup? last_deliveries: Dernières livraisons - new_delivery: Commencer un nouveau réapprovisionnement + new_delivery: Réapprovisionner le stock show_deliveries: Afficher tous les réapprovisionnements update: notice: Les données du_de la fournisseurE ont été mises à jour @@ -1814,7 +1815,7 @@ fr: task_format: ! '%{name} (%{duration}h)' who: Personnes en charge create: - notice: Le boulot a été généré + notice: Le boulot a bien été défini. destroy: notice: Le boulot a été supprimé edit: @@ -1827,32 +1828,33 @@ fr: error_not_found: Aucune équipe n'a été trouvée. form: search: - hint: Rechercher par utilisatrice_teur - noresult: AucunE utilisatricE_teur n'a été trouvéE + hint: Rechercher unE membre + noresult: AucunE membre n'a été trouvéE placeholder: Recherche... submit: - periodic: Sauvegarder le boulot hebdomadaire + periodic: Définir comme boulot hebdomadaire index: - show_group_tasks: Afficher les boulots pour cette équipe - title: Boulots + show_group_tasks: Afficher l'agenda de cette équipe + title: Agenda title_non_group: Boulots ouverts à tous list: accept_task: Te charger de ce boulot done: Effectué done_q: Effectué? - due_date: A faire pour le + due_date: À faire pour le mark_done: Marquer ce boulot comme étant effectué reject_task: Refuser ce boulot - task: Descriptio + task: Description task_format: ! '%{name} (%{duration}h)' who: Qui le fait? who_hint: (Combien manquent encore?) nav: - all_tasks: Tous les boulots - archive: Boulots déjà effectués (archive) - group_tasks: Boulots d'équipe - my_tasks: Mes boulots + all_tasks: L'agenda de la boufcoop + archive: Boulots déjà effectués (archives) + group_tasks: Sélectionner une équipe + my_tasks: Ton agenda new_task: Définir un nouveau boulot + pages: new: title: Définition d'un nouveau boulot repeated: Ce boulot a lieu toutes les semaines. @@ -1875,10 +1877,10 @@ fr: tasks_link: par là-bas. title: Ton boulot title_accepted: Boulots acceptés - title_open: Boulots disponible + title_open: Boulots disponibles workgroup: - title: Boulots pour l'%{workgroup} - title_all: Boulot de l'équipe + title: Agenda de l'%{workgroup} + title_all: Boulot prévu pour l'équipe time: am: le matin formats: @@ -1894,7 +1896,7 @@ fr: marks: close: ! '×' success: - or_cancel: ou supprimer + or_cancel: ou annuler please_wait: Merci de patienter... save: Sauvegarder show: Afficher diff --git a/config/locales/nl.yml b/config/locales/nl.yml index 983b4321..c3af065b 100644 --- a/config/locales/nl.yml +++ b/config/locales/nl.yml @@ -479,17 +479,26 @@ nl: notice: documents: order_by_articles: - filename: - rows: - title: + filename: Bestelling %{name}-%{date} - Artikellijst + rows: + - Huishouden + - Hoeveelheid + - Prijs + title: ! 'Artikellijst van bestelling: %{name}, gesloten op %{date}' order_by_groups: - filename: - rows: - sum: - title: + filename: Bestelling %{name}-%{date} - Huishoudenslijst + rows: + - Artikel + - Hoeveelheid + - Prijs + - Gr.Eenh. + - Eenheid + - Som + sum: Som + title: ! 'Huishoudenslijst van bestelling: %{name}, gesloten op %{date}' order_fax: - filename: - rows: + filename: Bestelling %{name}-%{date} - Fax + rows: ! '[]' order_matrix: filename: heading: @@ -498,29 +507,29 @@ nl: total: errors: format: - general: + general: Er is een probleem opgetreden. general_again: - general_msg: + general_msg: ! 'Er is een probleem opgetreden: %{msg}' messages: - accepted: - blank: + accepted: moet geaccepteerd worden + blank: moet ingevuld worden confirmation: - empty: - equal_to: + empty: moet ingevuld worden + equal_to: moet precies %{count} zijn even: - exclusion: - greater_than: + exclusion: moet even zijn + greater_than: moet groter dan %{count} zijn greater_than_or_equal_to: inclusion: invalid: - less_than: - less_than_or_equal_to: - not_a_number: - not_an_integer: - odd: + less_than: moet kleiner dan %{count} zijn + less_than_or_equal_to: moet groter of gelijk aan %{count} zijn + not_a_number: is geen getal + not_an_integer: moet een geheel getal zijn + odd: moet oneven zijn record_invalid: - taken: - taken_with_deleted: + taken: is al in gebruik + taken_with_deleted: is al in gebruik (verwijderde groep) too_long: too_short: wrong_length: @@ -697,6 +706,7 @@ nl: ordergroups: account_balance: Tegoed account_statement: + contact: name: Naam new_transaction: Nieuwe transactie update: @@ -1493,6 +1503,7 @@ nl: contact_person: Contactpersoon contact_phone: Telefoon ignore_apple_restriction: + name: page: body: parent_id: @@ -1634,6 +1645,7 @@ nl: show_stock_takings: stock_count: stock_worth: + title: toggle_unavailable: view_options: new: @@ -1725,6 +1737,7 @@ nl: group_tasks: my_tasks: new_task: + pages: new: title: repeated: @@ -1765,9 +1778,9 @@ nl: history: marks: close: ! '×' - success: + success: or_cancel: of annuleren - please_wait: + please_wait: Een moment alstublieft... save: Opslaan show: Tonen views: From 39b3dee0500e38b729120d08a06f9327c7119a00 Mon Sep 17 00:00:00 2001 From: wvengen Date: Thu, 20 Jun 2013 17:17:15 +0200 Subject: [PATCH 55/59] do not show empty fields on fax pdf (closes foodcoops/foodsoft#108) --- app/documents/order_fax.rb | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/app/documents/order_fax.rb b/app/documents/order_fax.rb index 0caaaa4e..a553456c 100644 --- a/app/documents/order_fax.rb +++ b/app/documents/order_fax.rb @@ -20,11 +20,17 @@ class OrderFax < OrderPdf move_down 5 text "#{contact[:zip_code]} #{contact[:city]}", size: 9, align: :right move_down 5 - text "#{I18n.t('simple_form.labels.supplier.customer_number')}: #{@order.supplier.try(:customer_number)}", size: 9, align: :right - move_down 5 - text "#{I18n.t('simple_form.labels.supplier.phone')}: #{contact[:phone]}", size: 9, align: :right - move_down 5 - text "#{I18n.t('simple_form.labels.supplier.email')}: #{contact[:email]}", size: 9, align: :right + unless @order.supplier.try(:customer_number).blank? + text "#{I18n.t('simple_form.labels.supplier.customer_number')}: #{@order.supplier[:customer_number]}", size: 9, align: :right + move_down 5 + end + unless contact[:phone].blank? + text "#{I18n.t('simple_form.labels.supplier.phone')}: #{contact[:phone]}", size: 9, align: :right + move_down 5 + end + unless contact[:email].blank? + text "#{I18n.t('simple_form.labels.supplier.email')}: #{contact[:email]}", size: 9, align: :right + end end # Recipient @@ -32,8 +38,10 @@ class OrderFax < OrderPdf text @order.name move_down 5 text @order.supplier.try(:address).to_s - move_down 5 - text "#{I18n.t('simple_form.labels.supplier.fax')}: #{@order.supplier.try(:fax)}" + unless @order.supplier.try(:fax).blank? + move_down 5 + text "#{I18n.t('simple_form.labels.supplier.fax')}: #{@order.supplier[:fax]}" + end end move_down 5 @@ -42,8 +50,10 @@ class OrderFax < OrderPdf move_down 10 text "#{I18n.t('simple_form.labels.delivery.delivered_on')}:" move_down 10 - text "#{I18n.t('simple_form.labels.supplier.contact_person')}: #{@order.supplier.try(:contact_person)}" - move_down 10 + unless @order.supplier.try(:contact_person).blank? + text "#{I18n.t('simple_form.labels.supplier.contact_person')}: #{@order.supplier[:contact_person]}" + move_down 10 + end # Articles data = [I18n.t('documents.order_fax.rows')] From b235592656e7d724c36dfd6a4a0d9c8eaf5c8bff Mon Sep 17 00:00:00 2001 From: wvengen Date: Fri, 21 Jun 2013 02:34:56 +0200 Subject: [PATCH 56/59] add total to order pdf, layout changes (closes foodcoops/foodsoft#138) --- app/documents/order_fax.rb | 14 ++++++++++++-- config/locales/de.yml | 2 ++ config/locales/en.yml | 8 +++++--- 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/app/documents/order_fax.rb b/app/documents/order_fax.rb index a553456c..f2182944 100644 --- a/app/documents/order_fax.rb +++ b/app/documents/order_fax.rb @@ -56,21 +56,31 @@ class OrderFax < OrderPdf end # Articles + total = 0 data = [I18n.t('documents.order_fax.rows')] data += @order.order_articles.ordered.all(include: :article).collect do |a| + subtotal = a.units_to_order * a.price.unit_quantity * a.price.price + total += subtotal [a.article.order_number, a.units_to_order, a.article.name, a.price.unit_quantity, a.article.unit, - a.price.price] + number_to_currency(a.price.price), + number_to_currency(subtotal)] end + data << [I18n.t('documents.order_fax.total'), nil, nil, nil, nil, nil, number_to_currency(total)] table data, cell_style: {size: 8, overflow: :shrink_to_fit} do |table| + table.header = true table.cells.border_width = 1 table.cells.border_color = '666666' + table.row(0).border_bottom_width = 2 table.columns(1).align = :right - table.columns(3..5).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).border_top_width = 2 end #font_size: 8, #vertical_padding: 3, diff --git a/config/locales/de.yml b/config/locales/de.yml index 43aed756..8638bfc5 100644 --- a/config/locales/de.yml +++ b/config/locales/de.yml @@ -505,6 +505,8 @@ de: - Gebinde - Einheit - Preis/Einheit + - Summe + total: Gesamtpreis order_matrix: filename: Bestellung %{name}-%{date} - Sortiermatrix heading: Artikelübersicht diff --git a/config/locales/en.yml b/config/locales/en.yml index 8c655949..1268a935 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -493,7 +493,7 @@ en: - Article - Amount - Price - - Unit Quantity + - Unit quantity - Unit - Sum sum: Sum @@ -504,16 +504,18 @@ en: - Order Number - Amount - Name - - Barrel + - Unit quantity - Unit - Price/Unit + - Subtotal + total: Total order_matrix: filename: Order %{name}-%{date} - sorting matrix heading: Article overview rows: - Article - Unit - - Barrel + - Unit quantity - FC-Price - Amount title: ! 'Order sorting matrix: %{name}, closed at %{date}' From ee31c0c2af14c5dfc08c7bf8b79783a9bf6937de Mon Sep 17 00:00:00 2001 From: wvengen Date: Tue, 10 Sep 2013 12:06:40 +0200 Subject: [PATCH 57/59] localeapp roundtrip --- config/locales/de.yml | 1 - config/locales/en.yml | 4 +++- config/locales/fr.yml | 3 ++- config/locales/nl.yml | 11 +++++++---- 4 files changed, 12 insertions(+), 7 deletions(-) diff --git a/config/locales/de.yml b/config/locales/de.yml index 8638bfc5..c0000036 100644 --- a/config/locales/de.yml +++ b/config/locales/de.yml @@ -505,7 +505,6 @@ de: - Gebinde - Einheit - Preis/Einheit - - Summe total: Gesamtpreis order_matrix: filename: Bestellung %{name}-%{date} - Sortiermatrix diff --git a/config/locales/en.yml b/config/locales/en.yml index 1268a935..2fa64013 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -519,7 +519,9 @@ en: - FC-Price - Amount title: ! 'Order sorting matrix: %{name}, closed at %{date}' - total: ! '%{count} articles in total' + total: + one: One article in total + other: ! '%{count} articles in total' errors: format: ! '%{attribute} %{message}' general: A problem has occured. diff --git a/config/locales/fr.yml b/config/locales/fr.yml index 1675943d..057acd4e 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -511,6 +511,7 @@ fr: - Nombre de lots - Unité - Prix unitaire + total: order_matrix: filename: Commande %{name}-%{date} - Tableau de répartition heading: Liste des articles @@ -1874,7 +1875,7 @@ fr: 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}. ' - tasks_link: par là-bas. + tasks_link: par là-bas title: Ton boulot title_accepted: Boulots acceptés title_open: Boulots disponibles diff --git a/config/locales/nl.yml b/config/locales/nl.yml index c3af065b..628bd0e8 100644 --- a/config/locales/nl.yml +++ b/config/locales/nl.yml @@ -499,12 +499,15 @@ nl: order_fax: filename: Bestelling %{name}-%{date} - Fax rows: ! '[]' + total: Totaal order_matrix: - filename: - heading: + filename: Bestelling %{name}-%{date} - Sorteermatrix + heading: Artikeloverzicht rows: - title: - total: + title: ! 'Sorteermatrix van bestelling: %{name}, gesloten op %{date}' + total: + one: In totaal éen artikel + other: In totaal %{count} artikelen errors: format: general: Er is een probleem opgetreden. From e6320e5b7b27d71cb20a465011d80278e39b9a5f Mon Sep 17 00:00:00 2001 From: wvengen Date: Tue, 17 Sep 2013 14:49:19 +0200 Subject: [PATCH 58/59] add resque version for security --- Gemfile | 2 +- Gemfile.lock | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Gemfile b/Gemfile index e80314ed..c633e55b 100644 --- a/Gemfile +++ b/Gemfile @@ -38,7 +38,7 @@ gem 'meta_search' gem 'acts_as_versioned', git: 'git://github.com/technoweenie/acts_as_versioned.git' # Use this instead of rubygem gem 'acts_as_tree' gem "rails-settings-cached", "0.2.4" -gem 'resque' +gem 'resque', '>= 1.24.1' gem 'whenever', require: false # For defining cronjobs, see config/schedule.rb group :production do diff --git a/Gemfile.lock b/Gemfile.lock index be91e252..c62e9991 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -333,7 +333,7 @@ DEPENDENCIES quiet_assets rails (~> 3.2.9) rails-settings-cached (= 0.2.4) - resque + resque (>= 1.24.1) rspec-core rspec-expectations rspec-rails From 1cf2145ff63ae2097eda7c103b69ff7a65248a26 Mon Sep 17 00:00:00 2001 From: wvengen Date: Tue, 17 Sep 2013 15:02:58 +0200 Subject: [PATCH 59/59] version update for security (now properly) (see also resque/redis-namespace#64) --- Gemfile | 2 +- Gemfile.lock | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Gemfile b/Gemfile index c633e55b..e80314ed 100644 --- a/Gemfile +++ b/Gemfile @@ -38,7 +38,7 @@ gem 'meta_search' gem 'acts_as_versioned', git: 'git://github.com/technoweenie/acts_as_versioned.git' # Use this instead of rubygem gem 'acts_as_tree' gem "rails-settings-cached", "0.2.4" -gem 'resque', '>= 1.24.1' +gem 'resque' gem 'whenever', require: false # For defining cronjobs, see config/schedule.rb group :production do diff --git a/Gemfile.lock b/Gemfile.lock index c62e9991..c816b8c4 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -205,7 +205,7 @@ GEM rdoc (3.12.2) json (~> 1.4) redis (3.0.4) - redis-namespace (1.3.0) + redis-namespace (1.3.1) redis (~> 3.0.0) responders (0.9.3) railties (~> 3.1) @@ -333,7 +333,7 @@ DEPENDENCIES quiet_assets rails (~> 3.2.9) rails-settings-cached (= 0.2.4) - resque (>= 1.24.1) + resque rspec-core rspec-expectations rspec-rails