Merge branch 'master' into warn-uncheck-ordered-article
This commit is contained in:
commit
e728e76729
55 changed files with 2900 additions and 138 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -16,3 +16,4 @@ doc/app/
|
||||||
Capfile
|
Capfile
|
||||||
config/deploy.rb
|
config/deploy.rb
|
||||||
config/deploy/*
|
config/deploy/*
|
||||||
|
.localeapp
|
14
.travis.yml
Normal file
14
.travis.yml
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
language: ruby
|
||||||
|
rvm:
|
||||||
|
- 1.9.3
|
||||||
|
services:
|
||||||
|
- redis-server
|
||||||
|
before_install:
|
||||||
|
- "export DISPLAY=:99.0"
|
||||||
|
- "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'
|
||||||
|
- 'bundle exec rake db:schema:load RAILS_ENV=test'
|
||||||
|
script: bundle exec rake spec
|
24
Gemfile
24
Gemfile
|
@ -54,10 +54,6 @@ group :development do
|
||||||
gem 'binding_of_caller'
|
gem 'binding_of_caller'
|
||||||
# gem "rails-i18n-debug"
|
# gem "rails-i18n-debug"
|
||||||
|
|
||||||
# Re-enable rails benchmarker/profiler
|
|
||||||
gem 'ruby-prof'
|
|
||||||
gem 'test-unit'
|
|
||||||
|
|
||||||
# Get infos when not using proper eager loading
|
# Get infos when not using proper eager loading
|
||||||
gem 'bullet'
|
gem 'bullet'
|
||||||
|
|
||||||
|
@ -72,6 +68,22 @@ group :development do
|
||||||
gem 'thin'
|
gem 'thin'
|
||||||
end
|
end
|
||||||
|
|
||||||
# Gems left for backwards compatibility
|
group :development, :test do
|
||||||
gem 'acts_as_configurable', git: 'git://github.com/bwalding/acts_as_configurable.git' # user settings migration needs it
|
gem 'ruby-prof'
|
||||||
|
end
|
||||||
|
|
||||||
|
group :test do
|
||||||
|
gem 'rspec-rails'
|
||||||
|
gem 'factory_girl_rails', '~> 4.0'
|
||||||
|
gem 'faker'
|
||||||
|
# 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
|
||||||
|
gem 'rspec-core'
|
||||||
|
gem 'rspec-expectations'
|
||||||
|
gem 'i18n-spec'
|
||||||
|
end
|
||||||
|
|
75
Gemfile.lock
75
Gemfile.lock
|
@ -4,13 +4,6 @@ GIT
|
||||||
specs:
|
specs:
|
||||||
localize_input (0.1.0)
|
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
|
GIT
|
||||||
remote: git://github.com/technoweenie/acts_as_versioned.git
|
remote: git://github.com/technoweenie/acts_as_versioned.git
|
||||||
revision: 63b1fc8529d028fae632fe80ec0cb25df56cd76b
|
revision: 63b1fc8529d028fae632fe80ec0cb25df56cd76b
|
||||||
|
@ -69,6 +62,14 @@ GEM
|
||||||
net-ssh-gateway (>= 1.1.0)
|
net-ssh-gateway (>= 1.1.0)
|
||||||
capistrano-ext (1.2.1)
|
capistrano-ext (1.2.1)
|
||||||
capistrano (>= 1.0.0)
|
capistrano (>= 1.0.0)
|
||||||
|
capybara (2.1.0)
|
||||||
|
mime-types (>= 1.16)
|
||||||
|
nokogiri (>= 1.3.3)
|
||||||
|
rack (>= 1.0.0)
|
||||||
|
rack-test (>= 0.5.4)
|
||||||
|
xpath (~> 2.0)
|
||||||
|
childprocess (0.3.9)
|
||||||
|
ffi (~> 1.0, >= 1.0.11)
|
||||||
chronic (0.9.0)
|
chronic (0.9.0)
|
||||||
client_side_validations (3.1.4)
|
client_side_validations (3.1.4)
|
||||||
coderay (1.0.8)
|
coderay (1.0.8)
|
||||||
|
@ -81,6 +82,8 @@ GEM
|
||||||
coffee-script-source (1.3.3)
|
coffee-script-source (1.3.3)
|
||||||
commonjs (0.2.6)
|
commonjs (0.2.6)
|
||||||
daemons (1.1.9)
|
daemons (1.1.9)
|
||||||
|
database_cleaner (0.7.1)
|
||||||
|
diff-lcs (1.2.4)
|
||||||
erubis (2.7.0)
|
erubis (2.7.0)
|
||||||
eventmachine (1.0.3)
|
eventmachine (1.0.3)
|
||||||
exception_notification (2.6.1)
|
exception_notification (2.6.1)
|
||||||
|
@ -88,6 +91,14 @@ GEM
|
||||||
execjs (1.4.0)
|
execjs (1.4.0)
|
||||||
multi_json (~> 1.0)
|
multi_json (~> 1.0)
|
||||||
expression_parser (0.9.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)
|
||||||
|
faker (1.1.2)
|
||||||
|
i18n (~> 0.5)
|
||||||
|
ffi (1.9.0)
|
||||||
haml (3.1.7)
|
haml (3.1.7)
|
||||||
haml-rails (0.3.5)
|
haml-rails (0.3.5)
|
||||||
actionpack (>= 3.1, < 4.1)
|
actionpack (>= 3.1, < 4.1)
|
||||||
|
@ -99,9 +110,13 @@ GEM
|
||||||
highline (1.6.19)
|
highline (1.6.19)
|
||||||
hike (1.2.3)
|
hike (1.2.3)
|
||||||
i18n (0.6.1)
|
i18n (0.6.1)
|
||||||
|
i18n-spec (0.4.0)
|
||||||
|
iso
|
||||||
inherited_resources (1.3.1)
|
inherited_resources (1.3.1)
|
||||||
has_scope (~> 0.5.0)
|
has_scope (~> 0.5.0)
|
||||||
responders (~> 0.6)
|
responders (~> 0.6)
|
||||||
|
iso (0.2.0)
|
||||||
|
i18n
|
||||||
journey (1.0.4)
|
journey (1.0.4)
|
||||||
jquery-rails (2.1.3)
|
jquery-rails (2.1.3)
|
||||||
railties (>= 3.1.0, < 5.0)
|
railties (>= 3.1.0, < 5.0)
|
||||||
|
@ -135,8 +150,9 @@ GEM
|
||||||
activesupport (~> 3.1)
|
activesupport (~> 3.1)
|
||||||
polyamorous (~> 0.5.0)
|
polyamorous (~> 0.5.0)
|
||||||
mime-types (1.21)
|
mime-types (1.21)
|
||||||
|
mini_portile (0.5.1)
|
||||||
mono_logger (1.1.0)
|
mono_logger (1.1.0)
|
||||||
multi_json (1.7.6)
|
multi_json (1.7.9)
|
||||||
mysql2 (0.3.11)
|
mysql2 (0.3.11)
|
||||||
net-scp (1.1.1)
|
net-scp (1.1.1)
|
||||||
net-ssh (>= 2.6.5)
|
net-ssh (>= 2.6.5)
|
||||||
|
@ -145,6 +161,8 @@ GEM
|
||||||
net-ssh (2.6.7)
|
net-ssh (2.6.7)
|
||||||
net-ssh-gateway (1.2.0)
|
net-ssh-gateway (1.2.0)
|
||||||
net-ssh (>= 2.6.5)
|
net-ssh (>= 2.6.5)
|
||||||
|
nokogiri (1.6.0)
|
||||||
|
mini_portile (~> 0.5.0)
|
||||||
pdf-reader (1.2.0)
|
pdf-reader (1.2.0)
|
||||||
Ascii85 (~> 1.0.0)
|
Ascii85 (~> 1.0.0)
|
||||||
hashery (~> 2.0)
|
hashery (~> 2.0)
|
||||||
|
@ -187,7 +205,7 @@ GEM
|
||||||
rdoc (3.12.2)
|
rdoc (3.12.2)
|
||||||
json (~> 1.4)
|
json (~> 1.4)
|
||||||
redis (3.0.4)
|
redis (3.0.4)
|
||||||
redis-namespace (1.3.0)
|
redis-namespace (1.3.1)
|
||||||
redis (~> 3.0.0)
|
redis (~> 3.0.0)
|
||||||
responders (0.9.3)
|
responders (0.9.3)
|
||||||
railties (~> 3.1)
|
railties (~> 3.1)
|
||||||
|
@ -197,8 +215,20 @@ GEM
|
||||||
redis-namespace (~> 1.2)
|
redis-namespace (~> 1.2)
|
||||||
sinatra (>= 0.9.2)
|
sinatra (>= 0.9.2)
|
||||||
vegas (~> 0.1.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-prof (0.13.0)
|
||||||
ruby-rc4 (0.1.5)
|
ruby-rc4 (0.1.5)
|
||||||
|
rubyzip (0.9.9)
|
||||||
sass (3.2.1)
|
sass (3.2.1)
|
||||||
sass-rails (3.2.5)
|
sass-rails (3.2.5)
|
||||||
railties (~> 3.2.0)
|
railties (~> 3.2.0)
|
||||||
|
@ -207,6 +237,11 @@ GEM
|
||||||
select2-rails (3.4.2)
|
select2-rails (3.4.2)
|
||||||
sass-rails
|
sass-rails
|
||||||
thor (~> 0.14)
|
thor (~> 0.14)
|
||||||
|
selenium-webdriver (2.35.1)
|
||||||
|
childprocess (>= 0.2.5)
|
||||||
|
multi_json (~> 1.0)
|
||||||
|
rubyzip (< 1.0.0)
|
||||||
|
websocket (~> 1.0.4)
|
||||||
simple-navigation (3.9.0)
|
simple-navigation (3.9.0)
|
||||||
activesupport (>= 2.3.2)
|
activesupport (>= 2.3.2)
|
||||||
simple-navigation-bootstrap (0.0.4)
|
simple-navigation-bootstrap (0.0.4)
|
||||||
|
@ -214,6 +249,10 @@ GEM
|
||||||
simple_form (2.1.0)
|
simple_form (2.1.0)
|
||||||
actionpack (~> 3.0)
|
actionpack (~> 3.0)
|
||||||
activemodel (~> 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)
|
sinatra (1.3.6)
|
||||||
rack (~> 1.4)
|
rack (~> 1.4)
|
||||||
rack-protection (~> 1.3)
|
rack-protection (~> 1.3)
|
||||||
|
@ -227,7 +266,6 @@ GEM
|
||||||
rack (~> 1.0)
|
rack (~> 1.0)
|
||||||
tilt (~> 1.1, != 1.3.0)
|
tilt (~> 1.1, != 1.3.0)
|
||||||
sqlite3 (1.3.6)
|
sqlite3 (1.3.6)
|
||||||
test-unit (2.5.3)
|
|
||||||
therubyracer (0.10.2)
|
therubyracer (0.10.2)
|
||||||
libv8 (~> 3.3.10)
|
libv8 (~> 3.3.10)
|
||||||
thin (1.5.1)
|
thin (1.5.1)
|
||||||
|
@ -252,18 +290,20 @@ GEM
|
||||||
uniform_notifier (1.1.1)
|
uniform_notifier (1.1.1)
|
||||||
vegas (0.1.11)
|
vegas (0.1.11)
|
||||||
rack (>= 1.0.0)
|
rack (>= 1.0.0)
|
||||||
|
websocket (1.0.7)
|
||||||
whenever (0.8.1)
|
whenever (0.8.1)
|
||||||
activesupport (>= 2.3.4)
|
activesupport (>= 2.3.4)
|
||||||
chronic (>= 0.6.3)
|
chronic (>= 0.6.3)
|
||||||
wikicloth (0.8.0)
|
wikicloth (0.8.0)
|
||||||
builder
|
builder
|
||||||
expression_parser
|
expression_parser
|
||||||
|
xpath (2.0.0)
|
||||||
|
nokogiri (~> 1.3)
|
||||||
|
|
||||||
PLATFORMS
|
PLATFORMS
|
||||||
ruby
|
ruby
|
||||||
|
|
||||||
DEPENDENCIES
|
DEPENDENCIES
|
||||||
acts_as_configurable!
|
|
||||||
acts_as_tree
|
acts_as_tree
|
||||||
acts_as_versioned!
|
acts_as_versioned!
|
||||||
better_errors
|
better_errors
|
||||||
|
@ -272,11 +312,16 @@ DEPENDENCIES
|
||||||
bullet
|
bullet
|
||||||
capistrano (= 2.13.5)
|
capistrano (= 2.13.5)
|
||||||
capistrano-ext
|
capistrano-ext
|
||||||
|
capybara (~> 2.1.0)
|
||||||
client_side_validations
|
client_side_validations
|
||||||
coffee-rails (~> 3.2.1)
|
coffee-rails (~> 3.2.1)
|
||||||
daemons
|
daemons
|
||||||
|
database_cleaner
|
||||||
exception_notification
|
exception_notification
|
||||||
|
factory_girl_rails (~> 4.0)
|
||||||
|
faker
|
||||||
haml-rails
|
haml-rails
|
||||||
|
i18n-spec
|
||||||
inherited_resources
|
inherited_resources
|
||||||
jquery-rails
|
jquery-rails
|
||||||
kaminari
|
kaminari
|
||||||
|
@ -289,14 +334,18 @@ DEPENDENCIES
|
||||||
rails (~> 3.2.9)
|
rails (~> 3.2.9)
|
||||||
rails-settings-cached (= 0.2.4)
|
rails-settings-cached (= 0.2.4)
|
||||||
resque
|
resque
|
||||||
|
rspec-core
|
||||||
|
rspec-expectations
|
||||||
|
rspec-rails
|
||||||
ruby-prof
|
ruby-prof
|
||||||
sass-rails (~> 3.2.3)
|
sass-rails (~> 3.2.3)
|
||||||
select2-rails
|
select2-rails
|
||||||
|
selenium-webdriver (~> 2.35.1)
|
||||||
simple-navigation
|
simple-navigation
|
||||||
simple-navigation-bootstrap
|
simple-navigation-bootstrap
|
||||||
simple_form
|
simple_form
|
||||||
|
simplecov
|
||||||
sqlite3
|
sqlite3
|
||||||
test-unit
|
|
||||||
therubyracer
|
therubyracer
|
||||||
thin
|
thin
|
||||||
twitter-bootstrap-rails
|
twitter-bootstrap-rails
|
||||||
|
|
|
@ -1,10 +1,6 @@
|
||||||
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
|
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)
|
[![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)
|
[![Dependency Status](https://gemnasium.com/foodcoops/foodsoft.png)](https://gemnasium.com/foodcoops/foodsoft)
|
||||||
|
|
||||||
|
|
|
@ -209,7 +209,7 @@ class ArticlesController < ApplicationController
|
||||||
|
|
||||||
# fills a form whith values of the selected shared_article
|
# fills a form whith values of the selected shared_article
|
||||||
def import
|
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
|
render :action => 'new', :layout => false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@ class SuppliersController < ApplicationController
|
||||||
def new
|
def new
|
||||||
if params[:shared_supplier_id]
|
if params[:shared_supplier_id]
|
||||||
shared_supplier = SharedSupplier.find(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
|
else
|
||||||
@supplier = Supplier.new
|
@supplier = Supplier.new
|
||||||
end
|
end
|
||||||
|
|
|
@ -20,20 +20,28 @@ class OrderFax < OrderPdf
|
||||||
move_down 5
|
move_down 5
|
||||||
text "#{contact[:zip_code]} #{contact[:city]}", size: 9, align: :right
|
text "#{contact[:zip_code]} #{contact[:city]}", size: 9, align: :right
|
||||||
move_down 5
|
move_down 5
|
||||||
text "#{I18n.t('simple_form.labels.supplier.customer_number')}: #{@order.supplier.try(:customer_number)}", 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
|
move_down 5
|
||||||
|
end
|
||||||
|
unless contact[:phone].blank?
|
||||||
text "#{I18n.t('simple_form.labels.supplier.phone')}: #{contact[:phone]}", size: 9, align: :right
|
text "#{I18n.t('simple_form.labels.supplier.phone')}: #{contact[:phone]}", size: 9, align: :right
|
||||||
move_down 5
|
move_down 5
|
||||||
|
end
|
||||||
|
unless contact[:email].blank?
|
||||||
text "#{I18n.t('simple_form.labels.supplier.email')}: #{contact[:email]}", size: 9, align: :right
|
text "#{I18n.t('simple_form.labels.supplier.email')}: #{contact[:email]}", size: 9, align: :right
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
# Recipient
|
# Recipient
|
||||||
bounding_box [margin_box.left,margin_box.top-60], width: 200 do
|
bounding_box [margin_box.left,margin_box.top-60], width: 200 do
|
||||||
text @order.name
|
text @order.name
|
||||||
move_down 5
|
move_down 5
|
||||||
text @order.supplier.try(:address).to_s
|
text @order.supplier.try(:address).to_s
|
||||||
|
unless @order.supplier.try(:fax).blank?
|
||||||
move_down 5
|
move_down 5
|
||||||
text "#{I18n.t('simple_form.labels.supplier.fax')}: #{@order.supplier.try(:fax)}"
|
text "#{I18n.t('simple_form.labels.supplier.fax')}: #{@order.supplier[:fax]}"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
move_down 5
|
move_down 5
|
||||||
|
@ -42,25 +50,37 @@ class OrderFax < OrderPdf
|
||||||
move_down 10
|
move_down 10
|
||||||
text "#{I18n.t('simple_form.labels.delivery.delivered_on')}:"
|
text "#{I18n.t('simple_form.labels.delivery.delivered_on')}:"
|
||||||
move_down 10
|
move_down 10
|
||||||
text "#{I18n.t('simple_form.labels.supplier.contact_person')}: #{@order.supplier.try(:contact_person)}"
|
unless @order.supplier.try(:contact_person).blank?
|
||||||
|
text "#{I18n.t('simple_form.labels.supplier.contact_person')}: #{@order.supplier[:contact_person]}"
|
||||||
move_down 10
|
move_down 10
|
||||||
|
end
|
||||||
|
|
||||||
# Articles
|
# Articles
|
||||||
|
total = 0
|
||||||
data = [I18n.t('documents.order_fax.rows')]
|
data = [I18n.t('documents.order_fax.rows')]
|
||||||
data += @order.order_articles.ordered.all(include: :article).collect do |a|
|
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.article.order_number,
|
||||||
a.units_to_order,
|
a.units_to_order,
|
||||||
a.article.name,
|
a.article.name,
|
||||||
a.price.unit_quantity,
|
a.price.unit_quantity,
|
||||||
a.article.unit,
|
a.article.unit,
|
||||||
a.price.price]
|
number_to_currency(a.price.price),
|
||||||
|
number_to_currency(subtotal)]
|
||||||
end
|
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 data, cell_style: {size: 8, overflow: :shrink_to_fit} do |table|
|
||||||
|
table.header = true
|
||||||
table.cells.border_width = 1
|
table.cells.border_width = 1
|
||||||
table.cells.border_color = '666666'
|
table.cells.border_color = '666666'
|
||||||
|
|
||||||
|
table.row(0).border_bottom_width = 2
|
||||||
table.columns(1).align = :right
|
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
|
end
|
||||||
#font_size: 8,
|
#font_size: 8,
|
||||||
#vertical_padding: 3,
|
#vertical_padding: 3,
|
||||||
|
|
6
app/helpers/suppliers_helper.rb
Normal file
6
app/helpers/suppliers_helper.rb
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
module SuppliersHelper
|
||||||
|
|
||||||
|
def associated_supplier_names(shared_supplier)
|
||||||
|
"(#{shared_supplier.suppliers.map(&:name).join(', ')})"
|
||||||
|
end
|
||||||
|
end
|
|
@ -7,8 +7,8 @@ class SharedArticle < ActiveRecord::Base
|
||||||
|
|
||||||
belongs_to :shared_supplier, :foreign_key => :supplier_id
|
belongs_to :shared_supplier, :foreign_key => :supplier_id
|
||||||
|
|
||||||
def build_new_article
|
def build_new_article(supplier)
|
||||||
shared_supplier.supplier.articles.build(
|
supplier.articles.build(
|
||||||
:name => name,
|
:name => name,
|
||||||
:unit => unit,
|
:unit => unit,
|
||||||
:note => note,
|
:note => note,
|
||||||
|
|
|
@ -5,7 +5,7 @@ class SharedSupplier < ActiveRecord::Base
|
||||||
# set correct table_name in external DB
|
# set correct table_name in external DB
|
||||||
self.table_name = 'suppliers'
|
self.table_name = 'suppliers'
|
||||||
|
|
||||||
has_one :supplier
|
has_many :suppliers
|
||||||
has_many :shared_articles, :foreign_key => :supplier_id
|
has_many :shared_articles, :foreign_key => :supplier_id
|
||||||
|
|
||||||
# These set of attributes are used to autofill attributes of new supplier,
|
# These set of attributes are used to autofill attributes of new supplier,
|
||||||
|
|
|
@ -13,11 +13,9 @@ class Supplier < ActiveRecord::Base
|
||||||
:delivery_days, :order_howto, :note, :shared_supplier_id, :min_order_quantity
|
:delivery_days, :order_howto, :note, :shared_supplier_id, :min_order_quantity
|
||||||
|
|
||||||
validates :name, :presence => true, :length => { :in => 4..30 }
|
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 :address, :presence => true, :length => { :in => 8..50 }
|
||||||
validates_length_of :order_howto, :note, maximum: 250
|
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
|
validate :uniqueness_of_name
|
||||||
|
|
||||||
scope :undeleted, -> { where(deleted_at: nil) }
|
scope :undeleted, -> { where(deleted_at: nil) }
|
||||||
|
|
|
@ -66,7 +66,7 @@ class User < ActiveRecord::Base
|
||||||
end
|
end
|
||||||
|
|
||||||
def receive_email?
|
def receive_email?
|
||||||
settings.messages['send_as_email'] == "1" && email.present?
|
settings.messages['send_as_email'] && email.present?
|
||||||
end
|
end
|
||||||
|
|
||||||
# Sets the user's password. It will be stored encrypted along with a random salt.
|
# Sets the user's password. It will be stored encrypted along with a random salt.
|
||||||
|
|
|
@ -3,7 +3,7 @@ class Workgroup < Group
|
||||||
|
|
||||||
has_many :tasks
|
has_many :tasks
|
||||||
# returns all non-finished 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
|
validates_uniqueness_of :name
|
||||||
validate :last_admin_on_earth, :on => :update
|
validate :last_admin_on_earth, :on => :update
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
.well.well-small
|
.well.well-small
|
||||||
%h3= t('.notes_and_journal')
|
%h3= t('.notes_and_journal')
|
||||||
#note
|
#note
|
||||||
- unless @order.note.empty?
|
- unless @order.note.blank?
|
||||||
= simple_format @order.note
|
= simple_format @order.note
|
||||||
- else
|
- else
|
||||||
%p= t('.comment_on_transaction')
|
%p= t('.comment_on_transaction')
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
%thead
|
%thead
|
||||||
%tr
|
%tr
|
||||||
%th= sort_link_helper t('.name'), "name", :per_page => @per_page
|
%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.numeric= sort_link_helper t('.account_balance'), "account_balance", :per_page => @per_page
|
||||||
%th
|
%th
|
||||||
%tbody
|
%tbody
|
||||||
|
|
|
@ -56,7 +56,7 @@
|
||||||
%pre
|
%pre
|
||||||
* #{t '.help.list_item_1'}
|
* #{t '.help.list_item_1'}
|
||||||
%pre
|
%pre
|
||||||
** #{t '.help_list_item_2'}
|
** #{t '.help.list_item_2'}
|
||||||
%tr
|
%tr
|
||||||
%td= t '.help.ordered_list'
|
%td= t '.help.ordered_list'
|
||||||
%td
|
%td
|
||||||
|
|
|
@ -4,4 +4,4 @@
|
||||||
= f.input :date
|
= f.input :date
|
||||||
= f.input :note
|
= f.input :note
|
||||||
= f.submit
|
= f.submit
|
||||||
= link_to t('ui.cancel'), stock_takings_path
|
= link_to t('ui.or_cancel'), stock_takings_path
|
||||||
|
|
|
@ -14,4 +14,4 @@
|
||||||
= render :partial => 'stock_change', :collection => @stock_taking.stock_changes
|
= render :partial => 'stock_change', :collection => @stock_taking.stock_changes
|
||||||
.form-actions
|
.form-actions
|
||||||
= f.submit class: 'btn'
|
= f.submit class: 'btn'
|
||||||
= link_to t('ui.cancel'), stock_takings_path
|
= link_to t('ui.or_cancel'), stock_takings_path
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
- title "Lager (#{StockArticle.available.count})"
|
- title t('.title', article_count: StockArticle.available.count)
|
||||||
- content_for :javascript do
|
- content_for :javascript do
|
||||||
:javascript
|
:javascript
|
||||||
$(function() {
|
$(function() {
|
||||||
|
|
|
@ -17,7 +17,9 @@
|
||||||
%td= shared_supplier.note
|
%td= shared_supplier.note
|
||||||
%td= shared_supplier.delivery_days
|
%td= shared_supplier.delivery_days
|
||||||
%td
|
%td
|
||||||
- if shared_supplier.supplier
|
- if shared_supplier.suppliers.any?
|
||||||
%i.icon-ok
|
%i.icon-ok
|
||||||
|
= associated_supplier_names(shared_supplier)
|
||||||
|
= link_to t('.subscribe_again'), new_supplier_path(:shared_supplier_id => shared_supplier), class: 'btn'
|
||||||
- else
|
- else
|
||||||
= link_to t('.subscribe'), new_supplier_path(:shared_supplier_id => shared_supplier), class: 'btn'
|
= link_to t('.subscribe'), new_supplier_path(:shared_supplier_id => shared_supplier), class: 'btn'
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
- content_for :sidebar do
|
- content_for :sidebar do
|
||||||
.well.well-small
|
.well.well-small
|
||||||
%ul.nav.nav-list
|
%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('.my_tasks'), user_tasks_path
|
||||||
%li= link_to t('.all_tasks'), tasks_path
|
%li= link_to t('.all_tasks'), tasks_path
|
||||||
%li= link_to t('.archive'), archive_tasks_path
|
%li= link_to t('.archive'), archive_tasks_path
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
- title "Meine Aufgaben"
|
- title t('.title')
|
||||||
= render 'nav'
|
= render 'nav'
|
||||||
|
|
||||||
- unless @unaccepted_tasks.empty?
|
- unless @unaccepted_tasks.empty?
|
||||||
|
|
|
@ -505,6 +505,7 @@ de:
|
||||||
- Gebinde
|
- Gebinde
|
||||||
- Einheit
|
- Einheit
|
||||||
- Preis/Einheit
|
- Preis/Einheit
|
||||||
|
total: Gesamtpreis
|
||||||
order_matrix:
|
order_matrix:
|
||||||
filename: Bestellung %{name}-%{date} - Sortiermatrix
|
filename: Bestellung %{name}-%{date} - Sortiermatrix
|
||||||
heading: Artikelübersicht
|
heading: Artikelübersicht
|
||||||
|
@ -719,6 +720,7 @@ de:
|
||||||
ordergroups:
|
ordergroups:
|
||||||
account_balance: Kontostand
|
account_balance: Kontostand
|
||||||
account_statement: Kontoauszug
|
account_statement: Kontoauszug
|
||||||
|
contact: Kontakt
|
||||||
name: Name
|
name: Name
|
||||||
new_transaction: Neue Transaktion
|
new_transaction: Neue Transaktion
|
||||||
update:
|
update:
|
||||||
|
@ -1604,6 +1606,7 @@ de:
|
||||||
contact_person: Kontaktperson
|
contact_person: Kontaktperson
|
||||||
contact_phone: Telefon
|
contact_phone: Telefon
|
||||||
ignore_apple_restriction: Bestellstop bei zu wenig Äpfeln ignorieren
|
ignore_apple_restriction: Bestellstop bei zu wenig Äpfeln ignorieren
|
||||||
|
name: Name
|
||||||
page:
|
page:
|
||||||
body: Inhalt
|
body: Inhalt
|
||||||
parent_id: Oberseite
|
parent_id: Oberseite
|
||||||
|
@ -1671,6 +1674,7 @@ de:
|
||||||
language:
|
language:
|
||||||
de: Deutsch
|
de: Deutsch
|
||||||
en: English
|
en: English
|
||||||
|
fr: Französisch
|
||||||
nl: Niederländisch
|
nl: Niederländisch
|
||||||
required:
|
required:
|
||||||
mark: ! '*'
|
mark: ! '*'
|
||||||
|
@ -1744,6 +1748,7 @@ de:
|
||||||
show_stock_takings: Inventurübersicht
|
show_stock_takings: Inventurübersicht
|
||||||
stock_count: ! 'Artikelanzahl:'
|
stock_count: ! 'Artikelanzahl:'
|
||||||
stock_worth: ! 'Aktueller Lagerwert:'
|
stock_worth: ! 'Aktueller Lagerwert:'
|
||||||
|
title: Lager (%{article_count})
|
||||||
toggle_unavailable: Nicht verfügbare Artikel zeigen/verstecken
|
toggle_unavailable: Nicht verfügbare Artikel zeigen/verstecken
|
||||||
view_options: Ansichtsoptionen
|
view_options: Ansichtsoptionen
|
||||||
new:
|
new:
|
||||||
|
@ -1774,6 +1779,7 @@ de:
|
||||||
shared_suppliers:
|
shared_suppliers:
|
||||||
body: <p>Hier werden die Lieferantinnen der externen Datenbank angezeigt.</p> <p>Ihr könnt externe Lieferantinnen importieren, indem ihr sie einfach abonniert. (siehe unten)</p> <p>Damit wird eine neue Lieferantin angelegt und mit der externen Datenbank verknüpft.</p>
|
body: <p>Hier werden die Lieferantinnen der externen Datenbank angezeigt.</p> <p>Ihr könnt externe Lieferantinnen importieren, indem ihr sie einfach abonniert. (siehe unten)</p> <p>Damit wird eine neue Lieferantin angelegt und mit der externen Datenbank verknüpft.</p>
|
||||||
subscribe: abonnieren
|
subscribe: abonnieren
|
||||||
|
subscribe_again: erneut abonnieren
|
||||||
supplier: Lieferantin
|
supplier: Lieferantin
|
||||||
title: Externe Listen
|
title: Externe Listen
|
||||||
show:
|
show:
|
||||||
|
@ -1834,6 +1840,7 @@ de:
|
||||||
group_tasks: Gruppenaufgaben
|
group_tasks: Gruppenaufgaben
|
||||||
my_tasks: Meine Aufgaben
|
my_tasks: Meine Aufgaben
|
||||||
new_task: Neue Aufgabe erstellen
|
new_task: Neue Aufgabe erstellen
|
||||||
|
pages: Seiten
|
||||||
new:
|
new:
|
||||||
title: Neue Aufgabe erstellen
|
title: Neue Aufgabe erstellen
|
||||||
repeated: Aufgabe wird wöchentlich wiederholt
|
repeated: Aufgabe wird wöchentlich wiederholt
|
||||||
|
|
|
@ -236,7 +236,7 @@ en:
|
||||||
option_available: Make articles available
|
option_available: Make articles available
|
||||||
option_delete: Delete article
|
option_delete: Delete article
|
||||||
option_not_available: Make articles unavailable
|
option_not_available: Make articles unavailable
|
||||||
option_select: Choose special offer ...
|
option_select: Select action ...
|
||||||
price_netto: Price
|
price_netto: Price
|
||||||
unit_quantity_desc: Unit quantity
|
unit_quantity_desc: Unit quantity
|
||||||
unit_quantity_short: Quantity
|
unit_quantity_short: Quantity
|
||||||
|
@ -440,7 +440,7 @@ en:
|
||||||
article: Article
|
article: Article
|
||||||
category: Category
|
category: Category
|
||||||
create_from_blank: Create new article
|
create_from_blank: Create new article
|
||||||
create_stock_article: Create stock articles
|
create_stock_article: Create stock article
|
||||||
price: Netprice
|
price: Netprice
|
||||||
quantity: Quantity
|
quantity: Quantity
|
||||||
title_fill_quantities: 2. Set delivery quantities
|
title_fill_quantities: 2. Set delivery quantities
|
||||||
|
@ -493,7 +493,7 @@ en:
|
||||||
- Article
|
- Article
|
||||||
- Amount
|
- Amount
|
||||||
- Price
|
- Price
|
||||||
- Unit Quantity
|
- Unit quantity
|
||||||
- Unit
|
- Unit
|
||||||
- Sum
|
- Sum
|
||||||
sum: Sum
|
sum: Sum
|
||||||
|
@ -504,20 +504,24 @@ en:
|
||||||
- Order Number
|
- Order Number
|
||||||
- Amount
|
- Amount
|
||||||
- Name
|
- Name
|
||||||
- Barrel
|
- Unit quantity
|
||||||
- Unit
|
- Unit
|
||||||
- Price/Unit
|
- Price/Unit
|
||||||
|
- Subtotal
|
||||||
|
total: Total
|
||||||
order_matrix:
|
order_matrix:
|
||||||
filename: Order %{name}-%{date} - sorting matrix
|
filename: Order %{name}-%{date} - sorting matrix
|
||||||
heading: Article overview
|
heading: Article overview
|
||||||
rows:
|
rows:
|
||||||
- Article
|
- Article
|
||||||
- Unit
|
- Unit
|
||||||
- Barrel
|
- Unit quantity
|
||||||
- FC-Price
|
- FC-Price
|
||||||
- Amount
|
- Amount
|
||||||
title: ! 'Order sorting matrix: %{name}, closed at %{date}'
|
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:
|
errors:
|
||||||
format: ! '%{attribute} %{message}'
|
format: ! '%{attribute} %{message}'
|
||||||
general: A problem has occured.
|
general: A problem has occured.
|
||||||
|
@ -721,6 +725,7 @@ en:
|
||||||
ordergroups:
|
ordergroups:
|
||||||
account_balance: Account balance
|
account_balance: Account balance
|
||||||
account_statement: Account statement
|
account_statement: Account statement
|
||||||
|
contact: Contact
|
||||||
name: Name
|
name: Name
|
||||||
new_transaction: New transaction
|
new_transaction: New transaction
|
||||||
update:
|
update:
|
||||||
|
@ -1606,6 +1611,7 @@ en:
|
||||||
contact_person: Contact person
|
contact_person: Contact person
|
||||||
contact_phone: Phone
|
contact_phone: Phone
|
||||||
ignore_apple_restriction: Ignore order stop by apple points restriction
|
ignore_apple_restriction: Ignore order stop by apple points restriction
|
||||||
|
name: Name
|
||||||
page:
|
page:
|
||||||
body: Body
|
body: Body
|
||||||
parent_id: Parent page
|
parent_id: Parent page
|
||||||
|
@ -1673,6 +1679,7 @@ en:
|
||||||
language:
|
language:
|
||||||
de: German
|
de: German
|
||||||
en: English
|
en: English
|
||||||
|
fr: French
|
||||||
nl: Dutch
|
nl: Dutch
|
||||||
required:
|
required:
|
||||||
mark: ! '*'
|
mark: ! '*'
|
||||||
|
@ -1746,6 +1753,7 @@ en:
|
||||||
show_stock_takings: Inventory overview
|
show_stock_takings: Inventory overview
|
||||||
stock_count: ! 'Number of articles:'
|
stock_count: ! 'Number of articles:'
|
||||||
stock_worth: ! 'Current stock value:'
|
stock_worth: ! 'Current stock value:'
|
||||||
|
title: Stock (%{article_count})
|
||||||
toggle_unavailable: Show/hide unavailable articles
|
toggle_unavailable: Show/hide unavailable articles
|
||||||
view_options: View options
|
view_options: View options
|
||||||
new:
|
new:
|
||||||
|
@ -1776,6 +1784,7 @@ en:
|
||||||
shared_suppliers:
|
shared_suppliers:
|
||||||
body: <p>Suppliers of the external database are displayed here.</p> <p>You can import external suppliers by subscribing (see below).</p> <p>A new supplier will be created and connected to the external database.</p>
|
body: <p>Suppliers of the external database are displayed here.</p> <p>You can import external suppliers by subscribing (see below).</p> <p>A new supplier will be created and connected to the external database.</p>
|
||||||
subscribe: Subscribe
|
subscribe: Subscribe
|
||||||
|
subscribe_again: Subscribe again
|
||||||
supplier: Supplier
|
supplier: Supplier
|
||||||
title: External lists
|
title: External lists
|
||||||
show:
|
show:
|
||||||
|
@ -1836,6 +1845,7 @@ en:
|
||||||
group_tasks: Group tasks
|
group_tasks: Group tasks
|
||||||
my_tasks: My tasks
|
my_tasks: My tasks
|
||||||
new_task: Create new task
|
new_task: Create new task
|
||||||
|
pages: Pages
|
||||||
new:
|
new:
|
||||||
title: Create new tasks
|
title: Create new tasks
|
||||||
repeated: Task is repeated weekly
|
repeated: Task is repeated weekly
|
||||||
|
|
1919
config/locales/fr.yml
Normal file
1919
config/locales/fr.yml
Normal file
File diff suppressed because it is too large
Load diff
|
@ -479,48 +479,60 @@ nl:
|
||||||
notice:
|
notice:
|
||||||
documents:
|
documents:
|
||||||
order_by_articles:
|
order_by_articles:
|
||||||
filename:
|
filename: Bestelling %{name}-%{date} - Artikellijst
|
||||||
rows:
|
rows:
|
||||||
title:
|
- Huishouden
|
||||||
|
- Hoeveelheid
|
||||||
|
- Prijs
|
||||||
|
title: ! 'Artikellijst van bestelling: %{name}, gesloten op %{date}'
|
||||||
order_by_groups:
|
order_by_groups:
|
||||||
filename:
|
filename: Bestelling %{name}-%{date} - Huishoudenslijst
|
||||||
rows:
|
rows:
|
||||||
sum:
|
- Artikel
|
||||||
title:
|
- Hoeveelheid
|
||||||
|
- Prijs
|
||||||
|
- Gr.Eenh.
|
||||||
|
- Eenheid
|
||||||
|
- Som
|
||||||
|
sum: Som
|
||||||
|
title: ! 'Huishoudenslijst van bestelling: %{name}, gesloten op %{date}'
|
||||||
order_fax:
|
order_fax:
|
||||||
filename:
|
filename: Bestelling %{name}-%{date} - Fax
|
||||||
rows:
|
rows: ! '[]'
|
||||||
|
total: Totaal
|
||||||
order_matrix:
|
order_matrix:
|
||||||
filename:
|
filename: Bestelling %{name}-%{date} - Sorteermatrix
|
||||||
heading:
|
heading: Artikeloverzicht
|
||||||
rows:
|
rows:
|
||||||
title:
|
title: ! 'Sorteermatrix van bestelling: %{name}, gesloten op %{date}'
|
||||||
total:
|
total:
|
||||||
|
one: In totaal éen artikel
|
||||||
|
other: In totaal %{count} artikelen
|
||||||
errors:
|
errors:
|
||||||
format:
|
format:
|
||||||
general:
|
general: Er is een probleem opgetreden.
|
||||||
general_again:
|
general_again:
|
||||||
general_msg:
|
general_msg: ! 'Er is een probleem opgetreden: %{msg}'
|
||||||
messages:
|
messages:
|
||||||
accepted:
|
accepted: moet geaccepteerd worden
|
||||||
blank:
|
blank: moet ingevuld worden
|
||||||
confirmation:
|
confirmation:
|
||||||
empty:
|
empty: moet ingevuld worden
|
||||||
equal_to:
|
equal_to: moet precies %{count} zijn
|
||||||
even:
|
even:
|
||||||
exclusion:
|
exclusion: moet even zijn
|
||||||
greater_than:
|
greater_than: moet groter dan %{count} zijn
|
||||||
greater_than_or_equal_to:
|
greater_than_or_equal_to:
|
||||||
inclusion:
|
inclusion:
|
||||||
invalid:
|
invalid:
|
||||||
less_than:
|
less_than: moet kleiner dan %{count} zijn
|
||||||
less_than_or_equal_to:
|
less_than_or_equal_to: moet groter of gelijk aan %{count} zijn
|
||||||
not_a_number:
|
not_a_number: is geen getal
|
||||||
not_an_integer:
|
not_an_integer: moet een geheel getal zijn
|
||||||
odd:
|
odd: moet oneven zijn
|
||||||
record_invalid:
|
record_invalid:
|
||||||
taken:
|
taken: is al in gebruik
|
||||||
taken_with_deleted:
|
taken_with_deleted: is al in gebruik (verwijderde groep)
|
||||||
too_long:
|
too_long:
|
||||||
too_short:
|
too_short:
|
||||||
wrong_length:
|
wrong_length:
|
||||||
|
@ -697,6 +709,7 @@ nl:
|
||||||
ordergroups:
|
ordergroups:
|
||||||
account_balance: Tegoed
|
account_balance: Tegoed
|
||||||
account_statement:
|
account_statement:
|
||||||
|
contact:
|
||||||
name: Naam
|
name: Naam
|
||||||
new_transaction: Nieuwe transactie
|
new_transaction: Nieuwe transactie
|
||||||
update:
|
update:
|
||||||
|
@ -1493,6 +1506,7 @@ nl:
|
||||||
contact_person: Contactpersoon
|
contact_person: Contactpersoon
|
||||||
contact_phone: Telefoon
|
contact_phone: Telefoon
|
||||||
ignore_apple_restriction:
|
ignore_apple_restriction:
|
||||||
|
name:
|
||||||
page:
|
page:
|
||||||
body:
|
body:
|
||||||
parent_id:
|
parent_id:
|
||||||
|
@ -1560,6 +1574,7 @@ nl:
|
||||||
language:
|
language:
|
||||||
de: Duits
|
de: Duits
|
||||||
en: Engels
|
en: Engels
|
||||||
|
fr: Frans
|
||||||
nl: Nederlands
|
nl: Nederlands
|
||||||
required:
|
required:
|
||||||
mark: ! '*'
|
mark: ! '*'
|
||||||
|
@ -1633,6 +1648,7 @@ nl:
|
||||||
show_stock_takings:
|
show_stock_takings:
|
||||||
stock_count:
|
stock_count:
|
||||||
stock_worth:
|
stock_worth:
|
||||||
|
title:
|
||||||
toggle_unavailable:
|
toggle_unavailable:
|
||||||
view_options:
|
view_options:
|
||||||
new:
|
new:
|
||||||
|
@ -1663,6 +1679,7 @@ nl:
|
||||||
shared_suppliers:
|
shared_suppliers:
|
||||||
body:
|
body:
|
||||||
subscribe:
|
subscribe:
|
||||||
|
subscribe_again:
|
||||||
supplier:
|
supplier:
|
||||||
title:
|
title:
|
||||||
show:
|
show:
|
||||||
|
@ -1723,6 +1740,7 @@ nl:
|
||||||
group_tasks:
|
group_tasks:
|
||||||
my_tasks:
|
my_tasks:
|
||||||
new_task:
|
new_task:
|
||||||
|
pages:
|
||||||
new:
|
new:
|
||||||
title:
|
title:
|
||||||
repeated:
|
repeated:
|
||||||
|
@ -1763,9 +1781,9 @@ nl:
|
||||||
history:
|
history:
|
||||||
marks:
|
marks:
|
||||||
close: ! '×'
|
close: ! '×'
|
||||||
success:
|
success: <i class="icon icon-ok"></i>
|
||||||
or_cancel: of annuleren
|
or_cancel: of annuleren
|
||||||
please_wait:
|
please_wait: Een moment alstublieft...
|
||||||
save: Opslaan
|
save: Opslaan
|
||||||
show: Tonen
|
show: Tonen
|
||||||
views:
|
views:
|
||||||
|
|
|
@ -35,6 +35,8 @@ class MoveWeeklyTasks < ActiveRecord::Migration
|
||||||
|
|
||||||
private
|
private
|
||||||
def weekly_task?(workgroup, task)
|
def weekly_task?(workgroup, task)
|
||||||
|
return false if task.due_date.nil?
|
||||||
|
|
||||||
group_task = {
|
group_task = {
|
||||||
weekday: workgroup.weekday,
|
weekday: workgroup.weekday,
|
||||||
name: workgroup.task_name,
|
name: workgroup.task_name,
|
||||||
|
|
|
@ -1,12 +1,25 @@
|
||||||
class MigrateUserSettings < ActiveRecord::Migration
|
class MigrateUserSettings < ActiveRecord::Migration
|
||||||
def up
|
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 = ConfigurableSetting.all
|
||||||
|
|
||||||
old_settings.each do |old_setting|
|
old_settings.each do |old_setting|
|
||||||
# get target (user)
|
# get target (user)
|
||||||
type = old_setting.configurable_type
|
type = old_setting.configurable_type
|
||||||
id = old_setting.configurable_id
|
id = old_setting.configurable_id
|
||||||
|
begin
|
||||||
user = type.constantize.find(id)
|
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)
|
# get the data (settings)
|
||||||
name = old_setting.name
|
name = old_setting.name
|
||||||
|
@ -27,8 +40,16 @@ class MigrateUserSettings < ActiveRecord::Migration
|
||||||
# save the user to apply after_save callback
|
# save the user to apply after_save callback
|
||||||
user.save
|
user.save
|
||||||
end
|
end
|
||||||
|
|
||||||
|
I18n.default_locale = default_locale
|
||||||
|
end
|
||||||
|
|
||||||
|
drop_table :configurable_settings
|
||||||
end
|
end
|
||||||
|
|
||||||
def down
|
def down
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# this is the base class of all configurable settings
|
||||||
|
class ConfigurableSetting < ActiveRecord::Base; end
|
12
db/schema.rb
12
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
|
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|
|
create_table "deliveries", :force => true do |t|
|
||||||
t.integer "supplier_id"
|
t.integer "supplier_id"
|
||||||
t.date "delivered_on"
|
t.date "delivered_on"
|
||||||
|
|
|
@ -11,7 +11,7 @@ module FoodsoftFile
|
||||||
def self.parse(file)
|
def self.parse(file)
|
||||||
articles, outlisted_articles = Array.new, Array.new
|
articles, outlisted_articles = Array.new, Array.new
|
||||||
row_index = 2
|
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
|
# check if the line is empty
|
||||||
unless row[2] == "" || row[2].nil?
|
unless row[2] == "" || row[2].nil?
|
||||||
article = {:number => row[1],
|
article = {:number => row[1],
|
||||||
|
|
|
@ -38,6 +38,15 @@ namespace :foodsoft do
|
||||||
puts yellow "All done! Your foodcoft should be running smoothly."
|
puts yellow "All done! Your foodcoft should be running smoothly."
|
||||||
start_server
|
start_server
|
||||||
end
|
end
|
||||||
|
|
||||||
|
namespace :setup do
|
||||||
|
desc "Initialize stock configuration"
|
||||||
|
task :stock_config do
|
||||||
|
setup_app_config
|
||||||
|
setup_development
|
||||||
|
setup_secret_token
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def setup_bundler
|
def setup_bundler
|
||||||
|
|
|
@ -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
|
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 :run => :environment do
|
||||||
task_to_run = ARGV[1]
|
task_to_run = ENV['TASK']
|
||||||
FoodsoftConfig.each_coop do |coop|
|
FoodsoftConfig.each_coop do |coop|
|
||||||
puts "Run '#{task_to_run}' for #{coop}"
|
puts "Run '#{task_to_run}' for #{coop}"
|
||||||
Rake::Task[task_to_run].execute
|
Rake::Task[task_to_run].execute
|
||||||
end
|
end
|
||||||
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 :run_single => :environment do
|
||||||
task_to_run = ARGV[1]
|
task_to_run = ENV['TASK']
|
||||||
FoodsoftConfig.select_foodcoop ENV['FOODCOOP']
|
FoodsoftConfig.select_foodcoop ENV['FOODCOOP']
|
||||||
puts "Run '#{task_to_run}' for #{ENV['FOODCOOP']}"
|
puts "Run '#{task_to_run}' for #{ENV['FOODCOOP']}"
|
||||||
Rake::Task[task_to_run].execute
|
Rake::Task[task_to_run].execute
|
||||||
|
|
3
lib/tasks/rspec.rake
Normal file
3
lib/tasks/rspec.rake
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
require 'rspec/core/rake_task'
|
||||||
|
RSpec::Core::RakeTask.new(:spec)
|
||||||
|
task :default => :spec
|
|
@ -55,12 +55,16 @@ fi
|
||||||
sed -i "s|^\\(\\s*gem\\s\\+'sqlite3'\\)|#\1|" Gemfile
|
sed -i "s|^\\(\\s*gem\\s\\+'sqlite3'\\)|#\1|" Gemfile
|
||||||
sed -i "s|^\\(\\s*sqlite3\\b\)|#\1|" Gemfile.lock
|
sed -i "s|^\\(\\s*sqlite3\\b\)|#\1|" Gemfile.lock
|
||||||
# make sure postgresql db is present, as it is the default heroku db
|
# make sure postgresql db is present, as it is the default heroku db
|
||||||
echo $'\ngem "pg"' >>Gemfile
|
echo "
|
||||||
echo $'\ngem "localeapp"' >>Gemfile
|
gem 'pg'" >>Gemfile
|
||||||
# always use unicorn
|
# always use unicorn
|
||||||
echo $'\ngem "unicorn"' >>Gemfile
|
echo "
|
||||||
|
gem 'unicorn'" >>Gemfile
|
||||||
echo 'web: bundle exec unicorn -p $PORT -E $RACK_ENV' >Procfile
|
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
|
# do not ignore deployment files
|
||||||
sed -i 's|^\(config/\*.yml\)|#\1|' .gitignore
|
sed -i 's|^\(config/\*.yml\)|#\1|' .gitignore
|
||||||
sed -i 's|^\(config/initializers/secret_token.rb\)|#\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']
|
config.polling_environments = ['$RAILS_ENV']
|
||||||
end
|
end
|
||||||
EOF
|
EOF
|
||||||
|
echo "
|
||||||
|
gem 'localeapp'" >>Gemfile
|
||||||
# also do not cache so we get locale updates
|
# 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
|
fi
|
||||||
|
# update Gemfile.lock after Gemfile updates (required by heroku)
|
||||||
|
bundle install --quiet
|
||||||
# TODO add more extensive database seed
|
# TODO add more extensive database seed
|
||||||
|
|
||||||
# and push = deploy
|
# and push = deploy
|
||||||
|
|
20
spec/factories/article.rb
Normal file
20
spec/factories/article.rb
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
require 'factory_girl'
|
||||||
|
|
||||||
|
FactoryGirl.define do
|
||||||
|
|
||||||
|
factory :article do
|
||||||
|
sequence(:name) { |n| Faker::Lorem.words(rand(2..4)).join(' ') + " ##{n}" }
|
||||||
|
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
|
||||||
|
sequence(:name) { |n| Faker::Lorem.characters(rand(2..12)) + " ##{n}" }
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
10
spec/factories/group_order.rb
Normal file
10
spec/factories/group_order.rb
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
require 'factory_girl'
|
||||||
|
|
||||||
|
FactoryGirl.define do
|
||||||
|
|
||||||
|
# requires order
|
||||||
|
factory :group_order do
|
||||||
|
ordergroup { FactoryGirl.create(:user, groups: [FactoryGirl.create(:ordergroup)]).ordergroup }
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
9
spec/factories/group_order_article.rb
Normal file
9
spec/factories/group_order_article.rb
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
require 'factory_girl'
|
||||||
|
|
||||||
|
FactoryGirl.define do
|
||||||
|
|
||||||
|
# requires order_article
|
||||||
|
factory :group_order_article do
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
31
spec/factories/order.rb
Normal file
31
spec/factories/order.rb
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
require 'factory_girl'
|
||||||
|
|
||||||
|
FactoryGirl.define do
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
# requires order and article
|
||||||
|
factory :order_article do
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
21
spec/factories/supplier.rb
Normal file
21
spec/factories/supplier.rb
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
require 'factory_girl'
|
||||||
|
|
||||||
|
FactoryGirl.define do
|
||||||
|
|
||||||
|
factory :supplier do
|
||||||
|
name { Faker::Company.name.truncate(30) }
|
||||||
|
phone { Faker::PhoneNumber.phone_number }
|
||||||
|
address { Faker::Address.street_address }
|
||||||
|
|
||||||
|
ignore do
|
||||||
|
article_count 0
|
||||||
|
end
|
||||||
|
|
||||||
|
after :create do |supplier, evaluator|
|
||||||
|
article_count = evaluator.article_count
|
||||||
|
article_count = rand(1..99) if article_count == true
|
||||||
|
FactoryGirl.create_list :article, article_count, supplier: supplier
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
36
spec/factories/user.rb
Normal file
36
spec/factories/user.rb
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
require 'factory_girl'
|
||||||
|
|
||||||
|
FactoryGirl.define do
|
||||||
|
|
||||||
|
factory :user do
|
||||||
|
sequence(:nick) { |n| "user#{n}"}
|
||||||
|
first_name { Faker::Name.first_name }
|
||||||
|
email { Faker::Internet.email }
|
||||||
|
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}"}
|
||||||
|
# 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
|
||||||
|
|
||||||
|
end
|
12
spec/i18n_spec.rb
Normal file
12
spec/i18n_spec.rb
Normal file
|
@ -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
|
55
spec/integration/balancing_spec.rb
Normal file
55
spec/integration/balancing_spec.rb
Normal file
|
@ -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
|
57
spec/integration/product_distribution_example_spec.rb
Normal file
57
spec/integration/product_distribution_example_spec.rb
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
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
|
||||||
|
# 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
|
||||||
|
visit new_group_order_path(:order_id => order.id)
|
||||||
|
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)
|
||||||
|
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)
|
||||||
|
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.finish!(admin)
|
||||||
|
oa.reload
|
||||||
|
# Endstand: insg. Bestellt wurden 6(1)
|
||||||
|
expect(oa.quantity).to eq(6)
|
||||||
|
expect(oa.tolerance).to eq(1)
|
||||||
|
# Gruppe a bekommt 3 einheiten.
|
||||||
|
goa_a = oa.group_order_articles.joins(:group_order).where(:group_orders => {:ordergroup_id => user_a.ordergroup.id}).first
|
||||||
|
expect(goa_a.result).to eq(3)
|
||||||
|
# gruppe b bekommt 2 einheiten.
|
||||||
|
goa_b = oa.group_order_articles.joins(:group_order).where(:group_orders => {:ordergroup_id => user_b.ordergroup.id}).first
|
||||||
|
expect(goa_b.result).to eq(2)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
21
spec/integration/session_spec.rb
Normal file
21
spec/integration/session_spec.rb
Normal file
|
@ -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
|
||||||
|
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
|
63
spec/integration/supplier_spec.rb
Normal file
63
spec/integration/supplier_spec.rb
Normal file
|
@ -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
|
47
spec/models/article_spec.rb
Normal file
47
spec/models/article_spec.rb
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
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
|
||||||
|
expect(article2).to be_invalid
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'computes the gross price correctly' do
|
||||||
|
article.deposit = 0
|
||||||
|
article.tax = 12
|
||||||
|
expect(article.gross_price).to eq((article.price * 1.12).round(2))
|
||||||
|
article.deposit = 1.20
|
||||||
|
expect(article.gross_price).to eq(((article.price + 1.20) * 1.12).round(2))
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'gross price >= net price' do
|
||||||
|
expect(article.gross_price).to be >= article.price
|
||||||
|
end
|
||||||
|
|
||||||
|
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
|
||||||
|
expect(supplier.deleted?).to be_false
|
||||||
|
supplier.mark_as_deleted
|
||||||
|
expect(supplier.deleted?).to be_true
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'keeps a price history' do
|
||||||
|
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.all.map(&:price)).to eq([article.price, oldprice])
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
48
spec/models/group_order_article_spec.rb
Normal file
48
spec/models/group_order_article_spec.rb
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
require 'spec_helper'
|
||||||
|
|
||||||
|
describe GroupOrderArticle do
|
||||||
|
let(:user) { FactoryGirl.create :user, groups: [FactoryGirl.create(:ordergroup)] }
|
||||||
|
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 }
|
||||||
|
|
||||||
|
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: 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)
|
||||||
|
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..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..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..99), rand(0..99))
|
||||||
|
goa.update_quantities(0, 0)
|
||||||
|
expect(goa.quantity).to eq(0)
|
||||||
|
expect(goa.tolerance).to eq(0)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
25
spec/models/group_order_spec.rb
Normal file
25
spec/models/group_order_spec.rb
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
require 'spec_helper'
|
||||||
|
|
||||||
|
describe GroupOrder do
|
||||||
|
let(:user) { FactoryGirl.create :user, groups: [FactoryGirl.create(:ordergroup)] }
|
||||||
|
let(:order) { FactoryGirl.create :order }
|
||||||
|
|
||||||
|
# the following two tests are currently disabled - https://github.com/foodcoops/foodsoft/issues/158
|
||||||
|
|
||||||
|
#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 }
|
||||||
|
|
||||||
|
it 'has zero price initially' do
|
||||||
|
expect(go.price).to eq(0)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
47
spec/models/order_spec.rb
Normal file
47
spec/models/order_spec.rb
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
require 'spec_helper'
|
||||||
|
|
||||||
|
describe Order do
|
||||||
|
|
||||||
|
it 'needs a supplier' do
|
||||||
|
expect(FactoryGirl.build(:order, supplier: nil)).to be_invalid
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'needs order articles' do
|
||||||
|
supplier = FactoryGirl.create :supplier, article_count: 0
|
||||||
|
expect(FactoryGirl.build(:order, supplier: supplier)).to be_invalid
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'can be created' do
|
||||||
|
expect(FactoryGirl.build(:order, article_count: 1)).to be_valid
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'with articles' do
|
||||||
|
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
|
||||||
|
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| expect(oa).to be_valid }
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'can be finished' do
|
||||||
|
# TODO randomise user
|
||||||
|
order.finish!(User.first)
|
||||||
|
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)
|
||||||
|
expect(order).to_not be_open
|
||||||
|
expect(order).to be_closed
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
16
spec/models/supplier_spec.rb
Normal file
16
spec/models/supplier_spec.rb
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
require 'spec_helper'
|
||||||
|
|
||||||
|
describe Supplier do
|
||||||
|
let(:supplier) { FactoryGirl.create :supplier }
|
||||||
|
|
||||||
|
it 'has a unique name' do
|
||||||
|
supplier2 = FactoryGirl.build :supplier, name: supplier.name
|
||||||
|
expect(supplier2).to be_invalid
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'has valid articles' do
|
||||||
|
supplier = FactoryGirl.create :supplier, article_count: true
|
||||||
|
supplier.articles.all.each {|a| expect(a).to be_valid }
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
59
spec/models/user_spec.rb
Normal file
59
spec/models/user_spec.rb
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
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'
|
||||||
|
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 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
|
||||||
|
expect(User.authenticate(user.nick, 'blahblah')).to be_true
|
||||||
|
end
|
||||||
|
it 'can not authenticate with incorrect password' do
|
||||||
|
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'
|
||||||
|
expect(user).to be_invalid
|
||||||
|
end
|
||||||
|
it 'can set a password with matching confirmation' do
|
||||||
|
user.password = 'abcdefghij'
|
||||||
|
user.password_confirmation = 'abcdefghij'
|
||||||
|
expect(user).to be_valid
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'has a unique nick' do
|
||||||
|
expect(FactoryGirl.build(:user, nick: user.nick, email: "x-#{user.email}")).to be_invalid
|
||||||
|
end
|
||||||
|
it 'has a unique email' do
|
||||||
|
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 expect(user.role_admin?).to be_true end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
67
spec/spec_helper.rb
Normal file
67
spec/spec_helper.rb
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
# 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'
|
||||||
|
|
||||||
|
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 }
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
# 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
|
||||||
|
# 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
|
||||||
|
# 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"
|
||||||
|
|
||||||
|
config.include SessionHelper
|
||||||
|
end
|
||||||
|
|
||||||
|
module Faker
|
||||||
|
class Unit
|
||||||
|
class << self
|
||||||
|
def unit
|
||||||
|
['kg', '1L', '100ml', 'piece', 'bunch', '500g'].sample
|
||||||
|
end
|
||||||
|
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
|
14
spec/support/coverage.rb
Normal file
14
spec/support/coverage.rb
Normal file
|
@ -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
|
17
spec/support/session_helper.rb
Normal file
17
spec/support/session_helper.rb
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
|
||||||
|
module SessionHelper
|
||||||
|
|
||||||
|
def login(user=nil, password=nil)
|
||||||
|
visit login_path
|
||||||
|
user = FactoryGirl.create :user if user.nil?
|
||||||
|
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
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
Loading…
Reference in a new issue