Merge branch 'master' into fix-closed-group_order-totals
Conflicts: db/schema.rb
This commit is contained in:
commit
ebb22ccb53
137 changed files with 4484 additions and 1507 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -16,3 +16,4 @@ doc/app/
|
|||
Capfile
|
||||
config/deploy.rb
|
||||
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
|
29
Gemfile
29
Gemfile
|
@ -17,6 +17,8 @@ group :assets do
|
|||
end
|
||||
|
||||
gem 'jquery-rails'
|
||||
gem 'select2-rails'
|
||||
gem 'bootstrap-datepicker-rails'
|
||||
|
||||
|
||||
gem 'mysql2'
|
||||
|
@ -35,7 +37,7 @@ gem 'simple-navigation-bootstrap'
|
|||
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 'acts_as_configurable', git: 'git://github.com/bwalding/acts_as_configurable.git'
|
||||
gem "rails-settings-cached", "0.2.4"
|
||||
gem 'resque'
|
||||
gem 'whenever', require: false # For defining cronjobs, see config/schedule.rb
|
||||
|
||||
|
@ -50,10 +52,7 @@ group :development do
|
|||
# Better error output
|
||||
gem 'better_errors'
|
||||
gem 'binding_of_caller'
|
||||
|
||||
# Re-enable rails benchmarker/profiler
|
||||
gem 'ruby-prof'
|
||||
gem 'test-unit'
|
||||
# gem "rails-i18n-debug"
|
||||
|
||||
# Get infos when not using proper eager loading
|
||||
gem 'bullet'
|
||||
|
@ -68,3 +67,23 @@ group :development do
|
|||
# Avoid having content-length warnings
|
||||
gem 'thin'
|
||||
end
|
||||
|
||||
group :development, :test do
|
||||
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
|
||||
|
|
89
Gemfile.lock
89
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
|
||||
|
@ -56,6 +49,8 @@ GEM
|
|||
coderay (>= 1.0.0)
|
||||
erubis (>= 2.7.0)
|
||||
binding_of_caller (0.6.8)
|
||||
bootstrap-datepicker-rails (1.1.1.1)
|
||||
railties (>= 3.0)
|
||||
builder (3.0.4)
|
||||
bullet (4.3.0)
|
||||
uniform_notifier
|
||||
|
@ -67,6 +62,14 @@ GEM
|
|||
net-ssh-gateway (>= 1.1.0)
|
||||
capistrano-ext (1.2.1)
|
||||
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)
|
||||
client_side_validations (3.1.4)
|
||||
coderay (1.0.8)
|
||||
|
@ -79,6 +82,8 @@ 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)
|
||||
exception_notification (2.6.1)
|
||||
|
@ -86,6 +91,14 @@ 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)
|
||||
faker (1.1.2)
|
||||
i18n (~> 0.5)
|
||||
ffi (1.9.0)
|
||||
haml (3.1.7)
|
||||
haml-rails (0.3.5)
|
||||
actionpack (>= 3.1, < 4.1)
|
||||
|
@ -95,11 +108,15 @@ GEM
|
|||
has_scope (0.5.1)
|
||||
hashery (2.0.1)
|
||||
highline (1.6.19)
|
||||
hike (1.2.1)
|
||||
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)
|
||||
|
@ -133,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.3)
|
||||
multi_json (1.7.9)
|
||||
mysql2 (0.3.11)
|
||||
net-scp (1.1.1)
|
||||
net-ssh (>= 2.6.5)
|
||||
|
@ -143,6 +161,8 @@ GEM
|
|||
net-ssh (2.6.7)
|
||||
net-ssh-gateway (1.2.0)
|
||||
net-ssh (>= 2.6.5)
|
||||
nokogiri (1.6.0)
|
||||
mini_portile (~> 0.5.0)
|
||||
pdf-reader (1.2.0)
|
||||
Ascii85 (~> 1.0.0)
|
||||
hashery (~> 2.0)
|
||||
|
@ -172,6 +192,8 @@ GEM
|
|||
activesupport (= 3.2.13)
|
||||
bundler (~> 1.0)
|
||||
railties (= 3.2.13)
|
||||
rails-settings-cached (0.2.4)
|
||||
rails (>= 3.0.0)
|
||||
railties (3.2.13)
|
||||
actionpack (= 3.2.13)
|
||||
activesupport (= 3.2.13)
|
||||
|
@ -183,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)
|
||||
|
@ -193,20 +215,44 @@ 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-prof (0.13.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)
|
||||
select2-rails (3.4.2)
|
||||
sass-rails
|
||||
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)
|
||||
activesupport (>= 2.3.2)
|
||||
simple-navigation-bootstrap (0.0.4)
|
||||
simple-navigation (>= 3.7.0)
|
||||
simple_form (2.0.3)
|
||||
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)
|
||||
|
@ -220,7 +266,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)
|
||||
|
@ -245,30 +290,38 @@ 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 (2.0.0)
|
||||
nokogiri (~> 1.3)
|
||||
|
||||
PLATFORMS
|
||||
ruby
|
||||
|
||||
DEPENDENCIES
|
||||
acts_as_configurable!
|
||||
acts_as_tree
|
||||
acts_as_versioned!
|
||||
better_errors
|
||||
binding_of_caller
|
||||
bootstrap-datepicker-rails
|
||||
bullet
|
||||
capistrano (= 2.13.5)
|
||||
capistrano-ext
|
||||
capybara (~> 2.1.0)
|
||||
client_side_validations
|
||||
coffee-rails (~> 3.2.1)
|
||||
daemons
|
||||
database_cleaner
|
||||
exception_notification
|
||||
factory_girl_rails (~> 4.0)
|
||||
faker
|
||||
haml-rails
|
||||
i18n-spec
|
||||
inherited_resources
|
||||
jquery-rails
|
||||
kaminari
|
||||
|
@ -279,14 +332,20 @@ DEPENDENCIES
|
|||
prawn
|
||||
quiet_assets
|
||||
rails (~> 3.2.9)
|
||||
rails-settings-cached (= 0.2.4)
|
||||
resque
|
||||
rspec-core
|
||||
rspec-expectations
|
||||
rspec-rails
|
||||
ruby-prof
|
||||
sass-rails (~> 3.2.3)
|
||||
select2-rails
|
||||
selenium-webdriver (~> 2.35.1)
|
||||
simple-navigation
|
||||
simple-navigation-bootstrap
|
||||
simple_form
|
||||
simplecov
|
||||
sqlite3
|
||||
test-unit
|
||||
therubyracer
|
||||
thin
|
||||
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
|
||||
=========
|
||||
[![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)
|
||||
|
||||
|
|
|
@ -1,14 +1,17 @@
|
|||
//= require jquery
|
||||
//= require jquery-ui
|
||||
//= require jquery_ujs
|
||||
//= require select2
|
||||
//= require twitter/bootstrap
|
||||
//= require jquery.tokeninput
|
||||
//= require bootstrap-datepicker
|
||||
//= require bootstrap-datepicker.de
|
||||
//= require bootstrap-datepicker/core
|
||||
//= require bootstrap-datepicker/locales/bootstrap-datepicker.de
|
||||
//= require bootstrap-datepicker/locales/bootstrap-datepicker.nl
|
||||
//= require jquery.observe_field
|
||||
//= require rails.validations
|
||||
//= require_self
|
||||
//= require ordering
|
||||
//= require stupidtable
|
||||
|
||||
// allow touch devices to work on click events
|
||||
// http://stackoverflow.com/a/16221066
|
||||
|
@ -112,9 +115,16 @@ $(function() {
|
|||
});
|
||||
|
||||
// Use bootstrap datepicker for dateinput
|
||||
$('.datepicker').datepicker({format: 'yyyy-mm-dd', weekStart: 1, language: 'de'});
|
||||
$('.datepicker').datepicker({format: 'yyyy-mm-dd', language: I18n.locale});
|
||||
|
||||
// See stupidtable.js for initialization of local table sorting
|
||||
});
|
||||
|
||||
// retrigger last local table sorting
|
||||
function updateSort(table) {
|
||||
$('.sorting-asc, .sorting-desc', table).toggleClass('.sorting-asc .sorting-desc')
|
||||
.removeData('sort-dir').trigger('click'); // CAUTION: removing data field of plugin
|
||||
}
|
||||
|
||||
// gives the row an yellow background
|
||||
function highlightRow(checkbox) {
|
||||
|
|
|
@ -10,6 +10,7 @@ var groupBalance = 0; // available group money
|
|||
var currencySeparator = "."; // default decimal separator
|
||||
var currencyPrecision = 2; // default digits behind comma
|
||||
var currencyUnit = "€"; // default currency
|
||||
var minimumBalance = 0; // minimum group balance for the order to be succesful
|
||||
var toleranceIsCostly = true; // default tolerance behaviour
|
||||
var isStockit = false; // Wheter the order is from stock oder normal supplier
|
||||
|
||||
|
@ -40,6 +41,10 @@ function setGroupBalance(amount) {
|
|||
groupBalance = amount;
|
||||
}
|
||||
|
||||
function setMinimumBalance(amount) {
|
||||
minimumBalance = amount;
|
||||
}
|
||||
|
||||
function addData(orderArticleId, itemPrice, itemUnit, itemSubtotal, itemQuantityOthers, itemToleranceOthers, allocated, available) {
|
||||
var i = orderArticleId;
|
||||
price[i] = itemPrice;
|
||||
|
@ -159,7 +164,7 @@ function updateBalance() {
|
|||
$('#total_balance').val(asMoney(balance));
|
||||
// determine bgcolor and submit button state according to balance
|
||||
var bgcolor = '';
|
||||
if (balance < 0) {
|
||||
if (balance < minimumBalance) {
|
||||
bgcolor = '#FF0000';
|
||||
$('#submit_button').attr('disabled', 'disabled')
|
||||
} else {
|
||||
|
|
186
app/assets/javascripts/stupidtable.js
Normal file
186
app/assets/javascripts/stupidtable.js
Normal file
|
@ -0,0 +1,186 @@
|
|||
// Stupid jQuery table plugin.
|
||||
|
||||
// Call on a table
|
||||
// sortFns: Sort functions for your datatypes.
|
||||
(function($) {
|
||||
|
||||
$.fn.stupidtable = function(sortFns) {
|
||||
return this.each(function() {
|
||||
var $table = $(this);
|
||||
sortFns = sortFns || {};
|
||||
|
||||
// ==================================================== //
|
||||
// Utility functions //
|
||||
// ==================================================== //
|
||||
|
||||
// Merge sort functions with some default sort functions.
|
||||
sortFns = $.extend({}, {
|
||||
"int": function(a, b) {
|
||||
return parseInt(a, 10) - parseInt(b, 10);
|
||||
},
|
||||
"float": function(a, b) {
|
||||
return parseFloat(a) - parseFloat(b);
|
||||
},
|
||||
"string": function(a, b) {
|
||||
if (a < b) return -1;
|
||||
if (a > b) return +1;
|
||||
return 0;
|
||||
},
|
||||
"string-ins": function(a, b) {
|
||||
a = a.toLowerCase();
|
||||
b = b.toLowerCase();
|
||||
if (a < b) return -1;
|
||||
if (a > b) return +1;
|
||||
return 0;
|
||||
}
|
||||
}, sortFns);
|
||||
|
||||
// Return the resulting indexes of a sort so we can apply
|
||||
// this result elsewhere. This returns an array of index numbers.
|
||||
// return[0] = x means "arr's 0th element is now at x"
|
||||
var sort_map = function(arr, sort_function, reverse_column) {
|
||||
var map = [];
|
||||
var index = 0;
|
||||
if (reverse_column) {
|
||||
for (var i = arr.length-1; i >= 0; i--) {
|
||||
map.push(i);
|
||||
}
|
||||
}
|
||||
else {
|
||||
var sorted = arr.slice(0).sort(sort_function);
|
||||
for (var i=0; i<arr.length; i++) {
|
||||
index = $.inArray(arr[i], sorted);
|
||||
|
||||
// If this index is already in the map, look for the next index.
|
||||
// This handles the case of duplicate entries.
|
||||
while ($.inArray(index, map) != -1) {
|
||||
index++;
|
||||
}
|
||||
map.push(index);
|
||||
}
|
||||
}
|
||||
return map;
|
||||
};
|
||||
|
||||
// Apply a sort map to the array.
|
||||
var apply_sort_map = function(arr, map) {
|
||||
var clone = arr.slice(0),
|
||||
newIndex = 0;
|
||||
for (var i=0; i<map.length; i++) {
|
||||
newIndex = map[i];
|
||||
clone[newIndex] = arr[i];
|
||||
}
|
||||
return clone;
|
||||
};
|
||||
|
||||
// ==================================================== //
|
||||
// Begin execution! //
|
||||
// ==================================================== //
|
||||
|
||||
// Do sorting when THs are clicked
|
||||
$table.on("click", "th", function() {
|
||||
var trs = $table.children("tbody").children("tr");
|
||||
var $this = $(this);
|
||||
var th_index = 0;
|
||||
var dir = $.fn.stupidtable.dir;
|
||||
|
||||
$table.find("th").slice(0, $this.index()).each(function() {
|
||||
var cols = $(this).attr("colspan") || 1;
|
||||
th_index += parseInt(cols,10);
|
||||
});
|
||||
|
||||
// Determine (and/or reverse) sorting direction, default `asc`
|
||||
var sort_dir = $this.data("sort-dir") === dir.ASC ? dir.DESC : dir.ASC;
|
||||
|
||||
// Choose appropriate sorting function. If we're sorting descending, check
|
||||
// for a `data-sort-desc` attribute.
|
||||
if ( sort_dir == dir.DESC )
|
||||
var type = $this.data("sort-desc") || $this.data("sort") || null;
|
||||
else
|
||||
var type = $this.data("sort") || null;
|
||||
|
||||
// Prevent sorting if no type defined
|
||||
if (type === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Trigger `beforetablesort` event that calling scripts can hook into;
|
||||
// pass parameters for sorted column index and sorting direction
|
||||
$table.trigger("beforetablesort", {column: th_index, direction: sort_dir});
|
||||
// More reliable method of forcing a redraw
|
||||
$table.css("display");
|
||||
|
||||
// Run sorting asynchronously on a timout to force browser redraw after
|
||||
// `beforetablesort` callback. Also avoids locking up the browser too much.
|
||||
setTimeout(function() {
|
||||
// Gather the elements for this column
|
||||
var column = [];
|
||||
var sortMethod = sortFns[type];
|
||||
|
||||
// Push either the value of the `data-order-by` attribute if specified
|
||||
// or just the text() value in this column to column[] for comparison.
|
||||
trs.each(function(index,tr) {
|
||||
var $e = $(tr).children().eq(th_index);
|
||||
var sort_val = $e.data("sort-value");
|
||||
var order_by = typeof(sort_val) !== "undefined" ? sort_val : $e.text();
|
||||
column.push(order_by);
|
||||
});
|
||||
|
||||
// Create the sort map. This column having a sort-dir implies it was
|
||||
// the last column sorted. As long as no data-sort-desc is specified,
|
||||
// we're free to just reverse the column.
|
||||
var reverse_column = !!$this.data("sort-dir") && !$this.data("sort-desc");
|
||||
var theMap = sort_map(column, sortMethod, reverse_column);
|
||||
|
||||
// Reset siblings
|
||||
$table.find("th").data("sort-dir", null).removeClass("sorting-desc sorting-asc");
|
||||
$this.data("sort-dir", sort_dir).addClass("sorting-"+sort_dir);
|
||||
|
||||
// Replace the content of tbody with the sortedTRs. Strangely (and
|
||||
// conveniently!) enough, .append accomplishes this for us.
|
||||
var sortedTRs = $(apply_sort_map(trs, theMap));
|
||||
$table.children("tbody").append(sortedTRs);
|
||||
|
||||
// Trigger `aftertablesort` event. Similar to `beforetablesort`
|
||||
$table.trigger("aftertablesort", {column: th_index, direction: sort_dir});
|
||||
// More reliable method of forcing a redraw
|
||||
$table.css("display");
|
||||
}, 10);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
// Enum containing sorting directions
|
||||
$.fn.stupidtable.dir = {ASC: "asc", DESC: "desc"};
|
||||
|
||||
})(jQuery);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// own additions for automatic initialization of table sorting
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
$(function() {
|
||||
var stupidtables = $('table.stupidtable');
|
||||
|
||||
if(stupidtables.length) {
|
||||
// Add pseudo links just for matching foodsoft style
|
||||
$('th[data-sort]', stupidtables).wrapInner('<a href="#" class="stupidlink"></a>');
|
||||
$('.stupidlink', stupidtables).on('click', function(e) {e.preventDefault();});
|
||||
|
||||
// Init stupidtable sorting
|
||||
stupidtables.stupidtable();
|
||||
|
||||
// Update class of sort link after sort to match foodsoft style
|
||||
stupidtables.on('aftertablesort', function(e, data) {
|
||||
// Ignore data and use the updated classes in DOM
|
||||
var stupidthead = $('thead', this);
|
||||
$('a.stupidlink', stupidthead).removeClass('sortup sortdown');
|
||||
$('th.sorting-asc a.stupidlink', stupidthead).addClass('sortup');
|
||||
$('th.sorting-desc a.stupidlink', stupidthead).addClass('sortdown');
|
||||
});
|
||||
|
||||
// Sort tables with a default sort
|
||||
$('.default-sort', stupidtables).trigger('click');
|
||||
}
|
||||
});
|
|
@ -1,4 +1,6 @@
|
|||
/*
|
||||
*= require bootstrap_and_overrides
|
||||
*= require select2
|
||||
*= require token-input-bootstrappy
|
||||
*= require bootstrap-datepicker
|
||||
*/
|
|
@ -31,10 +31,6 @@ body {
|
|||
// Example:
|
||||
// @linkColor: #ff0000;
|
||||
|
||||
|
||||
// Bootstrap datepicker
|
||||
@import "datepicker";
|
||||
|
||||
// Custom styles
|
||||
|
||||
// Fix empty dd tags in horizontal dl, see https://github.com/twitter/bootstrap/issues/4062
|
||||
|
@ -42,6 +38,22 @@ body {
|
|||
dd { .clearfix(); }
|
||||
}
|
||||
|
||||
// Do not use additional margin for input in table
|
||||
.form-horizontal .control-group.control-group-intable,
|
||||
.form-horizontal .controls.controls-intable {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
// Light tooltips without empty space below tables
|
||||
.tooltip-inner {
|
||||
color: #000;
|
||||
background-color: rgb(245,245,245);
|
||||
border: 1px solid #ccc;
|
||||
}
|
||||
.tooltip-inner .table {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
@mainRedColor: #ED0606;
|
||||
|
||||
.logo {
|
||||
|
@ -208,3 +220,21 @@ tr.unavailable {
|
|||
dt { width: 160px; }
|
||||
dd { margin-left: 170px; }
|
||||
}
|
||||
|
||||
.settings {
|
||||
.settings-group {
|
||||
margin-bottom: 10px;
|
||||
.control-label {
|
||||
margin: 5px 0 0 0;
|
||||
}
|
||||
}
|
||||
.control-group {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
.control-group.h_wrapper {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
.control-group.select {
|
||||
margin-bottom: 15px
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,13 @@
|
|||
# encoding: utf-8
|
||||
class ApplicationController < ActionController::Base
|
||||
include Foodsoft::ControllerExtensions::Locale
|
||||
helper_method :available_locales
|
||||
|
||||
protect_from_forgery
|
||||
before_filter :select_language, :select_foodcoop, :authenticate, :store_controller, :items_per_page, :set_redirect_to
|
||||
before_filter :select_foodcoop, :authenticate, :store_controller, :items_per_page, :set_redirect_to
|
||||
after_filter :remove_controller
|
||||
|
||||
|
||||
# Returns the controller handling the current request.
|
||||
def self.current
|
||||
Thread.current[:application_controller]
|
||||
|
@ -142,8 +145,4 @@ class ApplicationController < ActionController::Base
|
|||
{foodcoop: FoodsoftConfig.scope}
|
||||
end
|
||||
|
||||
# Used to prevent accidently switching to :en in production mode.
|
||||
def select_language
|
||||
I18n.locale = :de
|
||||
end
|
||||
end
|
||||
|
|
|
@ -32,7 +32,7 @@ class ArticlesController < ApplicationController
|
|||
end
|
||||
|
||||
def new
|
||||
@article = @supplier.articles.build(:tax => 7.0)
|
||||
@article = @supplier.articles.build(:tax => FoodsoftConfig[:tax_default])
|
||||
render :layout => false
|
||||
end
|
||||
|
||||
|
@ -145,19 +145,22 @@ class ArticlesController < ApplicationController
|
|||
begin
|
||||
@articles = Array.new
|
||||
articles, outlisted_articles = FoodsoftFile::parse(params[:articles]["file"])
|
||||
no_category = ArticleCategory.new
|
||||
articles.each do |row|
|
||||
# fallback to Others category
|
||||
category = (ArticleCategory.find_by_name(row[:category]) or no_category)
|
||||
# creates a new article and price
|
||||
article = Article.new( :name => row[:name],
|
||||
:note => row[:note],
|
||||
:manufacturer => row[:manufacturer],
|
||||
:origin => row[:origin],
|
||||
:unit => row[:unit],
|
||||
:article_category => ArticleCategory.find_by_name(row[:category]),
|
||||
:article_category => category,
|
||||
:price => row[:price],
|
||||
:unit_quantity => row[:unit_quantity],
|
||||
:order_number => row[:number],
|
||||
:deposit => row[:deposit],
|
||||
:tax => row[:tax])
|
||||
:tax => (row[:tax] or FoodsoftConfig[:tax_default]))
|
||||
# stop parsing, when an article isn't valid
|
||||
unless article.valid?
|
||||
raise I18n.t('articles.controller.error_parse', :msg => article.errors.full_messages.join(", "), :line => (articles.index(row) + 2).to_s)
|
||||
|
@ -206,7 +209,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
|
||||
|
||||
|
|
|
@ -5,43 +5,25 @@ class DeliveriesController < ApplicationController
|
|||
|
||||
def index
|
||||
@deliveries = @supplier.deliveries.all :order => 'delivered_on DESC'
|
||||
|
||||
respond_to do |format|
|
||||
format.html # index.html.erb
|
||||
format.xml { render :xml => @deliveries }
|
||||
end
|
||||
end
|
||||
|
||||
def show
|
||||
@delivery = Delivery.find(params[:id])
|
||||
|
||||
respond_to do |format|
|
||||
format.html # show.html.erb
|
||||
format.xml { render :xml => @delivery }
|
||||
end
|
||||
end
|
||||
|
||||
def new
|
||||
@delivery = @supplier.deliveries.build
|
||||
|
||||
respond_to do |format|
|
||||
format.html # new.html.erb
|
||||
format.xml { render :xml => @delivery }
|
||||
end
|
||||
@delivery.delivered_on = Date.today #TODO: move to model/database
|
||||
end
|
||||
|
||||
def create
|
||||
@delivery = Delivery.new(params[:delivery])
|
||||
|
||||
respond_to do |format|
|
||||
if @delivery.save
|
||||
flash[:notice] = I18n.t('deliveries.create.notice')
|
||||
format.html { redirect_to([@supplier,@delivery]) }
|
||||
format.xml { render :xml => @delivery, :status => :created, :location => @delivery }
|
||||
redirect_to [@supplier, @delivery]
|
||||
else
|
||||
format.html { render :action => "new" }
|
||||
format.xml { render :xml => @delivery.errors, :status => :unprocessable_entity }
|
||||
end
|
||||
render :action => "new"
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -52,15 +34,11 @@ class DeliveriesController < ApplicationController
|
|||
def update
|
||||
@delivery = Delivery.find(params[:id])
|
||||
|
||||
respond_to do |format|
|
||||
if @delivery.update_attributes(params[:delivery])
|
||||
flash[:notice] = I18n.t('deliveries.update.notice')
|
||||
format.html { redirect_to([@supplier,@delivery]) }
|
||||
format.xml { head :ok }
|
||||
redirect_to [@supplier,@delivery]
|
||||
else
|
||||
format.html { render :action => "edit" }
|
||||
format.xml { render :xml => @delivery.errors, :status => :unprocessable_entity }
|
||||
end
|
||||
render :action => "edit"
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -69,40 +47,60 @@ class DeliveriesController < ApplicationController
|
|||
@delivery.destroy
|
||||
|
||||
flash[:notice] = I18n.t('deliveries.destroy.notice')
|
||||
respond_to do |format|
|
||||
format.html { redirect_to(supplier_deliveries_url(@supplier)) }
|
||||
format.xml { head :ok }
|
||||
end
|
||||
redirect_to supplier_deliveries_url(@supplier)
|
||||
end
|
||||
|
||||
def add_stock_article
|
||||
article = @supplier.stock_articles.build(params[:stock_article])
|
||||
render :update do |page|
|
||||
if article.save
|
||||
logger.debug "new StockArticle: #{article.id}"
|
||||
page.insert_html :bottom, 'stock_changes', :partial => 'stock_change',
|
||||
:locals => {:stock_change => article.stock_changes.build, :supplier => @supplier}
|
||||
# three possibilites to fill a new_stock_article form
|
||||
# (1) start from blank or use params
|
||||
def new_stock_article
|
||||
@stock_article = @supplier.stock_articles.build(params[:stock_article])
|
||||
|
||||
page.replace_html 'new_stock_article', :partial => 'stock_article_form',
|
||||
:locals => {:stock_article => @supplier.stock_articles.build}
|
||||
render :layout => false
|
||||
end
|
||||
|
||||
# (2) StockArticle as template
|
||||
def copy_stock_article
|
||||
@stock_article = StockArticle.find(params[:old_stock_article_id]).dup
|
||||
|
||||
render :layout => false
|
||||
end
|
||||
|
||||
# (3) non-stock Article as template
|
||||
def derive_stock_article
|
||||
@stock_article = Article.find(params[:old_article_id]).becomes(StockArticle).dup
|
||||
|
||||
render :layout => false
|
||||
end
|
||||
|
||||
def create_stock_article
|
||||
@stock_article = StockArticle.new(params[:stock_article])
|
||||
|
||||
if @stock_article.valid? and @stock_article.save
|
||||
render :layout => false
|
||||
else
|
||||
page.replace_html 'new_stock_article', :partial => 'stock_article_form',
|
||||
:locals => {:stock_article => article}
|
||||
render :action => 'new_stock_article', :layout => false
|
||||
end
|
||||
end
|
||||
|
||||
def edit_stock_article
|
||||
@stock_article = StockArticle.find(params[:stock_article_id])
|
||||
render :layout => false
|
||||
end
|
||||
|
||||
def update_stock_article
|
||||
@stock_article = StockArticle.find(params[:stock_article][:id])
|
||||
|
||||
if @stock_article.update_attributes(params[:stock_article])
|
||||
render :layout => false
|
||||
else
|
||||
render :action => 'edit_stock_article', :layout => false
|
||||
end
|
||||
end
|
||||
|
||||
def add_stock_change
|
||||
@stock_change = StockChange.new
|
||||
@stock_change.stock_article = StockArticle.find(params[:stock_article_id])
|
||||
render :layout => false
|
||||
end
|
||||
|
||||
def fill_new_stock_article_form
|
||||
article = Article.find(params[:article_id])
|
||||
@supplier = article.supplier
|
||||
stock_article = @supplier.stock_articles.build(
|
||||
article.attributes.reject { |attr| attr == ('id' || 'type')}
|
||||
)
|
||||
|
||||
render :partial => 'stock_article_form', :locals => {:stock_article => stock_article}
|
||||
end
|
||||
end
|
||||
|
|
|
@ -65,7 +65,13 @@ class Finance::GroupOrderArticlesController < ApplicationController
|
|||
|
||||
def destroy
|
||||
group_order_article = GroupOrderArticle.find(params[:id])
|
||||
# only destroy if quantity and tolerance was zero already, so that we don't
|
||||
# lose what the user ordered, if any
|
||||
if group_order_article.quantity > 0 or group_order_article.tolerance >0
|
||||
group_order_article.update_attribute(:result, 0)
|
||||
else
|
||||
group_order_article.destroy
|
||||
end
|
||||
update_summaries(group_order_article)
|
||||
@order_article = group_order_article.order_article
|
||||
|
||||
|
|
|
@ -42,6 +42,14 @@ class Finance::OrderArticlesController < ApplicationController
|
|||
|
||||
def destroy
|
||||
@order_article = OrderArticle.find(params[:id])
|
||||
# only destroy if there are no associated GroupOrders; if we would, the requested
|
||||
# quantity and tolerance would be gone. Instead of destroying, we set all result
|
||||
# quantities to zero.
|
||||
if @order_article.group_order_articles.count == 0
|
||||
@order_article.destroy
|
||||
else
|
||||
@order_article.group_order_articles.each { |goa| goa.update_attribute(:result, 0) }
|
||||
@order_article.update_results!
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -16,6 +16,7 @@ class HomeController < ApplicationController
|
|||
|
||||
def update_profile
|
||||
if @current_user.update_attributes(params[:user])
|
||||
session[:locale] = @current_user.locale
|
||||
redirect_to my_profile_url, notice: I18n.t('home.changes_saved')
|
||||
else
|
||||
render :profile
|
||||
|
|
|
@ -58,6 +58,7 @@ class LoginController < ApplicationController
|
|||
if @user.save
|
||||
Membership.new(:user => @user, :group => @invite.group).save!
|
||||
@invite.destroy
|
||||
session[:locale] = @user.locale
|
||||
redirect_to login_url, notice: I18n.t('login.controller.accept_invitation.notice')
|
||||
end
|
||||
end
|
||||
|
|
|
@ -11,6 +11,8 @@ class SessionsController < ApplicationController
|
|||
if user
|
||||
session[:user_id] = user.id
|
||||
session[:scope] = FoodsoftConfig.scope # Save scope in session to not allow switching between foodcoops with one account
|
||||
session[:locale] = user.locale
|
||||
|
||||
if session[:return_to].present?
|
||||
redirect_to_url = session[:return_to]
|
||||
session[:return_to] = nil
|
||||
|
|
|
@ -55,4 +55,9 @@ class StockitController < ApplicationController
|
|||
|
||||
render :partial => 'form', :locals => {:stock_article => stock_article}
|
||||
end
|
||||
|
||||
def history
|
||||
@stock_article = StockArticle.undeleted.find(params[:stock_article_id])
|
||||
@stock_changes = @stock_article.stock_changes.order('stock_changes.created_at DESC').each {|s| s.readonly!}
|
||||
end
|
||||
end
|
||||
|
|
|
@ -18,7 +18,7 @@ class SuppliersController < ApplicationController
|
|||
def new
|
||||
if params[:shared_supplier_id]
|
||||
shared_supplier = SharedSupplier.find(params[:shared_supplier_id])
|
||||
@supplier = shared_supplier.build_supplier(shared_supplier.autofill_attributes)
|
||||
@supplier = shared_supplier.suppliers.new(shared_supplier.autofill_attributes)
|
||||
else
|
||||
@supplier = Supplier.new
|
||||
end
|
||||
|
|
|
@ -18,6 +18,9 @@ class TasksController < ApplicationController
|
|||
|
||||
def create
|
||||
@task = Task.new(params[:task])
|
||||
if params[:periodic]
|
||||
@task.periodic_task_group = PeriodicTaskGroup.new
|
||||
end
|
||||
if @task.save
|
||||
redirect_to tasks_url, :notice => I18n.t('tasks.create.notice')
|
||||
else
|
||||
|
@ -32,13 +35,20 @@ class TasksController < ApplicationController
|
|||
def edit
|
||||
@task = Task.find(params[:id])
|
||||
@task.current_user_id = current_user.id
|
||||
if @task.periodic?
|
||||
flash.now[:alert] = I18n.t('tasks.edit.warning_periodic').html_safe
|
||||
end
|
||||
end
|
||||
|
||||
def update
|
||||
@task = Task.find(params[:id])
|
||||
was_periodic = @task.periodic?
|
||||
@task.attributes=(params[:task])
|
||||
if @task.errors.empty? && @task.save
|
||||
flash[:notice] = I18n.t('tasks.update.notice')
|
||||
if was_periodic and not @task.periodic?
|
||||
flash[:notice] = I18n.t('tasks.update.notice_converted')
|
||||
end
|
||||
if @task.workgroup
|
||||
redirect_to workgroup_tasks_url(workgroup_id: @task.workgroup_id)
|
||||
else
|
||||
|
@ -53,7 +63,12 @@ class TasksController < ApplicationController
|
|||
task = Task.find(params[:id])
|
||||
# Save user_ids to update apple statistics after destroy
|
||||
user_ids = task.user_ids
|
||||
if params[:periodic]
|
||||
task.periodic_task_group.exclude_tasks_before(task)
|
||||
task.periodic_task_group.destroy
|
||||
else
|
||||
task.destroy
|
||||
end
|
||||
task.update_ordergroup_stats(user_ids)
|
||||
|
||||
redirect_to tasks_url, :notice => I18n.t('tasks.destroy.notice')
|
||||
|
|
|
@ -12,20 +12,29 @@ class OrderByArticles < OrderPdf
|
|||
|
||||
def body
|
||||
@order.order_articles.ordered.each do |order_article|
|
||||
text "#{order_article.article.name} (#{order_article.article.unit} | #{order_article.price.unit_quantity.to_s} | #{number_with_precision(order_article.price.fc_price, precision: 2)})",
|
||||
style: :bold, size: 10
|
||||
rows = []
|
||||
rows << I18n.t('documents.order_by_articles.rows')
|
||||
for goa in order_article.group_order_articles
|
||||
dimrows = []
|
||||
for goa in order_article.group_order_articles.ordered
|
||||
rows << [goa.group_order.ordergroup.name,
|
||||
"#{goa.quantity} + #{goa.tolerance}",
|
||||
goa.result,
|
||||
number_with_precision(order_article.price.fc_price * goa.result, precision: 2)]
|
||||
dimrows << rows.length if goa.result == 0
|
||||
end
|
||||
next if rows.length == 0
|
||||
rows.unshift I18n.t('documents.order_by_articles.rows') # table header
|
||||
|
||||
table rows, column_widths: [200,40,40], cell_style: {size: 8, overflow: :shrink_to_fit} do |table|
|
||||
table.columns(1..2).align = :right
|
||||
text "#{order_article.article.name} (#{order_article.article.unit} | #{order_article.price.unit_quantity.to_s} | #{number_with_precision(order_article.price.fc_price, precision: 2)})",
|
||||
style: :bold, size: 10
|
||||
table rows, cell_style: {size: 8, overflow: :shrink_to_fit} do |table|
|
||||
table.column(0).width = 200
|
||||
table.columns(1..3).align = :right
|
||||
table.column(2).font_style = :bold
|
||||
table.cells.border_width = 1
|
||||
table.cells.border_color = '666666'
|
||||
table.rows(0).border_bottom_width = 2
|
||||
# dim rows which were ordered but not received
|
||||
dimrows.each { |ri| table.row(ri).text_color = '999999' }
|
||||
end
|
||||
move_down 10
|
||||
end
|
||||
|
|
|
@ -12,12 +12,10 @@ class OrderByGroups < OrderPdf
|
|||
|
||||
def body
|
||||
# Start rendering
|
||||
@order.group_orders.each do |group_order|
|
||||
text group_order.ordergroup.name, size: 9, style: :bold
|
||||
|
||||
@order.group_orders.ordered.each do |group_order|
|
||||
total = 0
|
||||
rows = []
|
||||
rows << I18n.t('documents.order_by_groups.rows') # Table Header
|
||||
dimrows = []
|
||||
|
||||
group_order_articles = group_order.group_order_articles.ordered
|
||||
group_order_articles.each do |goa|
|
||||
|
@ -25,15 +23,20 @@ class OrderByGroups < OrderPdf
|
|||
sub_total = price * goa.result
|
||||
total += sub_total
|
||||
rows << [goa.order_article.article.name,
|
||||
"#{goa.quantity} + #{goa.tolerance}",
|
||||
goa.result,
|
||||
number_with_precision(price, precision: 2),
|
||||
goa.order_article.price.unit_quantity,
|
||||
goa.order_article.article.unit,
|
||||
number_with_precision(sub_total, precision: 2)]
|
||||
dimrows << rows.length if goa.result == 0
|
||||
end
|
||||
rows << [ I18n.t('documents.order_by_groups.sum'), nil, nil, nil, nil, number_with_precision(total, precision: 2)]
|
||||
next if rows.length == 0
|
||||
rows << [ I18n.t('documents.order_by_groups.sum'), nil, nil, nil, nil, nil, number_with_precision(total, precision: 2)]
|
||||
rows.unshift I18n.t('documents.order_by_groups.rows') # Table Header
|
||||
|
||||
table rows, column_widths: [250,50,50,50,50,50], cell_style: {size: 8, overflow: :shrink_to_fit} do |table|
|
||||
text group_order.ordergroup.name, size: 9, style: :bold
|
||||
table rows, width: 500, cell_style: {size: 8, overflow: :shrink_to_fit} do |table|
|
||||
# borders
|
||||
table.cells.borders = []
|
||||
table.row(0).borders = [:bottom]
|
||||
|
@ -41,8 +44,14 @@ class OrderByGroups < OrderPdf
|
|||
table.cells.border_width = 1
|
||||
table.cells.border_color = '666666'
|
||||
|
||||
table.columns(1..3).align = :right
|
||||
table.columns(5).align = :right
|
||||
table.column(0).width = 240
|
||||
table.column(2).font_style = :bold
|
||||
table.columns(1..4).align = :right
|
||||
table.column(6).align = :right
|
||||
table.column(6).font_style = :bold
|
||||
|
||||
# dim rows which were ordered but not received
|
||||
dimrows.each { |ri| table.row(ri).text_color = '999999' }
|
||||
end
|
||||
|
||||
move_down 15
|
||||
|
|
|
@ -20,20 +20,28 @@ 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
|
||||
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
|
||||
bounding_box [margin_box.left,margin_box.top-60], width: 200 do
|
||||
text @order.name
|
||||
move_down 5
|
||||
text @order.supplier.try(:address).to_s
|
||||
unless @order.supplier.try(:fax).blank?
|
||||
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
|
||||
|
||||
move_down 5
|
||||
|
@ -42,25 +50,37 @@ 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)}"
|
||||
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
|
||||
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,
|
||||
|
|
|
@ -159,4 +159,12 @@ module ApplicationHelper
|
|||
flash_messages.join("\n").html_safe
|
||||
end
|
||||
|
||||
# render base errors in a form after failed validation
|
||||
# http://railsapps.github.io/twitter-bootstrap-rails.html
|
||||
def base_errors resource
|
||||
return '' if (resource.errors.empty?) or (resource.errors[:base].empty?)
|
||||
messages = resource.errors[:base].map { |msg| content_tag(:li, msg) }.join
|
||||
render :partial => 'shared/base_errors', :locals => {:error_messages => messages}
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -10,8 +10,28 @@ module DeliveriesHelper
|
|||
end
|
||||
end
|
||||
|
||||
def stock_articles_for_select(supplier)
|
||||
supplier.stock_articles.undeleted.reorder('articles.name ASC').map {|a| ["#{a.name} (#{number_to_currency a.price}/#{a.unit})", a.id] }
|
||||
def articles_for_select2(supplier)
|
||||
supplier.articles.undeleted.reorder('articles.name ASC').map {|a| {:id => a.id, :text => "#{a.name} (#{number_to_currency a.price}/#{a.unit})"} }
|
||||
end
|
||||
|
||||
def stock_articles_for_table(supplier)
|
||||
supplier.stock_articles.undeleted.reorder('articles.name ASC')
|
||||
end
|
||||
|
||||
def stock_change_remove_link(stock_change_form)
|
||||
return link_to t('.remove_article'), "#", :class => 'remove_new_stock_change btn btn-small' if stock_change_form.object.new_record?
|
||||
output = stock_change_form.hidden_field :_destroy
|
||||
output += link_to t('.remove_article'), "#", :class => 'destroy_stock_change btn btn-small'
|
||||
return output.html_safe
|
||||
end
|
||||
|
||||
def stock_article_price_hint(stock_article)
|
||||
t('simple_form.hints.stock_article.edit_stock_article.price',
|
||||
:stock_article_copy_link => link_to(t('.copy_stock_article'),
|
||||
copy_stock_article_supplier_deliveries_path(@supplier, :old_stock_article_id => stock_article.id),
|
||||
:remote => true
|
||||
)
|
||||
)
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -4,7 +4,7 @@ module Finance::OrderArticlesHelper
|
|||
if @order.stockit?
|
||||
StockArticle.order('articles.name')
|
||||
else
|
||||
@order.supplier.articles.order('articles.name')
|
||||
@order.supplier.articles.undeleted.order('articles.name')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -4,4 +4,14 @@ module StockitHelper
|
|||
class_names << "unavailable" if article.quantity_available <= 0
|
||||
class_names.join(" ")
|
||||
end
|
||||
|
||||
def link_to_stock_change_reason(stock_change)
|
||||
if stock_change.delivery_id
|
||||
link_to t('.delivery'), supplier_delivery_path(stock_change.delivery.supplier, stock_change.delivery)
|
||||
elsif stock_change.order_id
|
||||
link_to t('.order'), order_path(stock_change.order)
|
||||
elsif stock_change.stock_taking_id
|
||||
link_to t('.stock_taking'), stock_taking_path(stock_change.stock_taking)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
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
|
|
@ -2,11 +2,15 @@ class Delivery < ActiveRecord::Base
|
|||
|
||||
belongs_to :supplier
|
||||
has_one :invoice
|
||||
has_many :stock_changes, :dependent => :destroy
|
||||
has_many :stock_changes,
|
||||
:dependent => :destroy,
|
||||
:include => 'stock_article',
|
||||
:order => 'articles.name ASC'
|
||||
|
||||
scope :recent, :order => 'created_at DESC', :limit => 10
|
||||
|
||||
validates_presence_of :supplier_id
|
||||
validates_presence_of :supplier_id, :delivered_on
|
||||
validate :stock_articles_must_be_unique
|
||||
|
||||
accepts_nested_attributes_for :stock_changes, :allow_destroy => :true
|
||||
|
||||
|
@ -16,6 +20,18 @@ class Delivery < ActiveRecord::Base
|
|||
end
|
||||
end
|
||||
|
||||
def includes_article?(article)
|
||||
self.stock_changes.map{|stock_change| stock_change.stock_article.id}.include? article.id
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def stock_articles_must_be_unique
|
||||
unless stock_changes.reject{|sc| sc.marked_for_destruction?}.map {|sc| sc.stock_article.id}.uniq!.nil?
|
||||
errors.add(:base, I18n.t('model.delivery.each_stock_article_must_be_unique'))
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
|
|
@ -17,6 +17,8 @@ class GroupOrder < ActiveRecord::Base
|
|||
scope :in_open_orders, joins(:order).merge(Order.open)
|
||||
scope :in_finished_orders, joins(:order).merge(Order.finished_not_closed)
|
||||
|
||||
scope :ordered, :include => :ordergroup, :order => 'groups.name'
|
||||
|
||||
# Generate some data for the javascript methods in ordering view
|
||||
def load_data
|
||||
data = {}
|
||||
|
|
|
@ -14,7 +14,7 @@ class GroupOrderArticle < ActiveRecord::Base
|
|||
validates_inclusion_of :tolerance, :in => 0..99
|
||||
validates_uniqueness_of :order_article_id, :scope => :group_order_id # just once an article per group order
|
||||
|
||||
scope :ordered, :conditions => 'result > 0'
|
||||
scope :ordered, :conditions => 'group_order_articles.result > 0 OR group_order_articles.quantity > 0 OR group_order_articles.tolerance > 0', :include => {:group_order => :ordergroup}, :order => 'groups.name'
|
||||
|
||||
localize_input_of :result
|
||||
|
||||
|
|
|
@ -108,10 +108,10 @@ class Ordergroup < Group
|
|||
|
||||
# Make sure, the name is uniq, add usefull message if uniq group is already deleted
|
||||
def uniqueness_of_name
|
||||
id = new_record? ? nil : self.id
|
||||
group = Ordergroup.where('groups.id != ? AND groups.name = ?', id, name).first
|
||||
if group.present?
|
||||
message = group.deleted? ? :taken_with_deleted : :taken
|
||||
group = Ordergroup.where('groups.name = ?', name)
|
||||
group = group.where('groups.id != ?', self.id) unless new_record?
|
||||
if group.exists?
|
||||
message = group.first.deleted? ? :taken_with_deleted : :taken
|
||||
errors.add :name, message
|
||||
end
|
||||
end
|
||||
|
|
29
app/models/periodic_task_group.rb
Normal file
29
app/models/periodic_task_group.rb
Normal file
|
@ -0,0 +1,29 @@
|
|||
class PeriodicTaskGroup < ActiveRecord::Base
|
||||
has_many :tasks, dependent: :destroy
|
||||
|
||||
PeriodDays = 7
|
||||
|
||||
def has_next_task?
|
||||
return false if tasks.empty?
|
||||
return false if tasks.first.due_date.nil?
|
||||
return true
|
||||
end
|
||||
|
||||
def create_next_task
|
||||
template_task = tasks.first
|
||||
self.next_task_date ||= template_task.due_date + PeriodDays
|
||||
|
||||
next_task = template_task.dup
|
||||
next_task.due_date = next_task_date
|
||||
next_task.save
|
||||
|
||||
self.next_task_date += PeriodDays
|
||||
self.save
|
||||
end
|
||||
|
||||
def exclude_tasks_before(task)
|
||||
tasks.where("due_date < '#{task.due_date}'").each do |t|
|
||||
t.update_attribute(:periodic_task_group, nil)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
||||
# These set of attributes are used to autofill attributes of new supplier,
|
||||
|
|
|
@ -18,6 +18,10 @@ class StockArticle < Article
|
|||
joins(:order).where("orders.state = 'open' OR orders.state = 'finished'").sum(:units_to_order)
|
||||
end
|
||||
|
||||
def quantity_history
|
||||
stock_changes.reorder('stock_changes.created_at ASC').map{|s| s.quantity}.cumulative_sum
|
||||
end
|
||||
|
||||
def self.stock_value
|
||||
available.collect { |a| a.quantity * a.gross_price }.sum
|
||||
end
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
class StockChange < ActiveRecord::Base
|
||||
belongs_to :delivery
|
||||
belongs_to :order
|
||||
belongs_to :stock_taking
|
||||
belongs_to :stock_article
|
||||
|
||||
validates_presence_of :stock_article_id, :quantity
|
||||
|
|
|
@ -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) }
|
||||
|
@ -82,10 +80,10 @@ class Supplier < ActiveRecord::Base
|
|||
|
||||
# Make sure, the name is uniq, add usefull message if uniq group is already deleted
|
||||
def uniqueness_of_name
|
||||
id = new_record? ? nil : self.id
|
||||
supplier = Supplier.where('suppliers.id != ? AND suppliers.name = ?', id, name).first
|
||||
if supplier.present?
|
||||
message = supplier.deleted? ? :taken_with_deleted : :taken
|
||||
supplier = Supplier.where('suppliers.name = ?', name)
|
||||
supplier = supplier.where('suppliers.id != ?', self.id) unless new_record?
|
||||
if supplier.exists?
|
||||
message = supplier.first.deleted? ? :taken_with_deleted : :taken
|
||||
errors.add :name, message
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
class Task < ActiveRecord::Base
|
||||
has_many :assignments, :dependent => :destroy
|
||||
has_many :users, :through => :assignments
|
||||
belongs_to :workgroup
|
||||
belongs_to :periodic_task_group
|
||||
|
||||
scope :non_group, where(workgroup_id: nil, done: false)
|
||||
scope :done, where(done: true)
|
||||
|
@ -16,7 +18,9 @@ class Task < ActiveRecord::Base
|
|||
validates :required_users, :presence => true
|
||||
validates_numericality_of :duration, :required_users, :only_integer => true, :greater_than => 0
|
||||
validates_length_of :description, maximum: 250
|
||||
validates :done, exclusion: { in: [true] }, if: :periodic?, on: :create
|
||||
|
||||
before_save :exclude_from_periodic_task_group, if: :changed?, unless: :new_record?
|
||||
after_save :update_ordergroup_stats
|
||||
|
||||
# Find all tasks, for which the current user should be responsible
|
||||
|
@ -46,6 +50,10 @@ class Task < ActiveRecord::Base
|
|||
end
|
||||
end
|
||||
|
||||
def periodic?
|
||||
not periodic_task_group.nil?
|
||||
end
|
||||
|
||||
def is_assigned?(user)
|
||||
self.assignments.detect {|ass| ass.user_id == user.id }
|
||||
end
|
||||
|
@ -100,5 +108,10 @@ class Task < ActiveRecord::Base
|
|||
def update_ordergroup_stats(user_ids = self.user_ids)
|
||||
Ordergroup.joins(:users).where(users: {id: user_ids}).each(&:update_stats!)
|
||||
end
|
||||
|
||||
def exclude_from_periodic_task_group
|
||||
self.periodic_task_group = nil
|
||||
true
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
require 'digest/sha1'
|
||||
# specific user rights through memberships (see Group)
|
||||
class User < ActiveRecord::Base
|
||||
include RailsSettings::Extend
|
||||
#TODO: acts_as_paraniod ??
|
||||
|
||||
has_many :memberships, :dependent => :destroy
|
||||
|
@ -19,7 +20,10 @@ class User < ActiveRecord::Base
|
|||
has_many :pages, :foreign_key => 'updated_by'
|
||||
has_many :created_orders, :class_name => 'Order', :foreign_key => 'created_by_user_id', :dependent => :nullify
|
||||
|
||||
attr_accessor :password, :setting_attributes
|
||||
attr_accessor :password, :settings_attributes
|
||||
|
||||
# makes the current_user (logged-in-user) available in models
|
||||
cattr_accessor :current_user
|
||||
|
||||
validates_presence_of :nick, :email
|
||||
validates_presence_of :password, :on => :create
|
||||
|
@ -32,45 +36,29 @@ class User < ActiveRecord::Base
|
|||
validates_length_of :password, :in => 5..25, :allow_blank => true
|
||||
|
||||
before_validation :set_password
|
||||
after_save :update_settings
|
||||
|
||||
# Adds support for configuration settings (through "settings" attribute).
|
||||
acts_as_configurable
|
||||
|
||||
# makes the current_user (logged-in-user) available in models
|
||||
cattr_accessor :current_user
|
||||
|
||||
# User settings keys
|
||||
# returns the User-settings and the translated description
|
||||
def self.setting_keys
|
||||
{
|
||||
"notify.orderFinished" => I18n.t('model.user.notify.order_finished'),
|
||||
"notify.negativeBalance" => I18n.t('model.user.notify.negative_balance'),
|
||||
"notify.upcoming_tasks" => I18n.t('model.user.notify.upcoming_tasks'),
|
||||
"messages.sendAsEmail" => I18n.t('model.user.notify.send_as_email'),
|
||||
"profile.phoneIsPublic" => I18n.t('model.user.notify.phone_is_public'),
|
||||
"profile.emailIsPublic" => I18n.t('model.user.notify.email_is_public'),
|
||||
"profile.nameIsPublic" => I18n.t('model.user.notify.name_is_public')
|
||||
}
|
||||
end
|
||||
# retuns the default setting for a NEW user
|
||||
# for old records nil will returned
|
||||
# TODO: integrate default behaviour in acts_as_configurable plugin
|
||||
def settings_default(setting)
|
||||
# define a default for the settings
|
||||
defaults = {
|
||||
"messages.sendAsEmail" => true,
|
||||
"notify.upcoming_tasks" => true
|
||||
}
|
||||
return true if self.new_record? && defaults[setting]
|
||||
after_initialize do
|
||||
settings.defaults['profile'] = { 'language' => I18n.default_locale } unless settings.profile
|
||||
settings.defaults['messages'] = { 'send_as_email' => true } unless settings.messages
|
||||
settings.defaults['notify'] = { 'upcoming_tasks' => true } unless settings.notify
|
||||
end
|
||||
|
||||
def update_settings
|
||||
unless setting_attributes.nil?
|
||||
for setting in User::setting_keys.keys
|
||||
self.settings[setting] = setting_attributes[setting] && setting_attributes[setting] == '1' ? '1' : nil
|
||||
after_save do
|
||||
return if settings_attributes.nil?
|
||||
settings_attributes.each do |key, value|
|
||||
value.each do |k, v|
|
||||
case v
|
||||
when '1'
|
||||
value[k] = true
|
||||
when '0'
|
||||
value[k] = false
|
||||
end
|
||||
end
|
||||
self.settings.merge!(key, value)
|
||||
end
|
||||
end
|
||||
|
||||
def locale
|
||||
settings.profile['language']
|
||||
end
|
||||
|
||||
def name
|
||||
|
@ -78,7 +66,7 @@ class User < ActiveRecord::Base
|
|||
end
|
||||
|
||||
def receive_email?
|
||||
settings['messages.sendAsEmail'] == "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.
|
||||
|
|
|
@ -3,54 +3,12 @@ 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
|
||||
validates_presence_of :task_name, :weekday, :task_required_users, :next_weekly_tasks_number,
|
||||
:if => :weekly_task
|
||||
validates_numericality_of :next_weekly_tasks_number, :greater_than => 0, :less_than => 21, :only_integer => true,
|
||||
:if => :weekly_task
|
||||
validates_length_of :task_description, maximum: 250
|
||||
validate :last_admin_on_earth, :on => :update
|
||||
before_destroy :check_last_admin_group
|
||||
|
||||
def self.weekdays
|
||||
days = I18n.t('date.day_names')
|
||||
(0..days.length-1).map {|i| [days[i], i.to_s]}
|
||||
end
|
||||
|
||||
# Returns an Array with date-objects to represent the next weekly-tasks
|
||||
def next_weekly_tasks
|
||||
# our system starts from 0 (sunday) to 6 (saturday)
|
||||
# get difference between groups weekday and now
|
||||
diff = self.weekday - Time.now.wday
|
||||
if diff >= 0
|
||||
# weektask is in current week
|
||||
nextTask = diff.day.from_now
|
||||
else
|
||||
# weektask is in the next week
|
||||
nextTask = (diff + 7).day.from_now
|
||||
end
|
||||
# now generate the Array
|
||||
nextTasks = Array.new
|
||||
next_weekly_tasks_number.times do
|
||||
nextTasks << nextTask.to_date
|
||||
nextTask = 1.week.from_now(nextTask)
|
||||
end
|
||||
return nextTasks
|
||||
end
|
||||
|
||||
def task_attributes(date)
|
||||
{
|
||||
:name => task_name,
|
||||
:description => task_description,
|
||||
:due_date => date,
|
||||
:required_users => task_required_users,
|
||||
:duration => task_duration,
|
||||
:weekly => true
|
||||
}
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
# Check before destroy a group, if this is the last group with admin role
|
||||
|
|
|
@ -20,10 +20,10 @@
|
|||
.well
|
||||
%h4= t '.preference'
|
||||
%table.table
|
||||
- for setting in User::setting_keys.keys
|
||||
- @user.settings.profile.each do |key, setting|
|
||||
%tr
|
||||
%td= User::setting_keys[setting]
|
||||
%td= @user.settings[setting] == '1' ? t('simple_form.yes') : t('simple_form.no')
|
||||
%td= t("simple_form.labels.settings.profile.#{key}")
|
||||
%td= (setting != true and setting != false) ? setting : (setting === true ? t('simple_form.yes') : t('simple_form.no'))
|
||||
.span3
|
||||
.well
|
||||
%h4= t '.groupabos'
|
||||
|
|
|
@ -19,7 +19,9 @@
|
|||
- @articles.each_with_index do |article, index|
|
||||
= fields_for "articles[#{article.id || index}]", article do |form|
|
||||
%tr
|
||||
%td= form.check_box 'availability'
|
||||
%td
|
||||
= yield form # allow to add hidden fields to form
|
||||
= form.check_box 'availability'
|
||||
%td= form.text_field 'name', class: 'input-medium'
|
||||
%td= form.text_field 'unit', class: 'input-mini'
|
||||
%td= form.text_field 'price', class: 'input-mini'
|
||||
|
|
|
@ -2,7 +2,9 @@
|
|||
%p= t('.body').html_safe
|
||||
|
||||
= form_tag(create_from_upload_supplier_articles_path(@supplier)) do
|
||||
= render 'edit_all_table'
|
||||
= render layout: 'edit_all_table' do |form|
|
||||
= form.hidden_field :manufacturer
|
||||
= form.hidden_field :origin
|
||||
.form-actions
|
||||
= submit_tag t('.submit', supplier: @supplier.name), class: 'btn btn-primary'
|
||||
= link_to t('ui.or_cancel'), upload_supplier_articles_path(@supplier)
|
||||
|
|
|
@ -1,45 +1,134 @@
|
|||
- content_for :javascript do
|
||||
:javascript
|
||||
$(function() {
|
||||
$('.destroy_stock_change').live('click', function() {
|
||||
$(this).prev('input').val('1').parent().hide();
|
||||
$('#stock_changes').on('click', '.destroy_stock_change', function() {
|
||||
$(this).prev('input').val('1'); // check for destruction
|
||||
|
||||
var stock_change = $(this).closest('tr');
|
||||
stock_change.hide(); // do not remove (to ensure destruction)
|
||||
stock_change.removeAttr('id'); // remove id to allow re-adding
|
||||
mark_article_for_delivery( stock_change.data('id') );
|
||||
return false;
|
||||
});
|
||||
|
||||
$('.remove_new_stock_change').live('click', function() {
|
||||
$(this).parent().remove();
|
||||
$('#stock_changes').on('click', '.remove_new_stock_change', function() {
|
||||
var stock_change = $(this).closest('tr');
|
||||
stock_change.remove();
|
||||
mark_article_for_delivery( stock_change.data('id') );
|
||||
return false;
|
||||
})
|
||||
|
||||
$('#new_stock_article').removeAttr('disabled').select2({
|
||||
placeholder: '#{t '.create_stock_article'}',
|
||||
data: #{articles_for_select2(@supplier).to_json},
|
||||
createSearchChoice: function(term) {
|
||||
return {
|
||||
id: 'new',
|
||||
text: term
|
||||
};
|
||||
},
|
||||
formatResult: function(result, container, query, escapeMarkup) {
|
||||
if(result.id == 'new') {
|
||||
return result.text + ' (#{t '.create_from_blank'})';
|
||||
}
|
||||
var markup=[];
|
||||
Select2.util.markMatch(result.text, query.term, markup, escapeMarkup);
|
||||
return markup.join("");
|
||||
}
|
||||
}).on('change', function(e) {
|
||||
var selectedArticle = $(e.currentTarget).select2('data');
|
||||
if(!selectedArticle) {
|
||||
return false;
|
||||
}
|
||||
if('new' == selectedArticle.id) {
|
||||
$.ajax({
|
||||
url: '#{new_stock_article_supplier_deliveries_path(@supplier)}',
|
||||
type: 'get',
|
||||
data: {stock_article: {name: selectedArticle.text}},
|
||||
contentType: 'application/json; charset=UTF-8'
|
||||
});
|
||||
$('#new_stock_article').select2('data', null);
|
||||
return true;
|
||||
}
|
||||
if('' != selectedArticle.id) {
|
||||
$.ajax({
|
||||
url: '#{derive_stock_article_supplier_deliveries_path(@supplier)}',
|
||||
type: 'get',
|
||||
data: {old_article_id: selectedArticle.id},
|
||||
contentType: 'application/json; charset=UTF-8'
|
||||
});
|
||||
$('#new_stock_article').select2('data', null);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
enablePriceTooltips();
|
||||
});
|
||||
|
||||
function mark_article_for_delivery(stock_article_id) {
|
||||
var articleTr = $('#stock_article_' + stock_article_id);
|
||||
if( is_article_available_for_delivery(stock_article_id) ) {
|
||||
articleTr.removeClass('unavailable');
|
||||
$('.button-add-stock-change', articleTr).removeAttr('disabled');
|
||||
}
|
||||
else {
|
||||
articleTr.addClass('unavailable');
|
||||
$('.button-add-stock-change', articleTr).attr('disabled', 'disabled');
|
||||
}
|
||||
}
|
||||
function is_article_available_for_delivery(stock_article_id) {
|
||||
return ( 0 == $('#stock_change_stock_article_' + stock_article_id).length );
|
||||
}
|
||||
|
||||
function enablePriceTooltips(context) {
|
||||
$('[data-toggle~="tooltip"]', context).tooltip({
|
||||
animation: false,
|
||||
html: true,
|
||||
placement: 'left'
|
||||
});
|
||||
}
|
||||
|
||||
= simple_form_for [@supplier, @delivery], validate: true do |f|
|
||||
= f.hidden_field :supplier_id
|
||||
#stock_changes
|
||||
= f.fields_for :stock_changes do |stock_change_form|
|
||||
%p
|
||||
= stock_change_form.select :stock_article_id, stock_articles_for_select(@supplier)
|
||||
Menge
|
||||
= stock_change_form.text_field :quantity, size: 5, autocomplete: 'off'
|
||||
= stock_change_form.hidden_field :_destroy
|
||||
= link_to t('.remove_article'), "#", class: 'destroy_stock_change'
|
||||
%p
|
||||
= link_to t('.add_article'), {action: 'add_stock_change', supplier_id: @supplier.id}, remote: true
|
||||
%p
|
||||
%small= t('.note_new_article', new_link: link_to(t('.note_new_article_link'), new_stock_article_path)).html_safe
|
||||
%hr/
|
||||
= f.error_notification
|
||||
= base_errors f.object
|
||||
= f.association :supplier, :as => :hidden
|
||||
|
||||
%h2= t '.title_select_stock_articles'
|
||||
%table#stock_articles_for_adding.table.table-hover.stupidtable
|
||||
%thead
|
||||
%tr
|
||||
%th.default-sort{:data => {:sort => 'string'}}= t '.article'
|
||||
%th= t '.price'
|
||||
%th= t '.unit'
|
||||
%th= t '.category'
|
||||
%th= t '.actions'
|
||||
%tfoot
|
||||
%tr
|
||||
%th{:colspan => 5}
|
||||
- if articles_for_select2(@supplier).empty?
|
||||
= link_to t('.create_stock_article'), new_stock_article_supplier_deliveries_path(@supplier), :remote => true, :class => 'btn'
|
||||
- else
|
||||
%input#new_stock_article{:style => 'width: 500px;'}
|
||||
%tbody
|
||||
- for article in stock_articles_for_table(@supplier)
|
||||
= render :partial => 'stock_article_for_adding', :locals => {:article => article}
|
||||
|
||||
%h2= t '.title_fill_quantities'
|
||||
%table.table#stock_changes.stupidtable
|
||||
%thead
|
||||
%tr
|
||||
%th.default-sort{:data => {:sort => 'string'}}= t '.article'
|
||||
%th= t '.price'
|
||||
%th= t '.unit'
|
||||
%th= t '.quantity'
|
||||
%th= t '.actions'
|
||||
%tbody
|
||||
= f.simple_fields_for :stock_changes do |stock_change_form|
|
||||
= render :partial => 'stock_change_fields', :locals => {:f => stock_change_form}
|
||||
|
||||
%h2= t '.title_finish_delivery'
|
||||
= f.input :delivered_on, as: :date_picker
|
||||
= f.input :note, input_html: {size: '35x4'}
|
||||
.form-actions
|
||||
= f.submit class: 'btn btn-primary'
|
||||
= link_to t('ui.or_cancel'), supplier_deliveries_path(@supplier)
|
||||
|
||||
/
|
||||
TODO: Fix this!!
|
||||
.span6
|
||||
%h2= t '.new_article.title'
|
||||
%p
|
||||
= t('.new_article.search', supplier: @supplier.name).html_safe + ': '
|
||||
= text_field_tag 'article_name'
|
||||
%hr/
|
||||
#stock_article_form
|
||||
= render 'stock_article_form', stock_article: @supplier.stock_articles.build
|
||||
|
|
11
app/views/deliveries/_stock_article_for_adding.html.haml
Normal file
11
app/views/deliveries/_stock_article_for_adding.html.haml
Normal file
|
@ -0,0 +1,11 @@
|
|||
- css_class = ( @delivery and @delivery.includes_article? article ) ? ( 'unavailable' ) : ( false )
|
||||
%tr{:id => "stock_article_#{article.id}", :class => css_class}
|
||||
%td= article.name
|
||||
%td{:data => {:toggle => :tooltip, :title => render(:partial => 'shared/article_price_info', :locals => {:article => article})}}= number_to_currency article.price
|
||||
%td= article.unit
|
||||
%td= article.article_category.name
|
||||
%td
|
||||
= link_to t('.action_edit'), edit_stock_article_supplier_deliveries_path(@supplier, :stock_article_id => article.id), remote: true, class: 'btn btn-mini'
|
||||
= link_to t('.action_other_price'), copy_stock_article_supplier_deliveries_path(@supplier, :old_stock_article_id => article.id), remote: true, class: 'btn btn-mini'
|
||||
- deliver_button_disabled = ( @delivery and @delivery.includes_article? article ) ? ( 'disabled' ) : ( false )
|
||||
= link_to t('.action_add_to_delivery'), add_stock_change_supplier_deliveries_path(@supplier, :stock_article_id => article.id), :method => :post, remote: true, class: 'button-add-stock-change btn btn-mini btn-primary', disabled: deliver_button_disabled
|
|
@ -1,14 +1,23 @@
|
|||
= simple_form_for stock_article, url: add_stock_article_supplier_deliveries_path(@supplier), remote: true,
|
||||
validate: true do |f|
|
||||
= f.hidden_field :supplier_id
|
||||
- url = ( stock_article.new_record? ) ? ( create_stock_article_supplier_deliveries_path(@supplier) ) : ( update_stock_article_supplier_deliveries_path(@supplier) )
|
||||
= simple_form_for stock_article, url: url, remote: true, validate: true do |f|
|
||||
= f.association :supplier, :as => :hidden
|
||||
= f.hidden_field :id unless stock_article.new_record?
|
||||
.modal-header
|
||||
= link_to t('ui.marks.close').html_safe, '#', class: 'close', data: {dismiss: 'modal'}
|
||||
%h3= t 'activerecord.models.stock_article'
|
||||
.modal-body
|
||||
= f.input :name
|
||||
= f.input :unit
|
||||
= f.input :note
|
||||
- if stock_article.new_record?
|
||||
= f.input :price
|
||||
= f.input :tax, :wrapper => :append do
|
||||
= f.input_field :tax
|
||||
%span.add-on %
|
||||
-# untested, because this view is currently not included (?)
|
||||
= f.input :deposit
|
||||
- else
|
||||
= f.input :price, :input_html => {:disabled => 'disabled'}, :hint => stock_article_price_hint(stock_article)
|
||||
= f.association :article_category
|
||||
= f.submit class: 'btn'
|
||||
.modal-footer
|
||||
= link_to t('ui.close'), '#', class: 'btn', data: {dismiss: 'modal'}
|
||||
= f.submit :class => 'btn btn-primary', 'data-disable-with' => t('ui.please_wait')
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
%p
|
||||
= fields_for "delivery[new_stock_changes][]", stock_change do |form|
|
||||
= form.select :stock_article_id, stock_articles_for_select(supplier)
|
||||
Menge
|
||||
= form.text_field :quantity, :size => 5, :autocomplete => 'off'
|
||||
= link_to t('.remove_article'), "#", :class => 'remove_new_stock_change'
|
||||
- if stock_change.stock_article.new_record?
|
||||
= simple_fields_for "delivery[new_stock_changes_new_stock_article][]", stock_change do |f|
|
||||
= render :partial => 'stock_change_fields', :locals => {:f => f}
|
||||
- else
|
||||
= simple_fields_for "delivery[new_stock_changes][]", stock_change do |f|
|
||||
= render :partial => 'stock_change_fields', :locals => {:f => f}
|
||||
|
|
10
app/views/deliveries/_stock_change_fields.html.haml
Normal file
10
app/views/deliveries/_stock_change_fields.html.haml
Normal file
|
@ -0,0 +1,10 @@
|
|||
- stock_change = f.object
|
||||
- stock_article = stock_change.stock_article
|
||||
%tr{:id => "stock_change_stock_article_#{stock_article.id}", :data => {:id => stock_article.id}}
|
||||
%td
|
||||
%span.stock_article_name= stock_change.stock_article.name
|
||||
= f.association :stock_article, :as => :hidden
|
||||
%td.price{:data => {:toggle => :tooltip, :title => render(:partial => 'shared/article_price_info', :locals => {:article => stock_article})}}= number_to_currency stock_article.price
|
||||
%td.unit= stock_change.stock_article.unit
|
||||
%td= f.input :quantity, :wrapper => :intable, :input_html => {:class => 'stock-change-quantity', :autocomplete => :off}
|
||||
%td= stock_change_remove_link f
|
25
app/views/deliveries/add_stock_change.js.erb
Normal file
25
app/views/deliveries/add_stock_change.js.erb
Normal file
|
@ -0,0 +1,25 @@
|
|||
(function(w) {
|
||||
if(!is_article_available_for_delivery(<%= @stock_change.stock_article.id %>)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$('#stock_changes tr').removeClass('success');
|
||||
|
||||
var stock_change = $(
|
||||
'<%= j(render(:partial => 'stock_change', :locals => {:stock_change => @stock_change})) %>'
|
||||
).addClass('success');
|
||||
enablePriceTooltips(stock_change);
|
||||
|
||||
$('#stock_changes').append(stock_change);
|
||||
mark_article_for_delivery(<%= @stock_change.stock_article.id %>);
|
||||
updateSort('#stock_changes');
|
||||
|
||||
var quantity = w.prompt('<%= j(t('.how_many_units', :unit => @stock_change.stock_article.unit, :name => @stock_change.stock_article.name)) %>'); <%# how to properly escape here? %>
|
||||
if(null === quantity) {
|
||||
stock_change.remove();
|
||||
mark_article_for_delivery(<%= @stock_change.stock_article.id %>);
|
||||
return false;
|
||||
}
|
||||
$('input.stock-change-quantity', stock_change).val(quantity);
|
||||
|
||||
})(window);
|
|
@ -1 +0,0 @@
|
|||
$('#stock_changes').append('#{escape_javascript(render(:partial => 'stock_change', :locals => {:stock_change => StockChange.new, :supplier => @supplier}))}');
|
5
app/views/deliveries/copy_stock_article.js.erb
Normal file
5
app/views/deliveries/copy_stock_article.js.erb
Normal file
|
@ -0,0 +1,5 @@
|
|||
$('#modalContainer').html(
|
||||
'<%= j(render(:partial => "stock_article_form", :locals => {:stock_article => @stock_article})) %>'
|
||||
);
|
||||
|
||||
$('#modalContainer').modal();
|
17
app/views/deliveries/create_stock_article.js.erb
Normal file
17
app/views/deliveries/create_stock_article.js.erb
Normal file
|
@ -0,0 +1,17 @@
|
|||
$('div.container-fluid').prepend(
|
||||
'<%= j(render(:partial => 'shared/alert_success', :locals => {:alert_message => t('.notice', :name => @stock_article.name)})) %>'
|
||||
);
|
||||
|
||||
(function() {
|
||||
$('#stock_articles_for_adding tr').removeClass('success');
|
||||
|
||||
var stock_article_for_adding = $(
|
||||
'<%= j(render(:partial => 'stock_article_for_adding', :locals => {:article => @stock_article})) %>'
|
||||
).addClass('success');
|
||||
enablePriceTooltips(stock_article_for_adding);
|
||||
|
||||
$('#stock_articles_for_adding tbody').append(stock_article_for_adding);
|
||||
updateSort('#stock_articles_for_adding');
|
||||
})();
|
||||
|
||||
$('#modalContainer').modal('hide');
|
5
app/views/deliveries/derive_stock_article.js.erb
Normal file
5
app/views/deliveries/derive_stock_article.js.erb
Normal file
|
@ -0,0 +1,5 @@
|
|||
$('#modalContainer').html(
|
||||
'<%= j(render(:partial => "stock_article_form", :locals => {:stock_article => @stock_article})) %>'
|
||||
);
|
||||
|
||||
$('#modalContainer').modal();
|
5
app/views/deliveries/edit_stock_article.js.erb
Normal file
5
app/views/deliveries/edit_stock_article.js.erb
Normal file
|
@ -0,0 +1,5 @@
|
|||
$('#modalContainer').html(
|
||||
'<%= j(render(:partial => "stock_article_form", :locals => {:stock_article => @stock_article})) %>'
|
||||
);
|
||||
|
||||
$('#modalContainer').modal();
|
5
app/views/deliveries/new_stock_article.js.erb
Normal file
5
app/views/deliveries/new_stock_article.js.erb
Normal file
|
@ -0,0 +1,5 @@
|
|||
$('#modalContainer').html(
|
||||
'<%= j(render(:partial => "stock_article_form", :locals => {:stock_article => @stock_article})) %>'
|
||||
);
|
||||
|
||||
$('#modalContainer').modal();
|
33
app/views/deliveries/update_stock_article.js.erb
Normal file
33
app/views/deliveries/update_stock_article.js.erb
Normal file
|
@ -0,0 +1,33 @@
|
|||
$('div.container-fluid').prepend(
|
||||
'<%= j(render(:partial => 'shared/alert_success', :locals => {:alert_message => t('.notice', :name => @stock_article.name)})) %>'
|
||||
);
|
||||
|
||||
(function() {
|
||||
// update entry in stock_article table
|
||||
|
||||
$('#stock_articles_for_adding tr').removeClass('success');
|
||||
|
||||
var stock_article_for_adding = $(
|
||||
'<%= j(render(:partial => 'stock_article_for_adding', :locals => {:article => @stock_article, :delivery => @delivery})) %>'
|
||||
).addClass('success');
|
||||
enablePriceTooltips(stock_article_for_adding);
|
||||
|
||||
$('#stock_article_<%= @stock_article.id %>').replaceWith(stock_article_for_adding);
|
||||
updateSort('#stock_articles_for_adding');
|
||||
|
||||
mark_article_for_delivery(<%= @stock_article.id %>);
|
||||
|
||||
// update entry in stock_changes table
|
||||
|
||||
$('#stock_changes tr').removeClass('success');
|
||||
|
||||
var stock_change_entry = $('#stock_change_stock_article_<%= @stock_article.id %>');
|
||||
$('.stock_article_name', stock_change_entry).text('<%= j(@stock_article.name) %>');
|
||||
$('.unit', stock_change_entry).text('<%= j(@stock_article.unit) %>');
|
||||
|
||||
stock_change_entry.addClass('success');
|
||||
|
||||
updateSort('#stock_changes');
|
||||
})();
|
||||
|
||||
$('#modalContainer').modal('hide');
|
|
@ -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')
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -14,9 +14,9 @@
|
|||
- for user in @users
|
||||
%tr
|
||||
%td= user.nick
|
||||
%td= user.name if @current_user.role_admin? || user.settings["profile.nameIsPublic"] == '1'
|
||||
%td= user.email if @current_user.role_admin? || user.settings["profile.emailIsPublic"] == '1'
|
||||
%td= user.phone if @current_user.role_admin? || user.settings["profile.phoneIsPublic"] == '1'
|
||||
%td= user.name if @current_user.role_admin? || user.settings.profile["name_is_public"]
|
||||
%td= user.email if @current_user.role_admin? || user.settings.profile["email_is_public"]
|
||||
%td= user.phone if @current_user.role_admin? || user.settings.profile["phone_is_public"]
|
||||
%td= user.ordergroup_name
|
||||
%td= user.workgroups.collect(&:name).join(', ')
|
||||
%td= link_to_new_message(message_params: {mail_to: user.id})
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#{data_to_js(@ordering_data)}
|
||||
setGroupBalance(#{@ordering_data[:available_funds]});
|
||||
setCurrencyFormat("#{t('number.currency.format.separator')}", #{t('number.currency.format.precision')}, "#{t('number.currency.format.unit')}");
|
||||
setMinimumBalance(#{FoodsoftConfig[:minimum_balance] or 0});
|
||||
setToleranceBehaviour(#{FoodsoftConfig[:tolerance_is_costly]});
|
||||
setStockit(#{@order.stockit?});
|
||||
});
|
||||
|
|
|
@ -22,5 +22,7 @@
|
|||
Javascripts
|
||||
\==================================================
|
||||
/ Placed at the end of the document so the pages load faster
|
||||
:javascript
|
||||
I18n = {locale: '#{j(I18n.locale.to_s)}'}
|
||||
= javascript_include_tag "application"
|
||||
= yield(:javascript)
|
||||
|
|
|
@ -45,26 +45,6 @@
|
|||
= f.label :role_orders
|
||||
%br/
|
||||
= f.check_box :role_orders
|
||||
%p
|
||||
= f.label :weekly_task
|
||||
%br/
|
||||
= f.check_box :weekly_task
|
||||
%p
|
||||
= f.label :weekday
|
||||
%br/
|
||||
= f.text_field :weekday
|
||||
%p
|
||||
= f.label :task_name
|
||||
%br/
|
||||
= f.text_field :task_name
|
||||
%p
|
||||
= f.label :task_description
|
||||
%br/
|
||||
= f.text_field :task_description
|
||||
%p
|
||||
= f.label :task_required_users
|
||||
%br/
|
||||
= f.text_field :task_required_users
|
||||
%p
|
||||
= f.label :deleted_at
|
||||
%br/
|
||||
|
|
|
@ -12,11 +12,6 @@
|
|||
%th Role Article Meta
|
||||
%th Role Finance
|
||||
%th Role Orders
|
||||
%th Weekly Task
|
||||
%th Weekday
|
||||
%th Task Name
|
||||
%th Task Description
|
||||
%th Task Required Users
|
||||
%th Deleted At
|
||||
%th Contact Person
|
||||
%th Contact Phone
|
||||
|
@ -34,11 +29,6 @@
|
|||
%td= h ordergroup.role_article_meta
|
||||
%td= h ordergroup.role_finance
|
||||
%td= h ordergroup.role_orders
|
||||
%td= h ordergroup.weekly_task
|
||||
%td= h ordergroup.weekday
|
||||
%td= h ordergroup.task_name
|
||||
%td= h ordergroup.task_description
|
||||
%td= h ordergroup.task_required_users
|
||||
%td= h ordergroup.deleted_at
|
||||
%td= h ordergroup.contact_person
|
||||
%td= h ordergroup.contact_phone
|
||||
|
|
|
@ -29,7 +29,10 @@
|
|||
- if order.stockit?
|
||||
%td= units
|
||||
- else
|
||||
%td= "#{order_article.quantity} + #{order_article.tolerance}" if unit_quantity > 1
|
||||
- if unit_quantity > 1 or order_article.tolerance > 0
|
||||
%td= "#{order_article.quantity} + #{order_article.tolerance}"
|
||||
- else
|
||||
%td= "#{order_article.quantity}"
|
||||
%td= units
|
||||
%p
|
||||
= t '.prices_sum'
|
||||
|
|
|
@ -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
|
||||
|
|
5
app/views/shared/_alert_success.haml
Normal file
5
app/views/shared/_alert_success.haml
Normal file
|
@ -0,0 +1,5 @@
|
|||
.alert.fade.in.alert-success
|
||||
%a.close{:href => '#', :data => {:dismiss => 'alert'}}
|
||||
= t('ui.marks.close').html_safe
|
||||
= t('ui.marks.success').html_safe
|
||||
= alert_message
|
17
app/views/shared/_article_price_info.html.haml
Normal file
17
app/views/shared/_article_price_info.html.haml
Normal file
|
@ -0,0 +1,17 @@
|
|||
%table.table.table-condensed
|
||||
%tr
|
||||
%th= t 'activerecord.attributes.article.price'
|
||||
%td.numeric= number_to_currency article.price
|
||||
%tr
|
||||
%th= t 'activerecord.attributes.article.deposit'
|
||||
%td.numeric= number_to_currency article.deposit
|
||||
%tr
|
||||
%th= t 'activerecord.attributes.article.tax'
|
||||
%td.numeric= number_to_percentage article.tax
|
||||
- unless article.fc_price == article.gross_price
|
||||
%tr
|
||||
%th= t 'activerecord.attributes.article.fc_share'
|
||||
%td.numeric= number_to_currency(article.fc_price-article.gross_price)
|
||||
%tr
|
||||
%th= t 'activerecord.attributes.article.fc_price'
|
||||
%td.numeric= number_to_currency article.fc_price
|
|
@ -2,8 +2,10 @@
|
|||
%thead
|
||||
%tr
|
||||
%th{:style => 'width:70%'}= t '.ordergroup'
|
||||
%th= t '.ordered'
|
||||
%th= t '.received'
|
||||
%th
|
||||
%acronym{:title => t('shared.articles.ordered_desc')}= t 'shared.articles.ordered'
|
||||
%th
|
||||
%acronym{:title => t('shared.articles.received_desc')}= t 'shared.articles.received'
|
||||
%th= t '.price'
|
||||
|
||||
- for order_article in order.order_articles.ordered.all(:include => [:article, :article_price])
|
||||
|
@ -13,8 +15,8 @@
|
|||
= order_article.article.name
|
||||
= "(#{order_article.article.unit} | #{order_article.price.unit_quantity} | #{number_to_currency(order_article.price.gross_price)})"
|
||||
%tbody
|
||||
- for goa in order_article.group_order_articles
|
||||
%tr{:class => cycle('even', 'odd', :name => 'groups')}
|
||||
- for goa in order_article.group_order_articles.ordered
|
||||
%tr{:class => [cycle('even', 'odd', :name => 'groups'), if goa.result == 0 then 'unavailable' end]}
|
||||
%td{:style => "width:70%"}=h goa.group_order.ordergroup.name
|
||||
%td= "#{goa.quantity} + #{goa.tolerance}"
|
||||
%td
|
||||
|
|
|
@ -3,7 +3,9 @@
|
|||
%tr
|
||||
%th{:style => "width:40%"}= t '.name'
|
||||
%th
|
||||
%acronym{:title => t('.units_desc')}= t '.units'
|
||||
%acronym{:title => t('shared.articles.ordered_desc')}= t 'shared.articles.ordered'
|
||||
%th
|
||||
%acronym{:title => t('shared.articles.received_desc')}= t 'shared.articles.received'
|
||||
%th
|
||||
%acronym{:title => t('.fc_price_desc')}= t '.fc_price'
|
||||
%th
|
||||
|
@ -11,10 +13,10 @@
|
|||
%th= t '.unit'
|
||||
%th= t '.price'
|
||||
|
||||
- for group_order in order.group_orders.all
|
||||
- for group_order in order.group_orders.ordered
|
||||
%thead
|
||||
%tr
|
||||
%th{:colspan => "6"}
|
||||
%th{:colspan => "7"}
|
||||
%h4= group_order.ordergroup.name
|
||||
%tbody
|
||||
- total = 0
|
||||
|
@ -22,17 +24,19 @@
|
|||
- fc_price = goa.order_article.price.fc_price
|
||||
- subTotal = fc_price * goa.result
|
||||
- total += subTotal
|
||||
%tr{:class => cycle('even', 'odd', :name => 'articles')}
|
||||
%tr{:class => [cycle('even', 'odd', :name => 'articles'), if goa.result == 0 then 'unavailable' end]}
|
||||
%td{:style => "width:40%"}=h goa.order_article.article.name
|
||||
%td= goa.result
|
||||
%td= "#{goa.quantity} + #{goa.tolerance}"
|
||||
%td
|
||||
%b= goa.result
|
||||
%td= number_to_currency(fc_price)
|
||||
%td= goa.order_article.price.unit_quantity
|
||||
%td= goa.order_article.article.unit
|
||||
%td= number_to_currency(subTotal)
|
||||
|
||||
%tr{:class => cycle('even', 'odd', :name => 'articles')}
|
||||
%th{:colspan => "5"} Summe
|
||||
%th{:colspan => "6"} Summe
|
||||
%th= number_to_currency(total)
|
||||
%tr
|
||||
%th(colspan="6")
|
||||
%th(colspan="7")
|
||||
- reset_cycle("articles")
|
||||
|
|
5
app/views/shared/_base_errors.haml
Normal file
5
app/views/shared/_base_errors.haml
Normal file
|
@ -0,0 +1,5 @@
|
|||
.alert.alert-error.alert-block
|
||||
%a.close{:href => '#', :data => {:dismiss => 'alert'}}
|
||||
= t('ui.marks.close').html_safe
|
||||
%ul
|
||||
= error_messages.html_safe
|
|
@ -13,13 +13,6 @@
|
|||
- members = group.users
|
||||
= "(#{members.size})"
|
||||
= members.collect(&:nick).join(", ")
|
||||
- if group.is_a?(Workgroup)
|
||||
%dt= t('.weekly_job') + ':'
|
||||
%dd
|
||||
- if group.weekly_task
|
||||
=h "#{group.task_name} am #{weekday(group.weekday)}"
|
||||
- else
|
||||
= t '.no_weekly_job'
|
||||
- else
|
||||
- unless group.is_a?(Workgroup)
|
||||
%dt= t '.apple_limit'
|
||||
%dd= group.ignore_apple_restriction ? t('.deactivated') : t('.activated')
|
||||
|
|
|
@ -3,17 +3,6 @@
|
|||
|
||||
= yield
|
||||
|
||||
- if f.object.is_a?(Workgroup)
|
||||
%h3= t '.title'
|
||||
= f.input :weekly_task
|
||||
#weekly_task_fields
|
||||
= f.input :weekday, as: :select, collection: Workgroup.weekdays
|
||||
= f.input :task_name
|
||||
= f.input :task_required_users
|
||||
= f.input :task_duration, :as => :select, :collection => (1..3)
|
||||
= f.input :task_description, as: :text, input_html: {rows: 5}
|
||||
= f.input :next_weekly_tasks_number
|
||||
|
||||
= f.input :user_tokens, :as => :string,
|
||||
:input_html => { 'data-pre' => f.object.users.map { |u| u.token_attributes }.to_json }
|
||||
|
||||
|
|
|
@ -5,11 +5,31 @@
|
|||
= f.input :phone
|
||||
= f.input :password, :required => f.object.new_record?
|
||||
= f.input :password_confirmation
|
||||
.control-group
|
||||
.controls
|
||||
- for setting in User::setting_keys.keys
|
||||
%label.checkbox{:for => "user[setting_attributes][#{setting}]"}
|
||||
= hidden_field_tag "user[setting_attributes][#{setting}]", '0'
|
||||
= check_box_tag "user[setting_attributes][#{setting}]", '1',
|
||||
f.object.settings[setting] == '1' || f.object.settings_default(setting)
|
||||
= User::setting_keys[setting]
|
||||
|
||||
= f.simple_fields_for :settings_attributes do |s|
|
||||
= s.simple_fields_for :profile, defaults: { inline_label: true } do |profile|
|
||||
= profile.input 'language', as: :select, collection: available_locales, required: false, selected: f.object.settings.profile['language']
|
||||
|
||||
.settings
|
||||
.settings-group
|
||||
= s.simple_fields_for :profile, defaults: { inline_label: true } do |profile|
|
||||
|
||||
%div{class: 'control-group h_wrapper'}
|
||||
%h5{class: 'controls'}
|
||||
= t 'simple_form.labels.settings.settings_group.privacy'
|
||||
= profile.input 'phone_is_public', as: :boolean, label: false, input_html: { checked: f.object.settings.profile['phone_is_public'] }
|
||||
= profile.input 'email_is_public', as: :boolean, label: false, input_html: { checked: f.object.settings.profile['email_is_public'] }
|
||||
= profile.input 'name_is_public', as: :boolean, label: false, input_html: { checked: f.object.settings.profile['name_is_public'] }
|
||||
|
||||
.settings-group
|
||||
%div{class: 'control-group'}
|
||||
%h5{class: 'controls'}
|
||||
= t 'simple_form.labels.settings.settings_group.messages'
|
||||
|
||||
= s.simple_fields_for :messages, defaults: { inline_label: true, label: false } do |messages|
|
||||
= messages.input 'send_as_email', as: :boolean, input_html: { checked: f.object.settings.messages['send_as_email'] }
|
||||
= s.simple_fields_for :notify, defaults: { inline_label: true, label: false } do |notify|
|
||||
= notify.input 'order_finished', as: :boolean, input_html: { checked: f.object.settings.notify['order_finished'] }
|
||||
= notify.input 'negative_balance', as: :boolean, input_html: { checked: f.object.settings.notify['negative_balance'] }
|
||||
= notify.input 'upcoming_tasks', as: :boolean, input_html: { checked: f.object.settings.notify['upcoming_tasks'] }
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -4,11 +4,5 @@ var successDiv = $('<div class="alert fade in alert-success"><a class="close" da
|
|||
successDiv.append(document.createTextNode('#{escape_javascript(t('.notice', name: @article.name))}'));
|
||||
$('div.container-fluid').prepend(successDiv);
|
||||
|
||||
-# WARNING: If you try to use the escape j(...) here, an error occurs:
|
||||
-# Ein Fehler ist aufgetreten: undefined method `gsub' for 50:Fixnum
|
||||
-# However, it should work without without escaping.
|
||||
-# Note that article names which are purely numeric, e.g. 12345, are escaped correctly (see above).
|
||||
|
||||
$('#stockArticle-#{@article.id}').remove();
|
||||
|
||||
-# WARNING: Do not use a simple .fadeOut() above, because it conflicts with the show/hide function of unavailable articles.
|
||||
|
|
17
app/views/stockit/history.haml
Normal file
17
app/views/stockit/history.haml
Normal file
|
@ -0,0 +1,17 @@
|
|||
- title t('.stock_changes', :article_name => @stock_article.name)
|
||||
|
||||
%table.table.table-hover#stock_changes
|
||||
%thead
|
||||
%tr
|
||||
%th= t '.datetime'
|
||||
%th= t '.reason'
|
||||
%th= t '.change_quantity'
|
||||
%th= t '.new_quantity'
|
||||
%tbody
|
||||
- reversed_history = @stock_article.quantity_history.reverse
|
||||
- @stock_changes.each_with_index do |stock_change, index|
|
||||
%tr
|
||||
%td= l stock_change.created_at
|
||||
%td= link_to_stock_change_reason(stock_change)
|
||||
%td= stock_change.quantity
|
||||
%td= reversed_history[index]
|
|
@ -1,4 +1,4 @@
|
|||
- title "Lager (#{StockArticle.available.count})"
|
||||
- title t('.title', article_count: StockArticle.available.count)
|
||||
- content_for :javascript do
|
||||
:javascript
|
||||
$(function() {
|
||||
|
@ -56,6 +56,7 @@
|
|||
%td= article.article_category.name
|
||||
%td
|
||||
= link_to t('ui.edit'), edit_stock_article_path(article), class: 'btn btn-mini'
|
||||
= link_to t('ui.history'), stock_article_history_path(article), class: 'btn btn-mini'
|
||||
= link_to t('ui.delete'), article, :method => :delete, :confirm => t('.confirm_delete'),
|
||||
class: 'btn btn-mini btn-danger', :remote => true
|
||||
%p
|
||||
|
|
|
@ -17,7 +17,9 @@
|
|||
%td= shared_supplier.note
|
||||
%td= shared_supplier.delivery_days
|
||||
%td
|
||||
- if shared_supplier.supplier
|
||||
- if shared_supplier.suppliers.any?
|
||||
%i.icon-ok
|
||||
= associated_supplier_names(shared_supplier)
|
||||
= link_to t('.subscribe_again'), new_supplier_path(:shared_supplier_id => shared_supplier), class: 'btn'
|
||||
- else
|
||||
= link_to t('.subscribe'), new_supplier_path(:shared_supplier_id => shared_supplier), class: 'btn'
|
||||
|
|
|
@ -25,5 +25,7 @@
|
|||
= f.input :due_date, as: :date_picker
|
||||
= f.input :done
|
||||
.form-actions
|
||||
= f.submit class: 'btn'
|
||||
= f.submit class: 'btn btn-primary'
|
||||
- if @task.new_record?
|
||||
= f.submit t('.submit.periodic'), name: 'periodic', class: 'btn'
|
||||
= link_to t('ui.or_cancel'), :back
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
%thead
|
||||
%tr
|
||||
%th= t '.due_date'
|
||||
%th
|
||||
%th= t '.task'
|
||||
%th{:colspan => '2'}
|
||||
= t '.who'
|
||||
|
@ -11,6 +12,9 @@
|
|||
- done = task.done ? " done" : ""
|
||||
%tr{:class => done }
|
||||
%td= format_date(task.due_date) unless task.due_date.nil?
|
||||
%td
|
||||
- if task.periodic?
|
||||
%i.icon-repeat{title: t('tasks.repeated')}
|
||||
%td= link_to t('.task_format', name: task.name, duration: task.duration), task_path(task)
|
||||
%td
|
||||
= task_assignments task
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -10,7 +10,10 @@
|
|||
%dd= simple_format(@task.description)
|
||||
- if @task.due_date.present?
|
||||
%dt= t '.due_date'
|
||||
%dd= format_date(@task.due_date)
|
||||
%dd
|
||||
= format_date(@task.due_date)
|
||||
- if @task.periodic?
|
||||
%i.icon-repeat{title: t('tasks.repeated')}
|
||||
%dt= t 'simple_form.labels.task.duration'
|
||||
%dd= t('.hours', count: @task.duration)
|
||||
%dt= t 'simple_form.labels.task.user_list'
|
||||
|
@ -29,3 +32,6 @@
|
|||
= link_to t('ui.edit'), edit_task_path(@task), class: 'btn'
|
||||
= link_to t('ui.delete'), task_path(@task), :method => :delete, :confirm => "Die Aufgabe wirklich löschen?",
|
||||
class: 'btn btn-danger'
|
||||
- if @task.periodic?
|
||||
= link_to t('.delete_group'), task_path(@task, periodic: true), method: :delete,
|
||||
confirm: t('.confirm_delete_group'), class: 'btn btn-danger'
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
- title "Meine Aufgaben"
|
||||
- title t('.title')
|
||||
= render 'nav'
|
||||
|
||||
- unless @unaccepted_tasks.empty?
|
||||
|
|
|
@ -1,16 +1,6 @@
|
|||
- title t('.title', workgroup: @group.name)
|
||||
= render 'nav'
|
||||
|
||||
%section.well
|
||||
%h3= t '.weekly.title'
|
||||
- if @group.weekly_task
|
||||
= t('.weekly.desc', weekday: weekday(@group.weekday), task: @group.task_name).html_safe
|
||||
- else
|
||||
= t('.weekly.empty').html_safe
|
||||
|
||||
- if @current_user.member_of?(@group) or @current_user.role_admin?
|
||||
= link_to t('.weekly.edit'), edit_foodcoop_workgroup_path(@group), class: 'btn'
|
||||
|
||||
%section
|
||||
%h3= t '.title_all'
|
||||
= render 'list', tasks: @group.open_tasks
|
||||
|
|
|
@ -45,26 +45,6 @@
|
|||
= f.label :role_orders
|
||||
%br/
|
||||
= f.check_box :role_orders
|
||||
%p
|
||||
= f.label :weekly_task
|
||||
%br/
|
||||
= f.check_box :weekly_task
|
||||
%p
|
||||
= f.label :weekday
|
||||
%br/
|
||||
= f.text_field :weekday
|
||||
%p
|
||||
= f.label :task_name
|
||||
%br/
|
||||
= f.text_field :task_name
|
||||
%p
|
||||
= f.label :task_description
|
||||
%br/
|
||||
= f.text_field :task_description
|
||||
%p
|
||||
= f.label :task_required_users
|
||||
%br/
|
||||
= f.text_field :task_required_users
|
||||
%p
|
||||
= f.label :deleted_at
|
||||
%br/
|
||||
|
|
|
@ -12,11 +12,6 @@
|
|||
%th Role Article Meta
|
||||
%th Role Finance
|
||||
%th Role Orders
|
||||
%th Weekly Task
|
||||
%th Weekday
|
||||
%th Task Name
|
||||
%th Task Description
|
||||
%th Task Required Users
|
||||
%th Deleted At
|
||||
%th Contact Person
|
||||
%th Contact Phone
|
||||
|
@ -34,11 +29,6 @@
|
|||
%td= h workgroup.role_article_meta
|
||||
%td= h workgroup.role_finance
|
||||
%td= h workgroup.role_orders
|
||||
%td= h workgroup.weekly_task
|
||||
%td= h workgroup.weekday
|
||||
%td= h workgroup.task_name
|
||||
%td= h workgroup.task_description
|
||||
%td= h workgroup.task_required_users
|
||||
%td= h workgroup.deleted_at
|
||||
%td= h workgroup.contact_person
|
||||
%td= h workgroup.contact_phone
|
||||
|
|
|
@ -18,7 +18,7 @@ class UserNotifier
|
|||
Order.find(order_id).group_orders.each do |group_order|
|
||||
group_order.ordergroup.users.each do |user|
|
||||
begin
|
||||
Mailer.order_result(user, group_order).deliver if user.settings["notify.orderFinished"] == '1'
|
||||
Mailer.order_result(user, group_order).deliver if user.settings.notify["order_finished"]
|
||||
rescue
|
||||
Rails.logger.warn "Can't deliver mail to #{user.email}"
|
||||
end
|
||||
|
@ -34,7 +34,7 @@ class UserNotifier
|
|||
|
||||
Ordergroup.find(ordergroup_id).users.each do |user|
|
||||
begin
|
||||
Mailer.negative_balance(user, transaction).deliver if user.settings["notify.negativeBalance"] == '1'
|
||||
Mailer.negative_balance(user, transaction).deliver if user.settings.notify["negative_balance"]
|
||||
rescue
|
||||
Rails.logger.warn "Can't deliver mail to #{user.email}"
|
||||
end
|
||||
|
|
|
@ -37,6 +37,9 @@ default: &defaults
|
|||
# price markup in percent
|
||||
price_markup: 2.0
|
||||
|
||||
# default vat percentage for new articles
|
||||
tax_default: 7.0
|
||||
|
||||
# tolerance order option: If set to false, article tolerance values do not count
|
||||
# for total article price as long as the order is not finished.
|
||||
tolerance_is_costly: false
|
||||
|
@ -45,6 +48,10 @@ default: &defaults
|
|||
# Comment out this option to activate this restriction
|
||||
# stop_ordering_under: 75
|
||||
|
||||
# ordergroups can only order when their balance is higher than or equal to this
|
||||
# not fully enforced right now, since the check is only client-side
|
||||
# minimum_balance: 0
|
||||
|
||||
# email address to be used as sender
|
||||
email_sender: foodsoft@foodcoop.test
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ module Foodsoft
|
|||
|
||||
# Internationalization.
|
||||
config.i18n.load_path += Dir[Rails.root.join('config', 'locales', '**', '*.{rb,yml}')]
|
||||
config.i18n.default_locale = :de
|
||||
config.i18n.default_locale = :en
|
||||
|
||||
# Configure the default encoding used in templates for Ruby 1.9.
|
||||
config.encoding = "utf-8"
|
||||
|
|
|
@ -10,3 +10,10 @@ class String
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
class Array
|
||||
def cumulative_sum
|
||||
csum = 0
|
||||
self.map{|val| csum += val}
|
||||
end
|
||||
end
|
||||
|
|
|
@ -37,6 +37,17 @@ SimpleForm.setup do |config|
|
|||
end
|
||||
end
|
||||
|
||||
# Do not use the label in tables
|
||||
config.wrappers :intable, :tag => 'div', :class => 'control-group control-group-intable', :error_class => 'error' do |b|
|
||||
b.use :html5
|
||||
b.use :placeholder
|
||||
b.wrapper :tag => 'div', :class => 'controls controls-intable' do |ba|
|
||||
ba.use :input
|
||||
ba.use :error, :wrap_with => { :tag => 'span', :class => 'help-inline' }
|
||||
ba.use :hint, :wrap_with => { :tag => 'p', :class => 'help-block' }
|
||||
end
|
||||
end
|
||||
|
||||
# Wrappers for forms and inputs using the Twitter Bootstrap toolkit.
|
||||
# Check the Bootstrap docs (http://twitter.github.com/bootstrap)
|
||||
# to learn about the different styles for forms and inputs,
|
||||
|
|
|
@ -39,6 +39,8 @@ de:
|
|||
article_category: Kategorie
|
||||
availability: Artikel ist verfügbar?
|
||||
deposit: Pfand
|
||||
fc_price: Endpreis
|
||||
fc_share: FC-Aufschlag
|
||||
gross_price: Bruttopreis
|
||||
price: Nettopreis
|
||||
tax: MwSt
|
||||
|
@ -81,6 +83,11 @@ de:
|
|||
too_long: ist zu lang (nicht mehr als %{count} Zeichen)
|
||||
too_short: ist zu kurz (nicht weniger als %{count} Zeichen)
|
||||
wrong_length: hat die falsche Länge (muss genau %{count} Zeichen haben)
|
||||
models:
|
||||
task:
|
||||
attributes:
|
||||
done:
|
||||
exclusion: erledigte Aufgaben können nicht wöchentlich wiederholt werden
|
||||
template:
|
||||
body: ! 'Bitte überprüfen Sie die folgenden Felder:'
|
||||
header:
|
||||
|
@ -416,20 +423,28 @@ de:
|
|||
second: Sekunden
|
||||
year: Jahr
|
||||
deliveries:
|
||||
add_stock_change:
|
||||
how_many_units: Wie viele Einheiten (%{unit}) des Artikels »%{name}« liefern?
|
||||
create:
|
||||
notice: Lieferung wurde erstellt. Bitte nicht vergessen die Rechnung anzulegen!
|
||||
create_stock_article:
|
||||
notice: Neuer Lagerartikel »%{name}« gespeichert.
|
||||
destroy:
|
||||
notice: Lieferung wurde gelöscht.
|
||||
edit:
|
||||
title: Lieferung bearbeiten
|
||||
form:
|
||||
add_article: Lagerartikel der Lieferung hinzufügen
|
||||
new_article:
|
||||
search: Suche nach Artikeln aus dem <i>%{supplier}</i> Katalog
|
||||
title: Neuen Lagerartikel anlegen
|
||||
note_new_article: Ist ein Artikel noch nicht in der Lagerverwaltung, muss er erst %{new_link} werden.
|
||||
note_new_article_link: neu angelegt
|
||||
remove_article: Artikel aus Lieferung entfernen
|
||||
actions: Optionen
|
||||
article: Artikel
|
||||
category: Kategorie
|
||||
create_from_blank: Ohne Vorlage anlegen
|
||||
create_stock_article: Lagerartikel anlegen
|
||||
price: Nettopreis
|
||||
quantity: Menge
|
||||
title_fill_quantities: 2. Liefermenge angeben
|
||||
title_finish_delivery: 3. Lieferung abschließen
|
||||
title_select_stock_articles: 1. Lagerartikel auswählen
|
||||
unit: Einheit
|
||||
index:
|
||||
confirm_delete: Bist Du sicher?
|
||||
new_delivery: Neue Lieferung für %{supplier} anlegen
|
||||
|
@ -449,24 +464,34 @@ de:
|
|||
title: Lieferung anzeigen
|
||||
title_articles: Artikel
|
||||
unit: Einheit
|
||||
stock_change:
|
||||
stock_article_for_adding:
|
||||
action_add_to_delivery: Liefern
|
||||
action_edit: Bearbeiten
|
||||
action_other_price: Kopieren
|
||||
stock_article_form:
|
||||
copy_stock_article: Lagerartikel kopieren
|
||||
stock_change_fields:
|
||||
remove_article: Artikel aus Lieferung entfernen
|
||||
suppliers_overview: Lieferantenübersicht
|
||||
update:
|
||||
notice: Lieferung wurde aktualisiert.
|
||||
update_stock_article:
|
||||
notice: Lagerartikel »%{name}« aktualisiert.
|
||||
documents:
|
||||
order_by_articles:
|
||||
filename: Bestellung %{name}-%{date} - Artikelsortierung
|
||||
rows:
|
||||
- Bestellgruppe
|
||||
- Menge
|
||||
- Bestellt
|
||||
- Bekommen
|
||||
- Preis
|
||||
title: ! 'Artikelsortierung der Bestellung: %{name}, beendet am %{date}'
|
||||
order_by_groups:
|
||||
filename: Bestellung %{name}-%{date} - Gruppensortierung
|
||||
rows:
|
||||
- Artikel
|
||||
- Menge
|
||||
- Bestellt
|
||||
- Bekommen
|
||||
- Preis
|
||||
- GebGr
|
||||
- Einheit
|
||||
|
@ -482,6 +507,8 @@ de:
|
|||
- Gebinde
|
||||
- Einheit
|
||||
- Preis/Einheit
|
||||
- Summe
|
||||
total: Gesamtpreis
|
||||
order_matrix:
|
||||
filename: Bestellung %{name}-%{date} - Sortiermatrix
|
||||
heading: Artikelübersicht
|
||||
|
@ -696,6 +723,7 @@ de:
|
|||
ordergroups:
|
||||
account_balance: Kontostand
|
||||
account_statement: Kontoauszug
|
||||
contact: Kontakt
|
||||
name: Name
|
||||
new_transaction: Neue Transaktion
|
||||
update:
|
||||
|
@ -1146,6 +1174,8 @@ de:
|
|||
subject: ! 'Betreff:'
|
||||
title: Nachricht anzeigen
|
||||
model:
|
||||
delivery:
|
||||
each_stock_article_must_be_unique: Lieferung darf jeden Lagerartikel höchstens einmal auflisten.
|
||||
membership:
|
||||
no_admin_delete: Mitgliedschaft kann nicht beendet werden. Du bist die letzte Administratorin
|
||||
order_article:
|
||||
|
@ -1154,14 +1184,6 @@ de:
|
|||
redirect: Weiterleiting auf [[%{title}]]...
|
||||
user:
|
||||
no_ordergroup: keine Bestellgruppe
|
||||
notify:
|
||||
email_is_public: E-Mail ist für Mitglieder sichtbar
|
||||
name_is_public: Name ist für Mitglieder sichtbar
|
||||
negative_balance: Informiere mich, falls meine Bestellgruppe ins Minus rutscht.
|
||||
order_finished: Informier mich über meine Bestellergebnisse (nach Ende der Bestellung).
|
||||
phone_is_public: Telefon ist für Mitglieder sichtbar
|
||||
send_as_email: Bekomme Nachrichten als Emails.
|
||||
upcoming_tasks: Erinnere mich an anstehende Aufgaben.
|
||||
navigation:
|
||||
admin:
|
||||
home: Übersicht
|
||||
|
@ -1423,7 +1445,7 @@ de:
|
|||
sessions:
|
||||
logged_in: Angemeldet!
|
||||
logged_out: Abgemeldet!
|
||||
login_invalid:
|
||||
login_invalid: Ungültiger Benutzername oder Passwort
|
||||
new:
|
||||
forgot_password: Passwort vergessen?
|
||||
login: Anmelden
|
||||
|
@ -1509,6 +1531,10 @@ de:
|
|||
units_to_order: Anzahl gelieferter Gebinde
|
||||
update_current_price: Ändert auch den Preis für aktuelle Bestellungen
|
||||
stock_article:
|
||||
copy_stock_article:
|
||||
name: Bitte ändern
|
||||
edit_stock_article:
|
||||
price: <ul><li>Preisänderung gesperrt.</li><li>Bei Bedarf %{stock_article_copy_link}.</li></ul>
|
||||
supplier:
|
||||
supplier:
|
||||
min_order_quantity: Die Mindestbestellmenge wird während der Bestellung angezeigt und soll motivieren
|
||||
|
@ -1581,9 +1607,25 @@ de:
|
|||
contact_person: Kontaktperson
|
||||
contact_phone: Telefon
|
||||
ignore_apple_restriction: Bestellstop bei zu wenig Äpfeln ignorieren
|
||||
name: Name
|
||||
page:
|
||||
body: Inhalt
|
||||
parent_id: Oberseite
|
||||
settings:
|
||||
messages:
|
||||
send_as_email: Bekomme Nachrichten als Emails.
|
||||
notify:
|
||||
negative_balance: Informiere mich, falls meine Bestellgruppe ins Minus rutscht.
|
||||
order_finished: Informier mich über meine Bestellergebnisse (nach Ende der Bestellung).
|
||||
upcoming_tasks: Erinnere mich an anstehende Aufgaben.
|
||||
profile:
|
||||
email_is_public: E-Mail ist für Mitglieder sichtbar.
|
||||
language: Sprache
|
||||
name_is_public: Name ist für Mitglieder sichtbar.
|
||||
phone_is_public: Telefon ist für Mitglieder sichtbar.
|
||||
settings_group:
|
||||
messages: Nachrichten
|
||||
privacy: Privatsphäre
|
||||
stock_article:
|
||||
supplier: Lieferant
|
||||
supplier:
|
||||
|
@ -1626,13 +1668,15 @@ de:
|
|||
role_finance: Finanzen
|
||||
role_orders: Bestellverwaltung
|
||||
role_suppliers: Lieferanten
|
||||
task_description: Beschreibung
|
||||
task_duration: Vor. Dauer in Stunden
|
||||
task_name: Name für Job
|
||||
task_required_users: Benötige Verantwortliche
|
||||
weekday: Wochentag
|
||||
weekly_task: Monatlichen Job definieren?
|
||||
'no': Nein
|
||||
options:
|
||||
settings:
|
||||
profile:
|
||||
language:
|
||||
de: Deutsch
|
||||
en: English
|
||||
fr: Französisch
|
||||
nl: Niederländisch
|
||||
required:
|
||||
mark: ! '*'
|
||||
text: benötigt
|
||||
|
@ -1677,6 +1721,15 @@ de:
|
|||
title: Lagerartikel bearbeiten
|
||||
form:
|
||||
price_hint: Um Chaos zu vermeiden können bis auf weiteres die Preise von angelegten Lagerartikeln nicht mehr verändert werden.
|
||||
history:
|
||||
change_quantity: Veränderung
|
||||
datetime: Zeitpunkt
|
||||
delivery: Lieferung
|
||||
new_quantity: Neuer Bestand
|
||||
order: Bestellung
|
||||
reason: Ereignis
|
||||
stock_changes: Verlauf anzeigen für »%{article_name}«
|
||||
stock_taking: Inventur
|
||||
index:
|
||||
article:
|
||||
article: Artikel
|
||||
|
@ -1696,6 +1749,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:
|
||||
|
@ -1726,6 +1780,7 @@ de:
|
|||
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>
|
||||
subscribe: abonnieren
|
||||
subscribe_again: erneut abonnieren
|
||||
supplier: Lieferantin
|
||||
title: Externe Listen
|
||||
show:
|
||||
|
@ -1756,12 +1811,15 @@ de:
|
|||
notice: Aufgabe wurde gelöscht
|
||||
edit:
|
||||
title: Aufgabe bearbeiten
|
||||
warning_periodic: <strong>Warnung:</strong> Diese Aufgabe ist Teil einer Gruppe von <em>wöchentlichen Aufgaben</em>. Beim Speichern wird sie aus der Gruppe ausgeschlossen und in eine <em>gewöhnliche Aufgabe</em> umgewandelt.
|
||||
error_not_found: Keine Arbeitsgruppe gefunden
|
||||
form:
|
||||
search:
|
||||
hint: Nach Nutzerin suchen
|
||||
noresult: Keine Nutzerin gefunden
|
||||
placeholder: Suche ...
|
||||
submit:
|
||||
periodic: Wöchentliche Aufgabe speichern
|
||||
index:
|
||||
show_group_tasks: Gruppenaufgaben anzeigen
|
||||
title: Aufgaben
|
||||
|
@ -1783,12 +1841,16 @@ de:
|
|||
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
|
||||
set_done:
|
||||
notice: Aufgabenstatus wurde aktualisiert
|
||||
show:
|
||||
accept_task: Aufgabe übernehmen
|
||||
confirm_delete_group: Diese und alle folgenden wöchentlichen Aufgaben wirklich löschen?
|
||||
delete_group: Aufgabe und folgende löschen
|
||||
due_date: Fälligkeitsdatum
|
||||
hours: ! '%{count}h'
|
||||
mark_done: Als erledigt markieren
|
||||
|
@ -1796,6 +1858,7 @@ de:
|
|||
title: Aufgabe anzeigen
|
||||
update:
|
||||
notice: Aufgabe wurde aktualisiert
|
||||
notice_converted: Aufgabe wurde aktualisiert und in eine gewöhnliche Aufgabe umgewandelt
|
||||
user:
|
||||
more: Nichts zu tun? %{tasks_link} gibt es bestimmt Arbeit
|
||||
tasks_link: Hier
|
||||
|
@ -1805,11 +1868,6 @@ de:
|
|||
workgroup:
|
||||
title: Aufgaben für %{workgroup}
|
||||
title_all: Alle Aufgaben der Gruppe
|
||||
weekly:
|
||||
desc: ! '<p>Jeden <b>%{weekday}</b> hat diese Arbeitsgruppe folgenden Job: <b>%{task}</b></p> <p>Die Wochenaufgaben werden von der Foodsoft automatisch erstellt. Eintragen müsst Ihr Euch aber selber.</p>'
|
||||
edit: Wöchentliche Aufgaben anpassen
|
||||
empty: Noch keine Wochenaufgaben angelegt.
|
||||
title: Wöchentliche Aufgaben
|
||||
time:
|
||||
am: vormittags
|
||||
formats:
|
||||
|
@ -1821,9 +1879,12 @@ de:
|
|||
close: Schließen
|
||||
delete: Löschen
|
||||
edit: Bearbeiten
|
||||
history: Verlauf anzeigen
|
||||
marks:
|
||||
close: ! '×'
|
||||
success: <i class="icon icon-ok"></i>
|
||||
or_cancel: oder abbrechen
|
||||
please_wait: Bitte warten...
|
||||
save: Speichern
|
||||
show: Anzeigen
|
||||
views:
|
||||
|
|
|
@ -39,6 +39,8 @@ en:
|
|||
article_category: article category
|
||||
availability: Is article available?
|
||||
deposit: deposit
|
||||
fc_price: FC price
|
||||
fc_share: FC share
|
||||
gross_price: gross price
|
||||
price: price
|
||||
tax: VAT
|
||||
|
@ -81,6 +83,11 @@ en:
|
|||
too_long: is too long (no more than %{count} characters)
|
||||
too_short: is too short (use more than %{count} characters)
|
||||
wrong_length: is the wrong length (has to have exactly %{count} characters)
|
||||
models:
|
||||
task:
|
||||
attributes:
|
||||
done:
|
||||
exclusion: finished tasks may not be repeated weekly
|
||||
template:
|
||||
body: ! 'Please check the following fields:'
|
||||
header:
|
||||
|
@ -229,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
|
||||
|
@ -307,7 +314,7 @@ en:
|
|||
title: Synchronize articles with external database
|
||||
unit_quantity_short: unit quantity
|
||||
update:
|
||||
body: ! '<p><i>Every article is shown twice. The old values are gray and contain the current values.</i></p>
|
||||
body: ! '<p><i>Every article is shown twice. The old values are gray and the text fields contain the current values.</i></p>
|
||||
|
||||
<p><i>Differences with the old articles are marked yellow.</i></p>'
|
||||
title: Update ...
|
||||
|
@ -418,20 +425,28 @@ en:
|
|||
second: seconds
|
||||
year: years
|
||||
deliveries:
|
||||
add_stock_change:
|
||||
how_many_units: ! 'How many units (%{unit}) to deliver? Stock article name: %{name}.'
|
||||
create:
|
||||
notice: Delivery was created. Please don’t forget to create invoice!
|
||||
create_stock_article:
|
||||
notice: The new stock article »%{name}« was saved.
|
||||
destroy:
|
||||
notice: Delivery was deleted.
|
||||
edit:
|
||||
title: Edit suppliers
|
||||
title: Edit delivery
|
||||
form:
|
||||
add_article: Add stock article to delivery
|
||||
new_article:
|
||||
search: Search for articles in the <i>%{supplier}</i> catalogue
|
||||
title: Create new stock article
|
||||
note_new_article: When an article is not yet in the inventory, you have to %{new_link} it first.
|
||||
note_new_article_link: create
|
||||
remove_article: Remove article from delivery
|
||||
actions: Tasks
|
||||
article: Article
|
||||
category: Category
|
||||
create_from_blank: Create new article
|
||||
create_stock_article: Create stock article
|
||||
price: Netprice
|
||||
quantity: Quantity
|
||||
title_fill_quantities: 2. Set delivery quantities
|
||||
title_finish_delivery: 3. Finish delivery
|
||||
title_select_stock_articles: 1. Select stock articles
|
||||
unit: Unit
|
||||
index:
|
||||
confirm_delete: Are you sure?
|
||||
new_delivery: ! 'Create new delivery for %{supplier} '
|
||||
|
@ -451,26 +466,36 @@ en:
|
|||
title: Show delivery
|
||||
title_articles: Article
|
||||
unit: Unit
|
||||
stock_change:
|
||||
remove_article: Remove articles from delivery
|
||||
stock_article_for_adding:
|
||||
action_add_to_delivery: Add to delivery
|
||||
action_edit: Edit
|
||||
action_other_price: Copy
|
||||
stock_article_form:
|
||||
copy_stock_article: Copy stock article
|
||||
stock_change_fields:
|
||||
remove_article: Remove article from delivery
|
||||
suppliers_overview: Supplier overview
|
||||
update:
|
||||
notice: Delivery was updated.
|
||||
update_stock_article:
|
||||
notice: The stock article »%{name}« was updated.
|
||||
documents:
|
||||
order_by_articles:
|
||||
filename: Order %{name}-%{date} - by articles
|
||||
rows:
|
||||
- Order group
|
||||
- Amount
|
||||
- Ordered
|
||||
- Received
|
||||
- Price
|
||||
title: ! 'Order sorted by articles: %{name}, closed at %{date}'
|
||||
order_by_groups:
|
||||
filename: Order %{name}-%{date} - by group
|
||||
rows:
|
||||
- Article
|
||||
- Amount
|
||||
- Ordered
|
||||
- Received
|
||||
- Price
|
||||
- Unit Quantity
|
||||
- Unit quantity
|
||||
- Unit
|
||||
- Sum
|
||||
sum: Sum
|
||||
|
@ -481,20 +506,24 @@ 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}'
|
||||
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.
|
||||
|
@ -698,6 +727,7 @@ en:
|
|||
ordergroups:
|
||||
account_balance: Account balance
|
||||
account_statement: Account statement
|
||||
contact: Contact
|
||||
name: Name
|
||||
new_transaction: New transaction
|
||||
update:
|
||||
|
@ -1148,6 +1178,8 @@ en:
|
|||
subject: ! 'Subject:'
|
||||
title: Show message
|
||||
model:
|
||||
delivery:
|
||||
each_stock_article_must_be_unique: Each stock article must not be listed more than once.
|
||||
membership:
|
||||
no_admin_delete: Membership can not be withdrawn as you are the last administrator.
|
||||
order_article:
|
||||
|
@ -1156,14 +1188,6 @@ en:
|
|||
redirect: Redirect to [[%{title}]]...
|
||||
user:
|
||||
no_ordergroup: no order group
|
||||
notify:
|
||||
email_is_public: Email is visible for other members.
|
||||
name_is_public: Name is visible for other members.
|
||||
negative_balance: inform me when by order group has a negative balance.
|
||||
order_finished: Inform me about my order result (when the order is closed).
|
||||
phone_is_public: Phone number is visible for other members.
|
||||
send_as_email: Receive messages as emails.
|
||||
upcoming_tasks: Remind me of upcoming tasks.
|
||||
navigation:
|
||||
admin:
|
||||
home: Overview
|
||||
|
@ -1435,10 +1459,15 @@ en:
|
|||
title: Foodsoft login
|
||||
user: User
|
||||
shared:
|
||||
articles:
|
||||
ordered: Ordered
|
||||
ordered_desc: Number of articles as ordered by member (amount + tolerance)
|
||||
received: Received
|
||||
received_desc: Number of articles that (will be) received by member
|
||||
articles_by_articles:
|
||||
ordered: Ordered (Amount + Tolerance)
|
||||
ordergroup: Ordergroup
|
||||
price: Total price
|
||||
ordered: Ordered (Amount + Tolerance)
|
||||
received: Received
|
||||
articles_by_groups:
|
||||
fc_price: FC-Price
|
||||
|
@ -1511,6 +1540,10 @@ en:
|
|||
units_to_order: Amount of delivered units
|
||||
update_current_price: Also update the price of the current order
|
||||
stock_article:
|
||||
copy_stock_article:
|
||||
name: Please modify
|
||||
edit_stock_article:
|
||||
price: <ul><li>Price changes are forbidden.</li><li>If necessary, %{stock_article_copy_link}.</li></ul>
|
||||
supplier:
|
||||
supplier:
|
||||
min_order_quantity: The minimum amount which has to be orderd will be shown during the order process and should motivate ordering
|
||||
|
@ -1583,9 +1616,25 @@ 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
|
||||
settings:
|
||||
messages:
|
||||
send_as_email: Receive messages as emails.
|
||||
notify:
|
||||
negative_balance: Inform me when my order group has a negative balance.
|
||||
order_finished: Inform me about my order result (when the order is closed).
|
||||
upcoming_tasks: Remind me of upcoming tasks.
|
||||
profile:
|
||||
email_is_public: Email is visible for other members.
|
||||
language: Language
|
||||
name_is_public: Name is visible for other members.
|
||||
phone_is_public: Phone number is visible for other members.
|
||||
settings_group:
|
||||
messages: Messages
|
||||
privacy: Privacy
|
||||
stock_article:
|
||||
supplier: Supplier
|
||||
supplier:
|
||||
|
@ -1628,13 +1677,15 @@ en:
|
|||
role_finance: Finances
|
||||
role_orders: Order management
|
||||
role_suppliers: Suppliers
|
||||
task_description: Description
|
||||
task_duration: Duration in hours
|
||||
task_name: Task name
|
||||
task_required_users: People required
|
||||
weekday: Weekday
|
||||
weekly_task: Define monthly task?
|
||||
'no': 'No'
|
||||
options:
|
||||
settings:
|
||||
profile:
|
||||
language:
|
||||
de: German
|
||||
en: English
|
||||
fr: French
|
||||
nl: Dutch
|
||||
required:
|
||||
mark: ! '*'
|
||||
text: required
|
||||
|
@ -1679,6 +1730,15 @@ en:
|
|||
title: Edit stock articles
|
||||
form:
|
||||
price_hint: To avoid choas, it is not possible to edit the prices of already added stock articles until further notice.
|
||||
history:
|
||||
change_quantity: Change
|
||||
datetime: Time
|
||||
delivery: Delivery
|
||||
new_quantity: New quantity
|
||||
order: Order
|
||||
reason: Reason
|
||||
stock_changes: Stock quantity changes of ‘%{article_name}’
|
||||
stock_taking: Inventory
|
||||
index:
|
||||
article:
|
||||
article: Article
|
||||
|
@ -1698,6 +1758,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:
|
||||
|
@ -1728,6 +1789,7 @@ en:
|
|||
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>
|
||||
subscribe: Subscribe
|
||||
subscribe_again: Subscribe again
|
||||
supplier: Supplier
|
||||
title: External lists
|
||||
show:
|
||||
|
@ -1758,12 +1820,15 @@ en:
|
|||
notice: Task has been deleted
|
||||
edit:
|
||||
title: Edit task
|
||||
warning_periodic: <strong>Warning:</strong> This task is part of a group of <em>weekly tasks</em>. When saving it will be excluded from the group and it will be converted to a <em>regular task</em>.
|
||||
error_not_found: No workgroup found
|
||||
form:
|
||||
search:
|
||||
hint: Search for user
|
||||
noresult: No user found
|
||||
placeholder: Search ...
|
||||
submit:
|
||||
periodic: Save weekly task
|
||||
index:
|
||||
show_group_tasks: Show group tasks
|
||||
title: Tasks
|
||||
|
@ -1785,12 +1850,16 @@ 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
|
||||
set_done:
|
||||
notice: The state of the task has been updated
|
||||
show:
|
||||
accept_task: Accept task
|
||||
confirm_delete_group: Really delete this and all subsequent tasks?
|
||||
delete_group: Delete task and subsequent
|
||||
due_date: Due date
|
||||
hours: ! '%{count}h'
|
||||
mark_done: Mark task as done
|
||||
|
@ -1798,6 +1867,7 @@ en:
|
|||
title: Show task
|
||||
update:
|
||||
notice: Task has been updated
|
||||
notice_converted: Task has been updated and was converted to a regular task
|
||||
user:
|
||||
more: Nothing to do? %{tasks_link} are tasks for sure.
|
||||
tasks_link: Here
|
||||
|
@ -1807,11 +1877,6 @@ en:
|
|||
workgroup:
|
||||
title: Tasks for %{workgroup}
|
||||
title_all: All group tasks
|
||||
weekly:
|
||||
desc: ! '<p>Every <b>%{weekday}</b> this workgroup has the following job: <b>%{task}</b></p> <p>The weektask has been created by Foodsoft automatically. You still have to sign up for it yourself.</p>'
|
||||
edit: Edit weekly tasks
|
||||
empty: No weekly tasks created yet.
|
||||
title: Weekly tasks
|
||||
time:
|
||||
am: morning
|
||||
formats:
|
||||
|
@ -1823,9 +1888,12 @@ en:
|
|||
close: Close
|
||||
delete: Delete
|
||||
edit: Edit
|
||||
history: Show history
|
||||
marks:
|
||||
close: ! '×'
|
||||
success: <i class="icon icon-ok"></i>
|
||||
or_cancel: or cancel
|
||||
please_wait: Please wait...
|
||||
save: Save
|
||||
show: Show
|
||||
views:
|
||||
|
|
1919
config/locales/fr.yml
Normal file
1919
config/locales/fr.yml
Normal file
File diff suppressed because it is too large
Load diff
|
@ -39,6 +39,8 @@ nl:
|
|||
article_category: categorie
|
||||
availability: Artikel leverbaar?
|
||||
deposit: statiegeld
|
||||
fc_price: prijs foodcoop
|
||||
fc_share: marge foodcoop
|
||||
gross_price: bruto prijs
|
||||
price: netto prijs
|
||||
tax: BTW
|
||||
|
@ -81,6 +83,11 @@ nl:
|
|||
too_long: is te lang (niet meer dan %{count} tekens)
|
||||
too_short: is te kort (niet minder dan %{count} tekens)
|
||||
wrong_length: heeft de verkeerde lengte (moet precies %{count} tekens zijn)
|
||||
models:
|
||||
task:
|
||||
attributes:
|
||||
done:
|
||||
exclusion: gedane taken kunnen niet herhaald worden
|
||||
template:
|
||||
body: ! 'Controleer de volgende velden:'
|
||||
header:
|
||||
|
@ -138,7 +145,7 @@ nl:
|
|||
first_paragraph: Hier kun je %{url} toevoegen, bewerken en verwijderen.
|
||||
new_ordergroup: Nieuw huishouden toevoegen
|
||||
new_ordergroups: nieuwe huishoudens
|
||||
second_paragraph:
|
||||
second_paragraph: ! 'Bedenk het <em>onderscheid tussen werkgroep en huishouden</em>: een huishouden heeft een rekening en kan bestellen. in een <em>%{url}</em> (bijv. sorteergroep) werken leden samen om taken te vervullen. Leden kunnen slechts lid zijn van éen huishouden, maar van meerdere werkgroepen.'
|
||||
title: Huishoudens
|
||||
workgroup: werkgroep
|
||||
new:
|
||||
|
@ -256,7 +263,7 @@ nl:
|
|||
notice: Alle artikelen en prijzen zijn bijgewerkt.
|
||||
destroy_active_article:
|
||||
drop: verwijderen
|
||||
note:
|
||||
note: ! '%{article} is deel van een lopende bestelling en kan niet verwijderd worden. Het artikel graag eerst uit de bestelling(en) %{drop_link}.'
|
||||
edit_all:
|
||||
note: ! 'Verplichte velden zijn: Naam, eenheid, (netto) prijs en bestellingsnummer.'
|
||||
submit: Alle artikelen bijwerken
|
||||
|
@ -265,10 +272,10 @@ nl:
|
|||
edit_all_table:
|
||||
available_desc: beschikbaar
|
||||
available_short: besch.
|
||||
order_number_desc: bestelnummer
|
||||
order_number_short: best.nr.
|
||||
price_desc: netto prijs
|
||||
price_short: prijs
|
||||
order_number_desc: Bestelnummer
|
||||
order_number_short: Best.nr.
|
||||
price_desc: Netto prijs
|
||||
price_short: Prijs
|
||||
unit_quantity_desc: Groothandelsverpakkingsgrootte
|
||||
unit_quantity_short: Gr.Eenh.
|
||||
form:
|
||||
|
@ -305,11 +312,13 @@ nl:
|
|||
price_short: prijs
|
||||
submit: Alle wissen/bijwerken
|
||||
title: Artikelen met externe database synchroniseren
|
||||
unit_quantity_short:
|
||||
unit_quantity_short: Gr.Eenh.
|
||||
update:
|
||||
body:
|
||||
title:
|
||||
update_msg:
|
||||
body: ! '<p><i>Ieder artikel wordt tweemaal getoond. De oude waarden zijn grijs, en de tekstvelden bevatten de huidige waarden.</i></p>
|
||||
|
||||
<p><i>Verschillen met de oude artikelen zijn geel gemarkeerd.</i></p>'
|
||||
title: Bijwerken ...
|
||||
update_msg: ! 'De volgende artikelen moeten bijgewerkt worden: '
|
||||
upload:
|
||||
body:
|
||||
fields:
|
||||
|
@ -416,20 +425,28 @@ nl:
|
|||
second: seconden
|
||||
year: jaren
|
||||
deliveries:
|
||||
add_stock_change:
|
||||
how_many_units:
|
||||
create:
|
||||
notice:
|
||||
create_stock_article:
|
||||
notice:
|
||||
destroy:
|
||||
notice:
|
||||
edit:
|
||||
title:
|
||||
form:
|
||||
add_article:
|
||||
new_article:
|
||||
search:
|
||||
title:
|
||||
note_new_article:
|
||||
note_new_article_link:
|
||||
remove_article:
|
||||
actions:
|
||||
article:
|
||||
category:
|
||||
create_from_blank:
|
||||
create_stock_article:
|
||||
price:
|
||||
quantity:
|
||||
title_fill_quantities:
|
||||
title_finish_delivery:
|
||||
title_select_stock_articles:
|
||||
unit:
|
||||
index:
|
||||
confirm_delete:
|
||||
new_delivery:
|
||||
|
@ -449,66 +466,99 @@ nl:
|
|||
title:
|
||||
title_articles:
|
||||
unit:
|
||||
stock_change:
|
||||
stock_article_for_adding:
|
||||
action_add_to_delivery:
|
||||
action_edit:
|
||||
action_other_price:
|
||||
stock_article_form:
|
||||
copy_stock_article:
|
||||
stock_change_fields:
|
||||
remove_article:
|
||||
suppliers_overview:
|
||||
update:
|
||||
notice:
|
||||
update_stock_article:
|
||||
notice:
|
||||
documents:
|
||||
order_by_articles:
|
||||
filename:
|
||||
filename: Bestelling %{name}-%{date} - Artikellijst
|
||||
rows:
|
||||
title:
|
||||
- Huishouden
|
||||
- Hoeveelheid
|
||||
- Prijs
|
||||
title: ! 'Artikellijst van bestelling: %{name}, gesloten op %{date}'
|
||||
order_by_groups:
|
||||
filename:
|
||||
filename: Bestelling %{name}-%{date} - Huishoudenslijst
|
||||
rows:
|
||||
sum:
|
||||
title:
|
||||
- Artikel
|
||||
- Hoeveelheid
|
||||
- Prijs
|
||||
- Gr.Eenh.
|
||||
- Eenheid
|
||||
- Som
|
||||
sum: Som
|
||||
title: ! 'Huishoudenslijst van bestelling: %{name}, gesloten op %{date}'
|
||||
order_fax:
|
||||
filename:
|
||||
filename: Bestelling %{name}-%{date} - Fax
|
||||
rows:
|
||||
total: Totaal
|
||||
order_matrix:
|
||||
filename:
|
||||
heading:
|
||||
filename: Bestelling %{name}-%{date} - Sorteermatrix
|
||||
heading: Artikeloverzicht
|
||||
rows:
|
||||
title:
|
||||
- Artikel
|
||||
- Eenheid
|
||||
- Gr.Eenh.
|
||||
- Foodcoop-prijs
|
||||
- Aantal
|
||||
title: ! 'Sorteermatrix van bestelling: %{name}, gesloten op %{date}'
|
||||
total:
|
||||
one: In totaal éen artikel
|
||||
other: In totaal %{count} artikelen
|
||||
errors:
|
||||
format:
|
||||
general:
|
||||
general_again:
|
||||
general_msg:
|
||||
format: ! '%{attribute} %{message}'
|
||||
general: Er is een probleem opgetreden.
|
||||
general_again: Er is een fout opgetreden. Probeer het opnieuw.
|
||||
general_msg: ! 'Er is een probleem opgetreden: %{msg}'
|
||||
messages:
|
||||
accepted:
|
||||
blank:
|
||||
confirmation:
|
||||
empty:
|
||||
equal_to:
|
||||
even:
|
||||
exclusion:
|
||||
greater_than:
|
||||
greater_than_or_equal_to:
|
||||
inclusion:
|
||||
invalid:
|
||||
less_than:
|
||||
less_than_or_equal_to:
|
||||
not_a_number:
|
||||
not_an_integer:
|
||||
odd:
|
||||
accepted: moet geaccepteerd worden
|
||||
blank: moet ingevuld worden
|
||||
confirmation: komt niet overeen met de bevestiging
|
||||
empty: moet ingevuld worden
|
||||
equal_to: moet precies %{count} zijn
|
||||
even: moet even zijn
|
||||
exclusion: moet even zijn
|
||||
greater_than: moet groter dan %{count} zijn
|
||||
greater_than_or_equal_to: moet groter dan of gelijk zijn aan %{count}
|
||||
inclusion: geen geldige waarde
|
||||
invalid: is ongeldig
|
||||
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:
|
||||
one: is te lang (niet meer dan éen teken)
|
||||
other: is te lang (niet meer dan %{count} tekens)
|
||||
too_short:
|
||||
one: is te kort (niet minder dan éen teken)
|
||||
other: is te kort (niet minder dan %{count} tekens)
|
||||
wrong_length:
|
||||
one: heeft de verkeerde lengte (moet precies éen zijn)
|
||||
other: heeft de verkeerde lengte (moet precies %{count} tekens hebben)
|
||||
template:
|
||||
body:
|
||||
body: ! 'Controleer alsjeblieft de volgende velden:'
|
||||
header:
|
||||
one: ! 'Kon %{model} niet opslaan: éen fout gevonden.'
|
||||
other: ! 'Kon %{model} niet opslaan: %{count} fouten gevonden.'
|
||||
feedback:
|
||||
create:
|
||||
notice:
|
||||
notice: Bericht verstuurd. Vriendelijk bedankt!
|
||||
new:
|
||||
first_paragraph:
|
||||
first_paragraph: Probleem gevonden? Voorstel? Idee? Verbeterpunt? We horen graag je feedback.
|
||||
second_paragraph:
|
||||
send:
|
||||
title:
|
||||
|
@ -542,7 +592,7 @@ nl:
|
|||
total_fc: Som (FC-prijs)
|
||||
units: Eenheden
|
||||
index:
|
||||
title: Gesloten orders
|
||||
title: Gesloten bestellingen
|
||||
invoice:
|
||||
edit: Factuur bewerken
|
||||
invoice_amount: ! 'Factuurbedrag:'
|
||||
|
@ -573,8 +623,8 @@ nl:
|
|||
orders:
|
||||
clear: afrekenen
|
||||
cleared: afgerekend (%{amount})
|
||||
close: direct afsluiten
|
||||
confirm: Weet je zeker dat de je bestelling wilt afsluiten?
|
||||
close: direct afrekenen
|
||||
confirm: Weet je zeker dat de je bestelling wilt afrekenen?
|
||||
end: Einde
|
||||
ended: gesloten
|
||||
last_edited_by: Laatst aangepast door
|
||||
|
@ -673,7 +723,8 @@ nl:
|
|||
title: Tegoeden beheren
|
||||
ordergroups:
|
||||
account_balance: Tegoed
|
||||
account_statement:
|
||||
account_statement: Rekeningafschrift
|
||||
contact:
|
||||
name: Naam
|
||||
new_transaction: Nieuwe transactie
|
||||
update:
|
||||
|
@ -681,31 +732,31 @@ nl:
|
|||
foodcoop:
|
||||
ordergroups:
|
||||
index:
|
||||
name:
|
||||
only_active:
|
||||
only_active_desc:
|
||||
title:
|
||||
name: Naam ...
|
||||
only_active: Alleen actieve
|
||||
only_active_desc: (minstens eenmaal in de laatste 3 maanden besteld)
|
||||
title: Huishoudens
|
||||
ordergroups:
|
||||
last_ordered:
|
||||
name:
|
||||
user:
|
||||
last_ordered: laatste besteld
|
||||
name: Naam
|
||||
user: Leden
|
||||
users:
|
||||
index:
|
||||
body:
|
||||
ph_name:
|
||||
ph_ordergroup:
|
||||
profile_link:
|
||||
title:
|
||||
body: <p>Hier kun je leden van deze foodcoop een bericht sturen.</p> <p>Om je eigen contactgegevens te laten zien, moet je die vrijgeven op %{profile_link}.</p>
|
||||
ph_name: Naam ...
|
||||
ph_ordergroup: Huishouden ...
|
||||
profile_link: Instellingen
|
||||
title: Leden
|
||||
workgroups:
|
||||
edit:
|
||||
invite_link:
|
||||
invite_new:
|
||||
title:
|
||||
invite_link: hier
|
||||
invite_new: Nieuwe leden kun je %{invite_link} uitnodigen.
|
||||
title: Groep bewerken
|
||||
index:
|
||||
body:
|
||||
title:
|
||||
body: <p>De groep kan alleen aangepast worden door leden ervan.<br/> Als je lid wilt worden van een groep, stuur dan een bericht aan een van de leden.</p>
|
||||
title: Werkgroepen
|
||||
workgroup:
|
||||
edit:
|
||||
edit: Groep bewerken
|
||||
show_tasks:
|
||||
group_orders:
|
||||
archive:
|
||||
|
@ -755,9 +806,9 @@ nl:
|
|||
title: Afgerekende bestellingen
|
||||
finished_orders:
|
||||
title: Niet afgerekende bestellingen
|
||||
total_sum:
|
||||
total_sum: Totaal
|
||||
funds:
|
||||
account_balance:
|
||||
account_balance: Tegoed
|
||||
available_funds:
|
||||
finished_orders: niet afgerekende bestellingen
|
||||
open_orders: Lopende bestellingen
|
||||
|
@ -853,12 +904,12 @@ nl:
|
|||
last_update:
|
||||
title:
|
||||
transactions:
|
||||
amount:
|
||||
note:
|
||||
title:
|
||||
view:
|
||||
when:
|
||||
where:
|
||||
amount: Bedrag
|
||||
note: Notitie
|
||||
title: Laatste transacties
|
||||
view: Rekeningafschrift tonen
|
||||
when: Wanneer
|
||||
where: Wie
|
||||
ordergroup:
|
||||
title:
|
||||
tasks_move:
|
||||
|
@ -894,7 +945,7 @@ nl:
|
|||
start_nav:
|
||||
admin:
|
||||
finances:
|
||||
accounts:
|
||||
accounts: Tegoeden bijwerken
|
||||
settle:
|
||||
title: Financiën
|
||||
foodcoop: Foodcoop
|
||||
|
@ -1039,6 +1090,8 @@ nl:
|
|||
subject:
|
||||
title:
|
||||
model:
|
||||
delivery:
|
||||
each_stock_article_must_be_unique:
|
||||
membership:
|
||||
no_admin_delete:
|
||||
order_article:
|
||||
|
@ -1047,14 +1100,6 @@ nl:
|
|||
redirect:
|
||||
user:
|
||||
no_ordergroup:
|
||||
notify:
|
||||
email_is_public:
|
||||
name_is_public:
|
||||
negative_balance:
|
||||
order_finished: Informeer me over mijn bestelresultaat (wanneer de bestelling gesloten wordt).
|
||||
phone_is_public:
|
||||
send_as_email:
|
||||
upcoming_tasks:
|
||||
navigation:
|
||||
admin:
|
||||
home: Overzicht
|
||||
|
@ -1092,7 +1137,7 @@ nl:
|
|||
number:
|
||||
currency:
|
||||
format:
|
||||
delimiter: ! ','
|
||||
delimiter: ! ' '
|
||||
format: ! '%n %u'
|
||||
precision: 2
|
||||
separator: ! ','
|
||||
|
@ -1400,6 +1445,10 @@ nl:
|
|||
units_to_order:
|
||||
update_current_price:
|
||||
stock_article:
|
||||
copy_stock_article:
|
||||
name:
|
||||
edit_stock_article:
|
||||
price:
|
||||
supplier:
|
||||
supplier:
|
||||
min_order_quantity:
|
||||
|
@ -1425,7 +1474,7 @@ nl:
|
|||
description: Omschrijving
|
||||
email: Email
|
||||
note: Notitie
|
||||
order_number: Order nummer
|
||||
order_number: Bestelnummer
|
||||
ordergroup: Huishouden
|
||||
password: Wachtwoord
|
||||
password_confirmation: Wachtwoord herhalen
|
||||
|
@ -1450,7 +1499,7 @@ nl:
|
|||
note: Notitie
|
||||
number: Nummer
|
||||
order: Bestelling
|
||||
paid_on: Betaalt op
|
||||
paid_on: Betaald op
|
||||
supplier: Leverancier
|
||||
message:
|
||||
body:
|
||||
|
@ -1472,9 +1521,25 @@ nl:
|
|||
contact_person: Contactpersoon
|
||||
contact_phone: Telefoon
|
||||
ignore_apple_restriction:
|
||||
name:
|
||||
page:
|
||||
body:
|
||||
parent_id:
|
||||
settings:
|
||||
messages:
|
||||
send_as_email: Berichten als emails ontvangen.
|
||||
notify:
|
||||
negative_balance: Informeer me wanneer mijn huishouden een negatief saldo krijgt.
|
||||
order_finished: Informeer me over mijn bestelresultaat (wanneer de bestelling gesloten wordt).
|
||||
upcoming_tasks: Herinner me aan aankomende taken.
|
||||
profile:
|
||||
email_is_public: E-mail is zichtbaar voor andere leden.
|
||||
language: Taal
|
||||
name_is_public: Naam is zichtbaar voor andere leden.
|
||||
phone_is_public: Telefoonnummer is zichtbaar voor andere leden.
|
||||
settings_group:
|
||||
messages: Berichten
|
||||
privacy: Privacy
|
||||
stock_article:
|
||||
supplier:
|
||||
supplier:
|
||||
|
@ -1513,17 +1578,19 @@ nl:
|
|||
workgroup:
|
||||
next_weekly_tasks_number:
|
||||
role_admin:
|
||||
role_article_meta:
|
||||
role_finance:
|
||||
role_article_meta: Artikelbestand
|
||||
role_finance: Financiën
|
||||
role_orders:
|
||||
role_suppliers:
|
||||
task_description:
|
||||
task_duration:
|
||||
task_name:
|
||||
task_required_users:
|
||||
weekday:
|
||||
weekly_task:
|
||||
role_suppliers: Leveranciers
|
||||
'no': Nee
|
||||
options:
|
||||
settings:
|
||||
profile:
|
||||
language:
|
||||
de: Duits
|
||||
en: Engels
|
||||
fr: Frans
|
||||
nl: Nederlands
|
||||
required:
|
||||
mark: ! '*'
|
||||
text: verplicht
|
||||
|
@ -1568,6 +1635,15 @@ nl:
|
|||
title:
|
||||
form:
|
||||
price_hint:
|
||||
history:
|
||||
change_quantity:
|
||||
datetime:
|
||||
delivery:
|
||||
new_quantity:
|
||||
order:
|
||||
reason:
|
||||
stock_changes:
|
||||
stock_taking:
|
||||
index:
|
||||
article:
|
||||
article:
|
||||
|
@ -1587,6 +1663,7 @@ nl:
|
|||
show_stock_takings:
|
||||
stock_count:
|
||||
stock_worth:
|
||||
title:
|
||||
toggle_unavailable:
|
||||
view_options:
|
||||
new:
|
||||
|
@ -1617,6 +1694,7 @@ nl:
|
|||
shared_suppliers:
|
||||
body:
|
||||
subscribe:
|
||||
subscribe_again:
|
||||
supplier:
|
||||
title:
|
||||
show:
|
||||
|
@ -1647,12 +1725,15 @@ nl:
|
|||
notice:
|
||||
edit:
|
||||
title:
|
||||
warning_periodic:
|
||||
error_not_found:
|
||||
form:
|
||||
search:
|
||||
hint:
|
||||
noresult:
|
||||
placeholder:
|
||||
submit:
|
||||
periodic:
|
||||
index:
|
||||
show_group_tasks:
|
||||
title:
|
||||
|
@ -1674,12 +1755,16 @@ nl:
|
|||
group_tasks:
|
||||
my_tasks:
|
||||
new_task:
|
||||
pages:
|
||||
new:
|
||||
title:
|
||||
repeated:
|
||||
set_done:
|
||||
notice:
|
||||
show:
|
||||
accept_task:
|
||||
confirm_delete_group:
|
||||
delete_group:
|
||||
due_date:
|
||||
hours:
|
||||
mark_done:
|
||||
|
@ -1687,6 +1772,7 @@ nl:
|
|||
title:
|
||||
update:
|
||||
notice:
|
||||
notice_converted:
|
||||
user:
|
||||
more:
|
||||
tasks_link:
|
||||
|
@ -1696,11 +1782,6 @@ nl:
|
|||
workgroup:
|
||||
title:
|
||||
title_all:
|
||||
weekly:
|
||||
desc:
|
||||
edit:
|
||||
empty:
|
||||
title:
|
||||
time:
|
||||
am: morgen
|
||||
formats:
|
||||
|
@ -1712,9 +1793,12 @@ nl:
|
|||
close: Sluiten
|
||||
delete: Verwijder
|
||||
edit: Bewerk
|
||||
history:
|
||||
marks:
|
||||
close: ! '×'
|
||||
success: <i class="icon icon-ok"></i>
|
||||
or_cancel: of annuleren
|
||||
please_wait: Een moment alstublieft...
|
||||
save: Opslaan
|
||||
show: Tonen
|
||||
views:
|
||||
|
|
|
@ -8,6 +8,7 @@ Foodsoft::Application.routes.draw do
|
|||
|
||||
root :to => redirect("/#{FoodsoftConfig.scope}")
|
||||
|
||||
|
||||
scope '/:foodcoop' do
|
||||
|
||||
# Root path
|
||||
|
@ -96,14 +97,23 @@ Foodsoft::Application.routes.draw do
|
|||
get :articles_search
|
||||
get :fill_new_stock_article_form
|
||||
end
|
||||
|
||||
get :history
|
||||
end
|
||||
|
||||
resources :suppliers do
|
||||
get :shared_suppliers, :on => :collection
|
||||
|
||||
resources :deliveries do
|
||||
post :drop_stock_change, :on => :member
|
||||
post :add_stock_article, :on => :collection
|
||||
post :add_stock_change, :on => :collection
|
||||
|
||||
get :new_stock_article, :on => :collection
|
||||
get :copy_stock_article, :on => :collection
|
||||
get :derive_stock_article, :on => :collection
|
||||
post :create_stock_article, :on => :collection
|
||||
|
||||
get :edit_stock_article, :on => :collection
|
||||
put :update_stock_article, :on => :collection
|
||||
end
|
||||
|
||||
resources :articles do
|
||||
|
|
|
@ -3,13 +3,11 @@
|
|||
|
||||
# Upcoming tasks notifier
|
||||
every :day, :at => '7:20 am' do
|
||||
rake "multicoops:run foodsoft:notify_upcoming_tasks"
|
||||
rake "multicoops:run TASK=foodsoft:notify_upcoming_tasks"
|
||||
end
|
||||
|
||||
# Weekly taks
|
||||
every :sunday, :at => '7:14 am' do
|
||||
rake "multicoops:run foodsoft:create_upcoming_weekly_tasks"
|
||||
rake "multicoops:run foodsoft:notify_users_of_weekly_task"
|
||||
rake "multicoops:run TASK=foodsoft:create_upcoming_periodic_tasks"
|
||||
rake "multicoops:run TASK=foodsoft:notify_users_of_weekly_task"
|
||||
end
|
||||
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue