Compare commits
65 commits
demo
...
online-pay
Author | SHA1 | Date | |
---|---|---|---|
|
260c51eef5 | ||
|
82f0935d65 | ||
|
66bbafcd4d | ||
|
55234b4e27 | ||
|
e194c68397 | ||
|
e1b5824830 | ||
|
91f27a0a48 | ||
|
caa32de30c | ||
|
1e63c59a8a | ||
|
a96f21134e | ||
|
bcf47ec92b | ||
|
ef6d6aa368 | ||
|
c4a53caf52 | ||
|
9282590c06 | ||
|
817e409a2b | ||
|
e80ec9c1ce | ||
|
7f23b4784c | ||
|
b07653b34f | ||
|
c442327275 | ||
|
33034e66b8 | ||
|
45e2668cea | ||
|
5f2130ca44 | ||
|
913136bb72 | ||
|
4ac5bcae06 | ||
|
37b3b4523a | ||
|
a1682932ac | ||
|
026c3a6285 | ||
|
a8b2f387db | ||
|
2151835afb | ||
|
20dc8b8b82 | ||
|
e4f91ef67a | ||
|
c50ba6eda5 | ||
|
075f3cfa1a | ||
|
64b99038e6 | ||
|
7fe5fb4592 | ||
8b0e03ff60 | |||
|
4bfa87d258 | ||
|
20a67becf5 | ||
|
91e07ab660 | ||
|
285441cb4b | ||
|
fb2b4d8a8a | ||
|
f6fb804bbe | ||
|
a7775f5a98 | ||
b06656ba80 | |||
|
6e721db654 | ||
45ae192891 | |||
808baa5a98 | |||
|
5cbe8dd968 | ||
|
34e238466f | ||
5fb10ec686 | |||
50bf879fbf | |||
ea248a5f28 | |||
4ff44aed4c | |||
3d81dd6b57 | |||
|
c67e9b5be8 | ||
|
8604e27fe9 | ||
|
f2d5936cf0 | ||
|
c01c16ecdb | ||
|
67d0492ac4 | ||
|
5f00a39841 | ||
|
8420323c92 | ||
|
e0f63eebdc | ||
|
a7a0830d43 | ||
|
503ed6c379 | ||
|
debce2a635 |
460 changed files with 11089 additions and 7166 deletions
5
.gitattributes
vendored
Normal file
5
.gitattributes
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
# Fixes line endings for Windows (Docker) environment, which are by default converted to crlf
|
||||
* text=auto
|
||||
*.sh text eol=lf
|
||||
proc-start text eol=lf
|
||||
Rakefile text eol=lf
|
6
.github/workflows/ruby.yml
vendored
6
.github/workflows/ruby.yml
vendored
|
@ -15,7 +15,7 @@ jobs:
|
|||
MYSQL_DATABASE: test
|
||||
MYSQL_ROOT_PASSWORD: password
|
||||
options: >-
|
||||
--health-cmd "mysqladmin ping"
|
||||
--health-cmd "mariadb-admin ping"
|
||||
--health-interval 10s
|
||||
--health-timeout 5s
|
||||
--health-retries 5
|
||||
|
@ -35,7 +35,9 @@ jobs:
|
|||
- name: Checkout source code
|
||||
uses: actions/checkout@v2
|
||||
- name: Setup chromedriver
|
||||
uses: nanasess/setup-chromedriver@v1.0.1
|
||||
uses: nanasess/setup-chromedriver@v2
|
||||
with:
|
||||
chromedriver-version: '115.0.5790.170' # https://github.com/nanasess/setup-chromedriver/issues/200
|
||||
- name: Setup ruby
|
||||
uses: ruby/setup-ruby@v1
|
||||
with:
|
||||
|
|
1811
.rubocop_todo.yml
1811
.rubocop_todo.yml
File diff suppressed because it is too large
Load diff
|
@ -1 +1 @@
|
|||
2.6.9
|
||||
2.7.8
|
||||
|
|
33
CHANGELOG.md
33
CHANGELOG.md
|
@ -1,3 +1,36 @@
|
|||
# Foodsoft 4.8.0
|
||||
|
||||
* feat: Show total sums for ordergroup finances [#1017](https://github.com/foodcoops/foodsoft/pull/1017)
|
||||
* feat: Richtext Messages and Attachments with Actiontext [#918](https://github.com/foodcoops/foodsoft/issues/918)
|
||||
* feat: Make date configurable via locales [#997](https://github.com/foodcoops/foodsoft/pull/997)
|
||||
* feat: Turkish language support added [#995](https://github.com/foodcoops/foodsoft/pull/995)
|
||||
* feat: Disable member list via configuration [#990](https://github.com/foodcoops/foodsoft/pull/990)
|
||||
* feat: Specify an URL to redirect after logout via settings #989
|
||||
* feat: introduce importmaps [#983](https://github.com/foodcoops/foodsoft/pull/983)
|
||||
* feat: ruby 2.7.2 and rails 7 upgrade [#979](https://github.com/foodcoops/foodsoft/pull/979)
|
||||
* feat: Add home controller test [#972](https://github.com/foodcoops/foodsoft/pull/972)
|
||||
* feat: Replace apivore with rswag for api tests [#969](https://github.com/foodcoops/foodsoft/pull/969)
|
||||
* feat: increase test coverage [#966](https://github.com/foodcoops/foodsoft/pull/966)
|
||||
* feat: Show order note as tooltip [#965](https://github.com/foodcoops/foodsoft/pull/965)
|
||||
* feat: Add sd_notify [#961](https://github.com/foodcoops/foodsoft/pull/961)
|
||||
* feat: Show instance name at login screen [#957](https://github.com/foodcoops/foodsoft/pull/957)
|
||||
* feat: Enabled systemd socket activation [#942](https://github.com/foodcoops/foodsoft/pull/942)
|
||||
* feat: Add table_print gem for debugging ActiveRecord queries in the console [#935](https://github.com/foodcoops/foodsoft/pull/935)
|
||||
* feat: Add admin UI for SupplierCategories (supplier_categories) [#930](https://github.com/foodcoops/foodsoft/pull/930)
|
||||
|
||||
* fix: add null checks for articles convert_units [33034e6](https://github.com/foodcoops/foodsoft/commit/33034e66b88968dedc5289425e1eff847ee67e12)
|
||||
* fix: downgrade haml to make deface work [#1003](https://github.com/foodcoops/foodsoft/pull/1003)
|
||||
* fix: dutch translation errors [#954](https://github.com/foodcoops/foodsoft/pull/954)
|
||||
* fix: Fixe filtering of active ordergroups [#934](https://github.com/foodcoops/foodsoft/pull/934)
|
||||
* fix: Change password validation to allow longer passwords [#923](https://github.com/foodcoops/foodsoft/pull/923)
|
||||
* fix: Invoice: change label "delivery" to "stock delivery" [#922](https://github.com/foodcoops/foodsoft/pull/922)
|
||||
* fix: Allow decimal numbers in transaction collections [#921](https://github.com/foodcoops/foodsoft/pull/921)
|
||||
* fix: Add validation of more article fields [#917](https://github.com/foodcoops/foodsoft/pull/917/files)
|
||||
* fix: Add default time_zone [#912](https://github.com/foodcoops/foodsoft/pull/912)
|
||||
* fix: Rename Piwik to Matomo [#911](https://github.com/foodcoops/foodsoft/pull/911/files)
|
||||
* fix: Change instructions to rbenv [#910](https://github.com/foodcoops/foodsoft/pull/910/files)
|
||||
|
||||
|
||||
# Foodsoft 4.7.1
|
||||
(31 December 2020)
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
FROM ruby:2.6
|
||||
FROM ruby:2.7
|
||||
|
||||
RUN supercronicUrl=https://github.com/aptible/supercronic/releases/download/v0.1.3/supercronic-linux-amd64 && \
|
||||
supercronicBin=/usr/local/bin/supercronic && \
|
||||
|
@ -22,6 +22,7 @@ RUN buildDeps='libmagic-dev' && \
|
|||
apt-get update && \
|
||||
apt-get install --no-install-recommends -y $buildDeps && \
|
||||
echo 'gem: --no-document' >> ~/.gemrc && \
|
||||
gem install bundler && \
|
||||
bundle config build.nokogiri "--use-system-libraries" && \
|
||||
bundle install --deployment --without development test -j 4 && \
|
||||
apt-get purge -y --auto-remove $buildDeps && \
|
||||
|
@ -48,9 +49,10 @@ RUN export DATABASE_URL=mysql2://localhost/temp?encoding=utf8 && \
|
|||
rm -Rf /var/lib/apt/lists/* /var/cache/apt/*
|
||||
|
||||
# Make relevant dirs and files writable for app user
|
||||
RUN mkdir -p tmp && \
|
||||
RUN mkdir -p tmp storage && \
|
||||
chown nobody config/app_config.yml && \
|
||||
chown nobody tmp
|
||||
chown nobody tmp && \
|
||||
chown nobody storage
|
||||
|
||||
# Run app as unprivileged user
|
||||
USER nobody
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
FROM ruby:2.6
|
||||
FROM ruby:2.7
|
||||
|
||||
# Install dependencies
|
||||
RUN deps='libmagic-dev chromium nodejs' && \
|
||||
|
@ -19,6 +19,7 @@ ENV PORT=3000 \
|
|||
|
||||
WORKDIR /app
|
||||
|
||||
RUN gem install bundler
|
||||
RUN bundle config build.nokogiri "--use-system-libraries"
|
||||
|
||||
EXPOSE 3000
|
||||
|
|
105
Gemfile
105
Gemfile
|
@ -1,87 +1,95 @@
|
|||
# A sample Gemfile
|
||||
source "https://rubygems.org"
|
||||
source 'https://rubygems.org'
|
||||
|
||||
gem "rails", '~> 5.2'
|
||||
gem 'rails', '~> 7.0'
|
||||
|
||||
gem 'sass-rails'
|
||||
gem 'less-rails'
|
||||
gem 'uglifier', '>= 1.0.3'
|
||||
gem 'sassc-rails'
|
||||
# See https://github.com/sstephenson/execjs#readme for more supported runtimes
|
||||
gem 'therubyracer', platforms: :ruby
|
||||
|
||||
gem 'jquery-rails'
|
||||
gem 'select2-rails'
|
||||
gem 'rails_tokeninput'
|
||||
gem 'bootsnap', require: false
|
||||
gem 'bootstrap-datepicker-rails'
|
||||
gem 'date_time_attribute'
|
||||
gem 'rails-assets-listjs', '0.2.0.beta.4' # remember to maintain list.*.js plugins and template engines on update
|
||||
gem 'i18n-js', '~> 3.0.0.rc8'
|
||||
gem 'jquery-rails'
|
||||
gem 'rails-assets-listjs', '0.2.0.beta.4' # remember to maintain list.*.js plugins and template engines on update
|
||||
gem 'rails-i18n'
|
||||
gem 'bootsnap', require: false
|
||||
gem 'rails_tokeninput'
|
||||
gem 'select2-rails'
|
||||
|
||||
gem 'mysql2'
|
||||
gem 'prawn'
|
||||
gem 'prawn-table'
|
||||
gem 'haml'
|
||||
gem 'haml-rails'
|
||||
gem 'kaminari'
|
||||
gem 'simple_form'
|
||||
gem 'inherited_resources'
|
||||
gem 'active_model_serializers', '~> 0.10.0'
|
||||
gem 'acts_as_tree'
|
||||
gem 'attribute_normalizer'
|
||||
gem 'daemons'
|
||||
gem 'doorkeeper'
|
||||
gem 'doorkeeper-i18n'
|
||||
gem 'haml', '~> 5.0'
|
||||
gem 'haml-rails'
|
||||
gem 'ice_cube'
|
||||
gem 'inherited_resources'
|
||||
gem 'kaminari'
|
||||
gem 'mysql2'
|
||||
gem 'prawn'
|
||||
gem 'prawn-table'
|
||||
gem 'puma'
|
||||
gem 'rack-cors', require: 'rack/cors'
|
||||
gem 'active_model_serializers', '~> 0.10.0'
|
||||
gem 'twitter-bootstrap-rails', '~> 2.2.8'
|
||||
gem 'rails-settings-cached', '= 0.4.3' # caching breaks tests until Rails 5 https://github.com/huacnlee/rails-settings-cached/issues/73
|
||||
gem 'ransack'
|
||||
gem 'resque'
|
||||
gem 'ruby-units'
|
||||
gem 'sd_notify'
|
||||
gem 'simple_form'
|
||||
gem 'simple-navigation', '~> 3.14.0' # 3.x for simple_navigation_bootstrap
|
||||
gem 'simple-navigation-bootstrap'
|
||||
gem 'sprockets', '< 4'
|
||||
gem 'ransack'
|
||||
gem 'acts_as_tree'
|
||||
gem 'rails-settings-cached', '= 0.4.3' # caching breaks tests until Rails 5 https://github.com/huacnlee/rails-settings-cached/issues/73
|
||||
gem 'resque'
|
||||
gem 'puma'
|
||||
gem 'sd_notify'
|
||||
gem 'twitter-bootstrap-rails', '~> 2.2.8'
|
||||
gem 'whenever', require: false # For defining cronjobs, see config/schedule.rb
|
||||
gem 'ruby-units'
|
||||
gem 'attribute_normalizer'
|
||||
gem 'ice_cube'
|
||||
gem 'recurring_select'
|
||||
gem 'roo'
|
||||
gem 'roo-xls'
|
||||
gem 'spreadsheet'
|
||||
# At time of development 01-06-2022 mmddyyyy necessary fix for config_helper.rb form builder was not in rubygems so we pull from github, see: https://github.com/gregschmit/recurring_select/pull/152
|
||||
gem 'exception_notification'
|
||||
gem 'gaffe'
|
||||
gem 'ruby-filemagic'
|
||||
gem 'mime-types'
|
||||
gem 'hashie', '~> 3.4.6', require: false # https://github.com/westfieldlabs/apivore/issues/114
|
||||
gem "image_processing", "~> 1.12"
|
||||
gem "importmap-rails", "~> 1.1"
|
||||
gem 'midi-smtp-server'
|
||||
gem 'mime-types'
|
||||
gem 'recurring_select', git: 'https://github.com/gregschmit/recurring_select'
|
||||
gem 'roo'
|
||||
gem 'roo-xls'
|
||||
gem 'rswag-api'
|
||||
gem 'rswag-ui'
|
||||
gem 'ruby-filemagic'
|
||||
gem 'spreadsheet'
|
||||
gem "terser", "~> 1.1"
|
||||
|
||||
# we use the git version of acts_as_versioned, and need to include it in this Gemfile
|
||||
gem 'acts_as_versioned', git: 'https://github.com/technoweenie/acts_as_versioned.git'
|
||||
gem 'foodsoft_wiki', path: 'plugins/wiki'
|
||||
gem 'foodsoft_messages', path: 'plugins/messages'
|
||||
gem 'foodsoft_documents', path: 'plugins/documents'
|
||||
gem 'foodsoft_discourse', path: 'plugins/discourse'
|
||||
gem 'foodsoft_documents', path: 'plugins/documents'
|
||||
gem 'foodsoft_links', path: 'plugins/links'
|
||||
gem 'foodsoft_messages', path: 'plugins/messages'
|
||||
gem 'foodsoft_polls', path: 'plugins/polls'
|
||||
gem 'foodsoft_wiki', path: 'plugins/wiki'
|
||||
|
||||
# plugins not enabled by default
|
||||
# gem 'foodsoft_current_orders', path: 'plugins/current_orders'
|
||||
# gem 'foodsoft_printer', path: 'plugins/printer'
|
||||
# gem 'foodsoft_uservoice', path: 'plugins/uservoice'
|
||||
gem 'foodsoft_mollie', path: 'plugins/mollie'
|
||||
|
||||
group :development do
|
||||
gem 'sqlite3', '~> 1.3.6'
|
||||
gem 'mailcatcher'
|
||||
gem 'web-console'
|
||||
gem 'listen'
|
||||
gem 'mailcatcher'
|
||||
gem 'sqlite3', '~> 1.3.6'
|
||||
gem 'web-console'
|
||||
|
||||
# Better error output
|
||||
gem 'better_errors'
|
||||
gem 'binding_of_caller'
|
||||
# gem "rails-i18n-debug"
|
||||
# chrome debugging extension https://github.com/dejan/rails_panel
|
||||
gem 'meta_request'
|
||||
# TODO: disabled due to https://github.com/rails/rails/issues/40781
|
||||
# gem 'meta_request'
|
||||
|
||||
# Get infos when not using proper eager loading
|
||||
gem 'bullet'
|
||||
|
@ -101,21 +109,20 @@ group :development, :test do
|
|||
end
|
||||
|
||||
group :test do
|
||||
gem 'rspec-rails'
|
||||
gem 'apparition' # Capybara javascript driver
|
||||
gem 'capybara'
|
||||
gem 'connection_pool'
|
||||
gem 'database_cleaner'
|
||||
gem 'factory_bot_rails'
|
||||
gem 'faker'
|
||||
gem 'capybara'
|
||||
gem 'apparition' # Capybara javascript driver
|
||||
gem 'database_cleaner'
|
||||
gem 'connection_pool'
|
||||
gem 'rspec-rails'
|
||||
# need to include rspec components before i18n-spec or rake fails in test environment
|
||||
gem 'i18n-spec'
|
||||
gem 'rspec-core'
|
||||
gem 'rspec-rerun'
|
||||
gem 'i18n-spec'
|
||||
# code coverage
|
||||
gem 'simplecov', require: false
|
||||
gem 'simplecov-lcov', require: false
|
||||
# api
|
||||
gem 'apivore', require: false
|
||||
gem 'hashie', '~> 3.4.6', require: false # https://github.com/westfieldlabs/apivore/issues/114
|
||||
gem 'rswag-specs'
|
||||
end
|
||||
|
|
407
Gemfile.lock
407
Gemfile.lock
|
@ -1,3 +1,14 @@
|
|||
GIT
|
||||
remote: https://github.com/gregschmit/recurring_select
|
||||
revision: 29febc4c4abdd6c30636c33a7d2daecb09973ecf
|
||||
specs:
|
||||
recurring_select (3.0.0)
|
||||
coffee-rails (>= 3.1)
|
||||
ice_cube (>= 0.11)
|
||||
jquery-rails (>= 3.0)
|
||||
rails (>= 5.2)
|
||||
sass-rails (>= 4.0)
|
||||
|
||||
GIT
|
||||
remote: https://github.com/technoweenie/acts_as_versioned.git
|
||||
revision: 63b1fc8529d028fae632fe80ec0cb25df56cd76b
|
||||
|
@ -37,6 +48,13 @@ PATH
|
|||
mail
|
||||
rails
|
||||
|
||||
PATH
|
||||
remote: plugins/mollie
|
||||
specs:
|
||||
foodsoft_mollie (0.0.1)
|
||||
mollie-api-ruby
|
||||
rails
|
||||
|
||||
PATH
|
||||
remote: plugins/polls
|
||||
specs:
|
||||
|
@ -59,67 +77,83 @@ PATH
|
|||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
actioncable (5.2.8.1)
|
||||
actionpack (= 5.2.8.1)
|
||||
actioncable (7.0.4)
|
||||
actionpack (= 7.0.4)
|
||||
activesupport (= 7.0.4)
|
||||
nio4r (~> 2.0)
|
||||
websocket-driver (>= 0.6.1)
|
||||
actionmailer (5.2.8.1)
|
||||
actionpack (= 5.2.8.1)
|
||||
actionview (= 5.2.8.1)
|
||||
activejob (= 5.2.8.1)
|
||||
actionmailbox (7.0.4)
|
||||
actionpack (= 7.0.4)
|
||||
activejob (= 7.0.4)
|
||||
activerecord (= 7.0.4)
|
||||
activestorage (= 7.0.4)
|
||||
activesupport (= 7.0.4)
|
||||
mail (>= 2.7.1)
|
||||
net-imap
|
||||
net-pop
|
||||
net-smtp
|
||||
actionmailer (7.0.4)
|
||||
actionpack (= 7.0.4)
|
||||
actionview (= 7.0.4)
|
||||
activejob (= 7.0.4)
|
||||
activesupport (= 7.0.4)
|
||||
mail (~> 2.5, >= 2.5.4)
|
||||
net-imap
|
||||
net-pop
|
||||
net-smtp
|
||||
rails-dom-testing (~> 2.0)
|
||||
actionpack (5.2.8.1)
|
||||
actionview (= 5.2.8.1)
|
||||
activesupport (= 5.2.8.1)
|
||||
rack (~> 2.0, >= 2.0.8)
|
||||
actionpack (7.0.4)
|
||||
actionview (= 7.0.4)
|
||||
activesupport (= 7.0.4)
|
||||
rack (~> 2.0, >= 2.2.0)
|
||||
rack-test (>= 0.6.3)
|
||||
rails-dom-testing (~> 2.0)
|
||||
rails-html-sanitizer (~> 1.0, >= 1.0.2)
|
||||
actionview (5.2.8.1)
|
||||
activesupport (= 5.2.8.1)
|
||||
rails-html-sanitizer (~> 1.0, >= 1.2.0)
|
||||
actiontext (7.0.4)
|
||||
actionpack (= 7.0.4)
|
||||
activerecord (= 7.0.4)
|
||||
activestorage (= 7.0.4)
|
||||
activesupport (= 7.0.4)
|
||||
globalid (>= 0.6.0)
|
||||
nokogiri (>= 1.8.5)
|
||||
actionview (7.0.4)
|
||||
activesupport (= 7.0.4)
|
||||
builder (~> 3.1)
|
||||
erubi (~> 1.4)
|
||||
rails-dom-testing (~> 2.0)
|
||||
rails-html-sanitizer (~> 1.0, >= 1.0.3)
|
||||
rails-html-sanitizer (~> 1.1, >= 1.2.0)
|
||||
active_model_serializers (0.10.13)
|
||||
actionpack (>= 4.1, < 7.1)
|
||||
activemodel (>= 4.1, < 7.1)
|
||||
case_transform (>= 0.2)
|
||||
jsonapi-renderer (>= 0.1.1.beta1, < 0.3)
|
||||
activejob (5.2.8.1)
|
||||
activesupport (= 5.2.8.1)
|
||||
activejob (7.0.4)
|
||||
activesupport (= 7.0.4)
|
||||
globalid (>= 0.3.6)
|
||||
activemodel (5.2.8.1)
|
||||
activesupport (= 5.2.8.1)
|
||||
activerecord (5.2.8.1)
|
||||
activemodel (= 5.2.8.1)
|
||||
activesupport (= 5.2.8.1)
|
||||
arel (>= 9.0)
|
||||
activestorage (5.2.8.1)
|
||||
actionpack (= 5.2.8.1)
|
||||
activerecord (= 5.2.8.1)
|
||||
marcel (~> 1.0.0)
|
||||
activesupport (5.2.8.1)
|
||||
activemodel (7.0.4)
|
||||
activesupport (= 7.0.4)
|
||||
activerecord (7.0.4)
|
||||
activemodel (= 7.0.4)
|
||||
activesupport (= 7.0.4)
|
||||
activestorage (7.0.4)
|
||||
actionpack (= 7.0.4)
|
||||
activejob (= 7.0.4)
|
||||
activerecord (= 7.0.4)
|
||||
activesupport (= 7.0.4)
|
||||
marcel (~> 1.0)
|
||||
mini_mime (>= 1.1.0)
|
||||
activesupport (7.0.4)
|
||||
concurrent-ruby (~> 1.0, >= 1.0.2)
|
||||
i18n (>= 0.7, < 2)
|
||||
minitest (~> 5.1)
|
||||
tzinfo (~> 1.1)
|
||||
i18n (>= 1.6, < 2)
|
||||
minitest (>= 5.1)
|
||||
tzinfo (~> 2.0)
|
||||
acts_as_tree (2.9.1)
|
||||
activerecord (>= 3.0.0)
|
||||
addressable (2.8.1)
|
||||
public_suffix (>= 2.0.2, < 6.0)
|
||||
apivore (1.6.2)
|
||||
actionpack (>= 4, < 6)
|
||||
hashie (~> 3.3)
|
||||
json-schema (~> 2.5)
|
||||
rspec (~> 3)
|
||||
rspec-expectations (~> 3.1)
|
||||
rspec-mocks (~> 3.1)
|
||||
apparition (0.6.0)
|
||||
capybara (~> 3.13, < 4)
|
||||
websocket-driver (>= 0.6.5)
|
||||
arel (9.0.0)
|
||||
ast (2.4.2)
|
||||
attribute_normalizer (1.2.0)
|
||||
base32 (0.3.4)
|
||||
|
@ -130,15 +164,15 @@ GEM
|
|||
bindex (0.8.1)
|
||||
binding_of_caller (1.0.0)
|
||||
debug_inspector (>= 0.0.1)
|
||||
bootsnap (1.13.0)
|
||||
bootsnap (1.15.0)
|
||||
msgpack (~> 1.2)
|
||||
bootstrap-datepicker-rails (1.9.0.1)
|
||||
railties (>= 3.0)
|
||||
builder (3.2.4)
|
||||
bullet (7.0.3)
|
||||
bullet (7.0.7)
|
||||
activesupport (>= 3.0.0)
|
||||
uniform_notifier (~> 1.11)
|
||||
capybara (3.36.0)
|
||||
capybara (3.38.0)
|
||||
addressable
|
||||
matrix
|
||||
mini_mime (>= 0.1.3)
|
||||
|
@ -159,7 +193,7 @@ GEM
|
|||
execjs
|
||||
coffee-script-source (1.12.2)
|
||||
commonjs (0.2.7)
|
||||
concurrent-ruby (1.1.10)
|
||||
concurrent-ruby (1.2.2)
|
||||
connection_pool (2.3.0)
|
||||
content_for_in_controllers (0.0.2)
|
||||
crass (1.0.6)
|
||||
|
@ -170,6 +204,7 @@ GEM
|
|||
activerecord (>= 5.a)
|
||||
database_cleaner-core (~> 2.0.0)
|
||||
database_cleaner-core (2.0.1)
|
||||
date (3.3.3)
|
||||
date_time_attribute (0.1.2)
|
||||
activesupport (>= 3.0.0)
|
||||
debug_inspector (1.1.0)
|
||||
|
@ -182,13 +217,13 @@ GEM
|
|||
diff-lcs (1.5.0)
|
||||
diffy (3.4.2)
|
||||
docile (1.4.0)
|
||||
doorkeeper (5.6.0)
|
||||
doorkeeper (5.6.6)
|
||||
railties (>= 5)
|
||||
doorkeeper-i18n (5.2.5)
|
||||
doorkeeper-i18n (5.2.6)
|
||||
doorkeeper (>= 5.2)
|
||||
email_reply_trimmer (0.1.13)
|
||||
erubi (1.11.0)
|
||||
eventmachine (1.2.7)
|
||||
erubi (1.12.0)
|
||||
eventmachine (1.0.9.1)
|
||||
exception_notification (4.5.0)
|
||||
actionmailer (>= 5.2, < 8)
|
||||
activesupport (>= 5.2, < 8)
|
||||
|
@ -199,16 +234,15 @@ GEM
|
|||
factory_bot_rails (6.2.0)
|
||||
factory_bot (~> 6.2.0)
|
||||
railties (>= 5.0.0)
|
||||
faker (2.22.0)
|
||||
faker (3.1.0)
|
||||
i18n (>= 1.8.11, < 2)
|
||||
ffi (1.15.5)
|
||||
gaffe (1.2.0)
|
||||
rails (>= 4.0.0)
|
||||
globalid (1.0.0)
|
||||
globalid (1.0.1)
|
||||
activesupport (>= 5.0)
|
||||
haml (6.0.5)
|
||||
temple (>= 0.8.2)
|
||||
thor
|
||||
haml (5.2.2)
|
||||
temple (>= 0.8.0)
|
||||
tilt
|
||||
haml-rails (2.1.0)
|
||||
actionpack (>= 5.1)
|
||||
|
@ -220,13 +254,19 @@ GEM
|
|||
activesupport (>= 5.2)
|
||||
hashie (3.4.6)
|
||||
htmlentities (4.3.4)
|
||||
i18n (1.12.0)
|
||||
i18n (1.14.1)
|
||||
concurrent-ruby (~> 1.0)
|
||||
i18n-js (3.0.11)
|
||||
i18n (>= 0.6.6, < 2)
|
||||
i18n-spec (0.6.0)
|
||||
iso
|
||||
ice_cube (0.16.4)
|
||||
image_processing (1.12.2)
|
||||
mini_magick (>= 4.9.5, < 5)
|
||||
ruby-vips (>= 2.0.17, < 3)
|
||||
importmap-rails (1.1.5)
|
||||
actionpack (>= 6.0.0)
|
||||
railties (>= 6.0.0)
|
||||
inherited_resources (1.13.1)
|
||||
actionpack (>= 5.2, < 7.1)
|
||||
has_scope (~> 0.6)
|
||||
|
@ -235,13 +275,13 @@ GEM
|
|||
interception (0.5)
|
||||
iso (0.4.0)
|
||||
i18n
|
||||
jquery-rails (4.5.0)
|
||||
jquery-rails (4.5.1)
|
||||
rails-dom-testing (>= 1, < 3)
|
||||
railties (>= 4.2.0)
|
||||
thor (>= 0.14, < 2.0)
|
||||
json (2.6.2)
|
||||
json-schema (2.8.1)
|
||||
addressable (>= 2.4)
|
||||
json (2.6.3)
|
||||
json-schema (3.0.0)
|
||||
addressable (>= 2.8)
|
||||
jsonapi-renderer (0.2.2)
|
||||
kaminari (1.2.2)
|
||||
activesupport (>= 4.1.0)
|
||||
|
@ -262,14 +302,18 @@ GEM
|
|||
less (~> 2.6.0)
|
||||
sprockets (~> 3.0)
|
||||
libv8 (3.16.14.19)
|
||||
libv8 (3.16.14.19-x86_64-linux)
|
||||
listen (3.7.1)
|
||||
rb-fsevent (~> 0.10, >= 0.10.3)
|
||||
rb-inotify (~> 0.9, >= 0.9.10)
|
||||
loofah (2.19.1)
|
||||
loofah (2.21.3)
|
||||
crass (~> 1.0.2)
|
||||
nokogiri (>= 1.5.9)
|
||||
mail (2.7.1)
|
||||
nokogiri (>= 1.12.0)
|
||||
mail (2.8.1)
|
||||
mini_mime (>= 0.1.1)
|
||||
net-imap
|
||||
net-pop
|
||||
net-smtp
|
||||
mailcatcher (0.2.4)
|
||||
eventmachine
|
||||
haml
|
||||
|
@ -282,29 +326,39 @@ GEM
|
|||
thin
|
||||
marcel (1.0.2)
|
||||
matrix (0.4.2)
|
||||
meta_request (0.7.3)
|
||||
rack-contrib (>= 1.1, < 3)
|
||||
railties (>= 3.0.0, < 7)
|
||||
method_source (1.0.0)
|
||||
midi-smtp-server (3.0.3)
|
||||
mime-types (3.4.1)
|
||||
mime-types-data (~> 3.2015)
|
||||
mime-types-data (3.2022.0105)
|
||||
mini_magick (4.12.0)
|
||||
mini_mime (1.1.2)
|
||||
mini_portile2 (2.8.0)
|
||||
minitest (5.16.3)
|
||||
mini_portile2 (2.8.2)
|
||||
minitest (5.18.0)
|
||||
mollie-api-ruby (4.7.1)
|
||||
mono_logger (1.1.1)
|
||||
msgpack (1.6.0)
|
||||
multi_json (1.15.0)
|
||||
mustermann (3.0.0)
|
||||
ruby2_keywords (~> 0.0.1)
|
||||
mysql2 (0.5.4)
|
||||
net-imap (0.3.4)
|
||||
date
|
||||
net-protocol
|
||||
net-pop (0.1.2)
|
||||
net-protocol
|
||||
net-protocol (0.2.1)
|
||||
timeout
|
||||
net-smtp (0.3.3)
|
||||
net-protocol
|
||||
nio4r (2.5.8)
|
||||
nokogiri (1.13.10)
|
||||
mini_portile2 (~> 2.8.0)
|
||||
nokogiri (1.15.2)
|
||||
mini_portile2 (~> 2.8.2)
|
||||
racc (~> 1.4)
|
||||
parallel (1.22.1)
|
||||
parser (3.1.2.1)
|
||||
nokogiri (1.15.2-x86_64-linux)
|
||||
racc (~> 1.4)
|
||||
parallel (1.23.0)
|
||||
parser (3.2.2.1)
|
||||
ast (~> 2.4.1)
|
||||
pdf-core (0.9.0)
|
||||
polyglot (0.3.5)
|
||||
|
@ -322,75 +376,70 @@ GEM
|
|||
pry-stack_explorer (0.6.1)
|
||||
binding_of_caller (~> 1.0)
|
||||
pry (~> 0.13)
|
||||
public_suffix (5.0.0)
|
||||
puma (5.6.5)
|
||||
public_suffix (5.0.1)
|
||||
puma (6.0.2)
|
||||
nio4r (~> 2.0)
|
||||
racc (1.6.1)
|
||||
rack (2.2.4)
|
||||
rack-contrib (2.3.0)
|
||||
rack (~> 2.0)
|
||||
racc (1.7.0)
|
||||
rack (2.2.7)
|
||||
rack-cors (1.1.1)
|
||||
rack (>= 2.0.0)
|
||||
rack-protection (3.0.4)
|
||||
rack-protection (3.0.5)
|
||||
rack
|
||||
rack-test (2.0.2)
|
||||
rack-test (2.1.0)
|
||||
rack (>= 1.3)
|
||||
rails (5.2.8.1)
|
||||
actioncable (= 5.2.8.1)
|
||||
actionmailer (= 5.2.8.1)
|
||||
actionpack (= 5.2.8.1)
|
||||
actionview (= 5.2.8.1)
|
||||
activejob (= 5.2.8.1)
|
||||
activemodel (= 5.2.8.1)
|
||||
activerecord (= 5.2.8.1)
|
||||
activestorage (= 5.2.8.1)
|
||||
activesupport (= 5.2.8.1)
|
||||
bundler (>= 1.3.0)
|
||||
railties (= 5.2.8.1)
|
||||
sprockets-rails (>= 2.0.0)
|
||||
rails (7.0.4)
|
||||
actioncable (= 7.0.4)
|
||||
actionmailbox (= 7.0.4)
|
||||
actionmailer (= 7.0.4)
|
||||
actionpack (= 7.0.4)
|
||||
actiontext (= 7.0.4)
|
||||
actionview (= 7.0.4)
|
||||
activejob (= 7.0.4)
|
||||
activemodel (= 7.0.4)
|
||||
activerecord (= 7.0.4)
|
||||
activestorage (= 7.0.4)
|
||||
activesupport (= 7.0.4)
|
||||
bundler (>= 1.15.0)
|
||||
railties (= 7.0.4)
|
||||
rails-assets-listjs (0.2.0.beta.4)
|
||||
railties (>= 3.1)
|
||||
rails-dom-testing (2.0.3)
|
||||
activesupport (>= 4.2.0)
|
||||
nokogiri (>= 1.6)
|
||||
rails-html-sanitizer (1.4.4)
|
||||
loofah (~> 2.19, >= 2.19.1)
|
||||
rails-i18n (5.1.3)
|
||||
rails-html-sanitizer (1.6.0)
|
||||
loofah (~> 2.21)
|
||||
nokogiri (~> 1.14)
|
||||
rails-i18n (7.0.6)
|
||||
i18n (>= 0.7, < 2)
|
||||
railties (>= 5.0, < 6)
|
||||
railties (>= 6.0.0, < 8)
|
||||
rails-settings-cached (0.4.3)
|
||||
rails (>= 4.2.0)
|
||||
rails_tokeninput (1.7.0)
|
||||
railties (>= 3.1.0)
|
||||
railties (5.2.8.1)
|
||||
actionpack (= 5.2.8.1)
|
||||
activesupport (= 5.2.8.1)
|
||||
railties (7.0.4)
|
||||
actionpack (= 7.0.4)
|
||||
activesupport (= 7.0.4)
|
||||
method_source
|
||||
rake (>= 0.8.7)
|
||||
thor (>= 0.19.0, < 2.0)
|
||||
rake (>= 12.2)
|
||||
thor (~> 1.0)
|
||||
zeitwerk (~> 2.5)
|
||||
rainbow (3.1.1)
|
||||
rake (13.0.6)
|
||||
ransack (2.5.0)
|
||||
activerecord (>= 5.2.4)
|
||||
activesupport (>= 5.2.4)
|
||||
ransack (3.2.1)
|
||||
activerecord (>= 6.1.5)
|
||||
activesupport (>= 6.1.5)
|
||||
i18n
|
||||
rb-fsevent (0.11.2)
|
||||
rb-inotify (0.10.1)
|
||||
ffi (~> 1.0)
|
||||
recurring_select (3.0.0)
|
||||
coffee-rails (>= 3.1)
|
||||
ice_cube (>= 0.11)
|
||||
jquery-rails (>= 3.0)
|
||||
rails (>= 5.2)
|
||||
sass-rails (>= 4.0)
|
||||
redis (5.0.5)
|
||||
redis-client (>= 0.9.0)
|
||||
redis-client (0.9.0)
|
||||
redis-client (0.11.2)
|
||||
connection_pool
|
||||
redis-namespace (1.9.0)
|
||||
redis-namespace (1.10.0)
|
||||
redis (>= 4)
|
||||
ref (2.0.0)
|
||||
regexp_parser (2.6.0)
|
||||
regexp_parser (2.8.0)
|
||||
responders (3.0.1)
|
||||
actionpack (>= 5.0)
|
||||
railties (>= 5.0)
|
||||
|
@ -400,59 +449,71 @@ GEM
|
|||
redis-namespace (~> 1.6)
|
||||
sinatra (>= 0.9.2)
|
||||
rexml (3.2.5)
|
||||
roo (2.8.3)
|
||||
roo (2.9.0)
|
||||
nokogiri (~> 1)
|
||||
rubyzip (>= 1.3.0, < 3.0.0)
|
||||
roo-xls (1.2.0)
|
||||
nokogiri
|
||||
roo (>= 2.0.0, < 3)
|
||||
spreadsheet (> 0.9.0)
|
||||
rspec (3.11.0)
|
||||
rspec-core (~> 3.11.0)
|
||||
rspec-expectations (~> 3.11.0)
|
||||
rspec-mocks (~> 3.11.0)
|
||||
rspec-core (3.11.0)
|
||||
rspec-support (~> 3.11.0)
|
||||
rspec-expectations (3.11.1)
|
||||
rspec (3.12.0)
|
||||
rspec-core (~> 3.12.0)
|
||||
rspec-expectations (~> 3.12.0)
|
||||
rspec-mocks (~> 3.12.0)
|
||||
rspec-core (3.12.0)
|
||||
rspec-support (~> 3.12.0)
|
||||
rspec-expectations (3.12.1)
|
||||
diff-lcs (>= 1.2.0, < 2.0)
|
||||
rspec-support (~> 3.11.0)
|
||||
rspec-mocks (3.11.1)
|
||||
rspec-support (~> 3.12.0)
|
||||
rspec-mocks (3.12.1)
|
||||
diff-lcs (>= 1.2.0, < 2.0)
|
||||
rspec-support (~> 3.11.0)
|
||||
rspec-rails (5.1.2)
|
||||
actionpack (>= 5.2)
|
||||
activesupport (>= 5.2)
|
||||
railties (>= 5.2)
|
||||
rspec-core (~> 3.10)
|
||||
rspec-expectations (~> 3.10)
|
||||
rspec-mocks (~> 3.10)
|
||||
rspec-support (~> 3.10)
|
||||
rspec-support (~> 3.12.0)
|
||||
rspec-rails (6.0.1)
|
||||
actionpack (>= 6.1)
|
||||
activesupport (>= 6.1)
|
||||
railties (>= 6.1)
|
||||
rspec-core (~> 3.11)
|
||||
rspec-expectations (~> 3.11)
|
||||
rspec-mocks (~> 3.11)
|
||||
rspec-support (~> 3.11)
|
||||
rspec-rerun (1.1.0)
|
||||
rspec (~> 3.0)
|
||||
rspec-support (3.11.1)
|
||||
rubocop (1.36.0)
|
||||
rspec-support (3.12.0)
|
||||
rswag-api (2.7.0)
|
||||
railties (>= 3.1, < 7.1)
|
||||
rswag-specs (2.9.0)
|
||||
activesupport (>= 3.1, < 7.1)
|
||||
json-schema (>= 2.2, < 4.0)
|
||||
railties (>= 3.1, < 7.1)
|
||||
rspec-core (>= 2.14)
|
||||
rswag-ui (2.7.0)
|
||||
actionpack (>= 3.1, < 7.1)
|
||||
railties (>= 3.1, < 7.1)
|
||||
rubocop (1.50.2)
|
||||
json (~> 2.3)
|
||||
parallel (~> 1.10)
|
||||
parser (>= 3.1.2.1)
|
||||
parser (>= 3.2.0.0)
|
||||
rainbow (>= 2.2.2, < 4.0)
|
||||
regexp_parser (>= 1.8, < 3.0)
|
||||
rexml (>= 3.2.5, < 4.0)
|
||||
rubocop-ast (>= 1.20.1, < 2.0)
|
||||
rubocop-ast (>= 1.28.0, < 2.0)
|
||||
ruby-progressbar (~> 1.7)
|
||||
unicode-display_width (>= 1.4.0, < 3.0)
|
||||
rubocop-ast (1.21.0)
|
||||
parser (>= 3.1.1.0)
|
||||
rubocop-rails (2.16.1)
|
||||
unicode-display_width (>= 2.4.0, < 3.0)
|
||||
rubocop-ast (1.28.1)
|
||||
parser (>= 3.2.1.0)
|
||||
rubocop-rails (2.17.4)
|
||||
activesupport (>= 4.2.0)
|
||||
rack (>= 1.1)
|
||||
rubocop (>= 1.33.0, < 2.0)
|
||||
rubocop-rspec (2.13.2)
|
||||
rubocop-rspec (2.16.0)
|
||||
rubocop (~> 1.33)
|
||||
ruby-filemagic (0.7.3)
|
||||
ruby-ole (1.2.12.2)
|
||||
ruby-prof (1.4.3)
|
||||
ruby-progressbar (1.11.0)
|
||||
ruby-prof (1.4.5)
|
||||
ruby-progressbar (1.13.0)
|
||||
ruby-units (3.0.0)
|
||||
ruby-vips (2.1.4)
|
||||
ffi (~> 1.12)
|
||||
ruby2_keywords (0.0.5)
|
||||
rubyzip (2.3.2)
|
||||
sass-rails (6.0.0)
|
||||
|
@ -475,21 +536,21 @@ GEM
|
|||
simple_form (5.1.0)
|
||||
actionpack (>= 5.2)
|
||||
activemodel (>= 5.2)
|
||||
simplecov (0.21.2)
|
||||
simplecov (0.22.0)
|
||||
docile (~> 1.1)
|
||||
simplecov-html (~> 0.11)
|
||||
simplecov_json_formatter (~> 0.1)
|
||||
simplecov-html (0.12.3)
|
||||
simplecov-lcov (0.8.0)
|
||||
simplecov_json_formatter (0.1.4)
|
||||
sinatra (3.0.4)
|
||||
sinatra (3.0.5)
|
||||
mustermann (~> 3.0)
|
||||
rack (~> 2.2, >= 2.2.4)
|
||||
rack-protection (= 3.0.4)
|
||||
rack-protection (= 3.0.5)
|
||||
tilt (~> 2.0)
|
||||
skinny (0.2.2)
|
||||
eventmachine (~> 1.0)
|
||||
thin
|
||||
skinny (0.2.4)
|
||||
eventmachine (~> 1.0.0)
|
||||
thin (>= 1.5, < 1.7)
|
||||
spreadsheet (1.3.0)
|
||||
ruby-ole
|
||||
sprockets (3.7.2)
|
||||
|
@ -503,17 +564,19 @@ GEM
|
|||
sqlite3-ruby (1.3.3)
|
||||
sqlite3 (>= 1.3.3)
|
||||
table_print (1.5.7)
|
||||
temple (0.8.2)
|
||||
temple (0.9.1)
|
||||
terser (1.1.13)
|
||||
execjs (>= 0.3.0, < 3)
|
||||
therubyracer (0.12.3)
|
||||
libv8 (~> 3.16.14.15)
|
||||
ref
|
||||
thin (1.8.1)
|
||||
daemons (~> 1.0, >= 1.0.9)
|
||||
eventmachine (~> 1.0, >= 1.0.4)
|
||||
rack (>= 1, < 3)
|
||||
thor (1.2.1)
|
||||
thread_safe (0.3.6)
|
||||
thin (1.6.2)
|
||||
daemons (>= 1.0.9)
|
||||
eventmachine (>= 1.0.0)
|
||||
rack (>= 1.0.0)
|
||||
thor (1.2.2)
|
||||
tilt (2.0.11)
|
||||
timeout (0.3.1)
|
||||
ttfunk (1.7.0)
|
||||
twitter-bootstrap-rails (2.2.8)
|
||||
actionpack (>= 3.1)
|
||||
|
@ -522,20 +585,18 @@ GEM
|
|||
railties (>= 3.1)
|
||||
twitter-text (1.14.7)
|
||||
unf (~> 0.1.0)
|
||||
tzinfo (1.2.10)
|
||||
thread_safe (~> 0.1)
|
||||
uglifier (4.2.0)
|
||||
execjs (>= 0.3.0, < 3)
|
||||
tzinfo (2.0.6)
|
||||
concurrent-ruby (~> 1.0)
|
||||
unf (0.1.4)
|
||||
unf_ext
|
||||
unf_ext (0.0.8.2)
|
||||
unicode-display_width (2.3.0)
|
||||
unicode-display_width (2.4.2)
|
||||
uniform_notifier (1.16.0)
|
||||
web-console (3.7.0)
|
||||
actionview (>= 5.0)
|
||||
activemodel (>= 5.0)
|
||||
web-console (4.2.0)
|
||||
actionview (>= 6.0.0)
|
||||
activemodel (>= 6.0.0)
|
||||
bindex (>= 0.4.0)
|
||||
railties (>= 5.0)
|
||||
railties (>= 6.0.0)
|
||||
websocket-driver (0.7.5)
|
||||
websocket-extensions (>= 0.1.0)
|
||||
websocket-extensions (0.1.5)
|
||||
|
@ -549,15 +610,16 @@ GEM
|
|||
twitter-text
|
||||
xpath (3.2.0)
|
||||
nokogiri (~> 1.8)
|
||||
zeitwerk (2.6.8)
|
||||
|
||||
PLATFORMS
|
||||
ruby
|
||||
x86_64-linux
|
||||
|
||||
DEPENDENCIES
|
||||
active_model_serializers (~> 0.10.0)
|
||||
acts_as_tree
|
||||
acts_as_versioned!
|
||||
apivore
|
||||
apparition
|
||||
attribute_normalizer
|
||||
better_errors
|
||||
|
@ -579,22 +641,24 @@ DEPENDENCIES
|
|||
foodsoft_documents!
|
||||
foodsoft_links!
|
||||
foodsoft_messages!
|
||||
foodsoft_mollie!
|
||||
foodsoft_polls!
|
||||
foodsoft_wiki!
|
||||
gaffe
|
||||
haml
|
||||
haml (~> 5.0)
|
||||
haml-rails
|
||||
hashie (~> 3.4.6)
|
||||
i18n-js (~> 3.0.0.rc8)
|
||||
i18n-spec
|
||||
ice_cube
|
||||
image_processing (~> 1.12)
|
||||
importmap-rails (~> 1.1)
|
||||
inherited_resources
|
||||
jquery-rails
|
||||
kaminari
|
||||
less-rails
|
||||
listen
|
||||
mailcatcher
|
||||
meta_request
|
||||
midi-smtp-server
|
||||
mime-types
|
||||
mysql2
|
||||
|
@ -604,26 +668,29 @@ DEPENDENCIES
|
|||
pry-stack_explorer
|
||||
puma
|
||||
rack-cors
|
||||
rails (~> 5.2)
|
||||
rails (~> 7.0)
|
||||
rails-assets-listjs (= 0.2.0.beta.4)
|
||||
rails-i18n
|
||||
rails-settings-cached (= 0.4.3)
|
||||
rails_tokeninput
|
||||
ransack
|
||||
recurring_select
|
||||
recurring_select!
|
||||
resque
|
||||
roo
|
||||
roo-xls
|
||||
rspec-core
|
||||
rspec-rails
|
||||
rspec-rerun
|
||||
rswag-api
|
||||
rswag-specs
|
||||
rswag-ui
|
||||
rubocop
|
||||
rubocop-rails
|
||||
rubocop-rspec
|
||||
ruby-filemagic
|
||||
ruby-prof
|
||||
ruby-units
|
||||
sass-rails
|
||||
sassc-rails
|
||||
sd_notify
|
||||
select2-rails
|
||||
simple-navigation (~> 3.14.0)
|
||||
|
@ -635,11 +702,11 @@ DEPENDENCIES
|
|||
sprockets (< 4)
|
||||
sqlite3 (~> 1.3.6)
|
||||
table_print
|
||||
terser (~> 1.1)
|
||||
therubyracer
|
||||
twitter-bootstrap-rails (~> 2.2.8)
|
||||
uglifier (>= 1.0.3)
|
||||
web-console
|
||||
whenever
|
||||
|
||||
BUNDLED WITH
|
||||
1.17.3
|
||||
2.4.5
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
Foodsoft
|
||||
=========
|
||||
|
||||
[![Build Status](https://github.com/foodcoops/foodsoft/workflows/Ruby/badge.svg)](https://github.com/foodcoops/foodsoft/actions)
|
||||
[![Coverage Status](https://coveralls.io/repos/foodcoops/foodsoft/badge.svg?branch=master)](https://coveralls.io/r/foodcoops/foodsoft?branch=master)
|
||||
[![Docs Status](https://inch-ci.org/github/foodcoops/foodsoft.svg?branch=master)](http://inch-ci.org/github/foodcoops/foodsoft)
|
||||
|
@ -15,10 +16,16 @@ If you're a food coop considering to use foodsoft, please have a look at the [wi
|
|||
|
||||
More information about using this software and contributing can be found on the [wiki](https://github.com/foodcoops/foodsoft/wiki).
|
||||
|
||||
Roadmap
|
||||
-------
|
||||
|
||||
If you'd like to see what is currently bring prioritised for development, check [our roadmap](https://github.com/orgs/foodcoops/projects/1). If you'd like to influence the roadmap, please join our [monthly community call](https://forum.foodcoops.net/t/foodsoft-monthly-community-call/573/6). As of March 2023, Foodsoft has limited development capacity but we are trying to build this up once more. For now, we try to prioritise what we work on, in order to focus our efforts. If your proposed changes are waiting for some time without review, please join the community call to discuss.
|
||||
|
||||
Developing
|
||||
----------
|
||||
|
||||
> Foodsoft development needs your help! If you want to hack/triage/organise to improve the software, please consider joining our monthly community calls which are announced on [this forum thread](https://forum.foodcoops.net/t/foodsoft-monthly-community-call/573/6). In these calls, we check in with each other, discuss what to prioritise and try to make progress with development and community issues together.
|
||||
|
||||
Get foodsoft [running locally](doc/SETUP_DEVELOPMENT.md),
|
||||
then visit our [Developing Guidelines](https://github.com/foodcoops/foodsoft/wiki/Developing-Guidelines)
|
||||
page on the wiki.
|
||||
|
@ -35,7 +42,6 @@ Deploying
|
|||
Setup foodsoft to [run in production](doc/SETUP_PRODUCTION.md), or join an existing
|
||||
[hosting platform](https://foodcoops.net/foodsoft-hosting/).
|
||||
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
|
|
2
Rakefile
2
Rakefile
|
@ -1,7 +1,7 @@
|
|||
#!/usr/bin/env rake
|
||||
# Add your own tasks in files placed in lib/tasks ending in .rake,
|
||||
|
||||
require File.expand_path('../config/application', __FILE__)
|
||||
require File.expand_path('config/application', __dir__)
|
||||
require 'rake'
|
||||
require 'rspec-rerun/tasks' if defined?(RSpec) # http://stackoverflow.com/a/16853615/2866660
|
||||
|
||||
|
|
2
VERSION
2
VERSION
|
@ -1 +1 @@
|
|||
4.7.99
|
||||
4.8.99
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
//= require bootstrap-datepicker/locales/bootstrap-datepicker.es
|
||||
//= require bootstrap-datepicker/locales/bootstrap-datepicker.nl
|
||||
//= require bootstrap-datepicker/locales/bootstrap-datepicker.fr
|
||||
//= require bootstrap-datepicker/locales/bootstrap-datepicker.tr
|
||||
//= require list
|
||||
//= require list.unlist
|
||||
//= require list.delay
|
|
@ -180,16 +180,12 @@ function updateBalance() {
|
|||
$('#new_balance').html(I18n.l("currency", balance));
|
||||
$('#total_balance').val(I18n.l("currency", balance));
|
||||
// determine bgcolor and submit button state according to balance
|
||||
var bgcolor = '';
|
||||
if (balance < minimumBalance) {
|
||||
bgcolor = '#FF0000';
|
||||
$('#submit_button').attr('disabled', 'disabled')
|
||||
$('#available_funds_error').css('display', 'block')
|
||||
} else {
|
||||
$('#submit_button').removeAttr('disabled')
|
||||
}
|
||||
// update bgcolor
|
||||
for (i in itemTotal) {
|
||||
$('#td_price_' + i).css('background-color', bgcolor);
|
||||
$('#available_funds_error').css('display', 'none')
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -232,4 +228,6 @@ $(function() {
|
|||
});
|
||||
|
||||
updateButtons($(document));
|
||||
|
||||
$(document).ready(updateBalance);
|
||||
});
|
||||
|
|
31
app/assets/stylesheets/actiontext.css
Normal file
31
app/assets/stylesheets/actiontext.css
Normal file
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Provides a drop-in pointer for the default Trix stylesheet that will format the toolbar and
|
||||
* the trix-editor content (whether displayed or under editing). Feel free to incorporate this
|
||||
* inclusion directly in any other asset bundle and remove this file.
|
||||
*
|
||||
*= require trix
|
||||
*/
|
||||
|
||||
/*
|
||||
* We need to override trix.css’s image gallery styles to accommodate the
|
||||
* <action-text-attachment> element we wrap around attachments. Otherwise,
|
||||
* images in galleries will be squished by the max-width: 33%; rule.
|
||||
*/
|
||||
.trix-content .attachment-gallery > action-text-attachment,
|
||||
.trix-content .attachment-gallery > .attachment {
|
||||
flex: 1 0 33%;
|
||||
padding: 0 0.5em;
|
||||
max-width: 33%;
|
||||
}
|
||||
|
||||
.trix-content .attachment-gallery.attachment-gallery--2 > action-text-attachment,
|
||||
.trix-content .attachment-gallery.attachment-gallery--2 > .attachment, .trix-content .attachment-gallery.attachment-gallery--4 > action-text-attachment,
|
||||
.trix-content .attachment-gallery.attachment-gallery--4 > .attachment {
|
||||
flex-basis: 50%;
|
||||
max-width: 50%;
|
||||
}
|
||||
|
||||
.trix-content action-text-attachment .attachment {
|
||||
padding: 0 !important;
|
||||
max-width: 100% !important;
|
||||
}
|
|
@ -7,4 +7,5 @@
|
|||
*= require list.unlist
|
||||
*= require list.missing
|
||||
*= require recurring_select
|
||||
*= require actiontext
|
||||
*/
|
||||
|
|
|
@ -3,39 +3,39 @@ class Admin::BankAccountsController < Admin::BaseController
|
|||
|
||||
def new
|
||||
@bank_account = BankAccount.new(params[:bank_account])
|
||||
render :layout => false
|
||||
render layout: false
|
||||
end
|
||||
|
||||
def edit
|
||||
@bank_account = BankAccount.find(params[:id])
|
||||
render action: 'new', layout: false
|
||||
end
|
||||
|
||||
def create
|
||||
@bank_account = BankAccount.new(params[:bank_account])
|
||||
if @bank_account.valid? && @bank_account.save
|
||||
redirect_to update_bank_accounts_admin_finances_url, :status => 303
|
||||
redirect_to update_bank_accounts_admin_finances_url, status: :see_other
|
||||
else
|
||||
render :action => 'new', :layout => false
|
||||
render action: 'new', layout: false
|
||||
end
|
||||
end
|
||||
|
||||
def edit
|
||||
@bank_account = BankAccount.find(params[:id])
|
||||
render :action => 'new', :layout => false
|
||||
end
|
||||
|
||||
def update
|
||||
@bank_account = BankAccount.find(params[:id])
|
||||
|
||||
if @bank_account.update(params[:bank_account])
|
||||
redirect_to update_bank_accounts_admin_finances_url, :status => 303
|
||||
redirect_to update_bank_accounts_admin_finances_url, status: :see_other
|
||||
else
|
||||
render :action => 'new', :layout => false
|
||||
render action: 'new', layout: false
|
||||
end
|
||||
end
|
||||
|
||||
def destroy
|
||||
@bank_account = BankAccount.find(params[:id])
|
||||
@bank_account.destroy
|
||||
redirect_to update_bank_accounts_admin_finances_url, :status => 303
|
||||
rescue => error
|
||||
flash.now[:alert] = error.message
|
||||
redirect_to update_bank_accounts_admin_finances_url, status: :see_other
|
||||
rescue StandardError => e
|
||||
flash.now[:alert] = e.message
|
||||
render template: 'shared/alert'
|
||||
end
|
||||
end
|
||||
|
|
|
@ -6,6 +6,11 @@ class Admin::BankGatewaysController < Admin::BaseController
|
|||
render layout: false
|
||||
end
|
||||
|
||||
def edit
|
||||
@bank_gateway = BankGateway.find(params[:id])
|
||||
render action: 'new', layout: false
|
||||
end
|
||||
|
||||
def create
|
||||
@bank_gateway = BankGateway.new(params[:bank_gateway])
|
||||
if @bank_gateway.valid? && @bank_gateway.save
|
||||
|
@ -15,11 +20,6 @@ class Admin::BankGatewaysController < Admin::BaseController
|
|||
end
|
||||
end
|
||||
|
||||
def edit
|
||||
@bank_gateway = BankGateway.find(params[:id])
|
||||
render action: 'new', layout: false
|
||||
end
|
||||
|
||||
def update
|
||||
@bank_gateway = BankGateway.find(params[:id])
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
class Admin::ConfigsController < Admin::BaseController
|
||||
before_action :get_tabs, only: [:show, :list]
|
||||
before_action :get_tabs, only: %i[show list]
|
||||
|
||||
def show
|
||||
@current_tab = @tabs.include?(params[:tab]) ? params[:tab] : @tabs.first
|
||||
|
@ -16,7 +16,7 @@ class Admin::ConfigsController < Admin::BaseController
|
|||
def update
|
||||
parse_recurring_selects! params[:config][:order_schedule]
|
||||
ActiveRecord::Base.transaction do
|
||||
# TODO support nested configuration keys
|
||||
# TODO: support nested configuration keys
|
||||
params[:config].each do |key, val|
|
||||
FoodsoftConfig[key] = convert_config_value val
|
||||
end
|
||||
|
@ -29,7 +29,7 @@ class Admin::ConfigsController < Admin::BaseController
|
|||
|
||||
# Set configuration tab names as `@tabs`
|
||||
def get_tabs
|
||||
@tabs = %w(foodcoop payment tasks messages layout language security others)
|
||||
@tabs = %w[foodcoop payment tasks messages layout language security others]
|
||||
# allow engines to modify this list
|
||||
engines = Rails::Engine.subclasses.map(&:instance).select { |e| e.respond_to?(:configuration) }
|
||||
engines.each { |e| e.configuration(@tabs, self) }
|
||||
|
@ -38,16 +38,16 @@ class Admin::ConfigsController < Admin::BaseController
|
|||
|
||||
# turn recurring rules into something palatable
|
||||
def parse_recurring_selects!(config)
|
||||
if config
|
||||
for k in [:pickup, :boxfill, :ends] do
|
||||
if config[k]
|
||||
# allow clearing it using dummy value '{}' ('' would break recurring_select)
|
||||
if config[k][:recurr].present? && config[k][:recurr] != '{}'
|
||||
config[k][:recurr] = ActiveSupport::JSON.decode(config[k][:recurr])
|
||||
config[k][:recurr] = FoodsoftDateUtil.rule_from(config[k][:recurr]).to_ical if config[k][:recurr]
|
||||
else
|
||||
config[k] = nil
|
||||
end
|
||||
return unless config
|
||||
|
||||
for k in %i[pickup boxfill ends] do
|
||||
if config[k]
|
||||
# allow clearing it using dummy value '{}' ('' would break recurring_select)
|
||||
if config[k][:recurr].present? && config[k][:recurr] != '{}'
|
||||
config[k][:recurr] = ActiveSupport::JSON.decode(config[k][:recurr])
|
||||
config[k][:recurr] = FoodsoftDateUtil.rule_from(config[k][:recurr]).to_ical if config[k][:recurr]
|
||||
else
|
||||
config[k] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -10,21 +10,21 @@ class Admin::FinancesController < Admin::BaseController
|
|||
|
||||
def update_bank_accounts
|
||||
@bank_accounts = BankAccount.order('name')
|
||||
render :layout => false
|
||||
render layout: false
|
||||
end
|
||||
|
||||
def update_bank_gateways
|
||||
@bank_gateways = BankGateway.order('name')
|
||||
render :layout => false
|
||||
render layout: false
|
||||
end
|
||||
|
||||
def update_transaction_types
|
||||
@financial_transaction_classes = FinancialTransactionClass.includes(:financial_transaction_types).order('name ASC')
|
||||
render :layout => false
|
||||
render layout: false
|
||||
end
|
||||
|
||||
def update_supplier_categories
|
||||
@supplier_categories = SupplierCategory.order('name')
|
||||
render :layout => false
|
||||
render layout: false
|
||||
end
|
||||
end
|
||||
|
|
|
@ -6,25 +6,25 @@ class Admin::FinancialTransactionClassesController < Admin::BaseController
|
|||
render layout: false
|
||||
end
|
||||
|
||||
def create
|
||||
@financial_transaction_class = FinancialTransactionClass.new(params[:financial_transaction_class])
|
||||
if @financial_transaction_class.save
|
||||
redirect_to update_transaction_types_admin_finances_url, status: 303
|
||||
else
|
||||
render action: 'new', layout: false
|
||||
end
|
||||
end
|
||||
|
||||
def edit
|
||||
@financial_transaction_class = FinancialTransactionClass.find(params[:id])
|
||||
render action: 'new', layout: false
|
||||
end
|
||||
|
||||
def create
|
||||
@financial_transaction_class = FinancialTransactionClass.new(params[:financial_transaction_class])
|
||||
if @financial_transaction_class.save
|
||||
redirect_to update_transaction_types_admin_finances_url, status: :see_other
|
||||
else
|
||||
render action: 'new', layout: false
|
||||
end
|
||||
end
|
||||
|
||||
def update
|
||||
@financial_transaction_class = FinancialTransactionClass.find(params[:id])
|
||||
|
||||
if @financial_transaction_class.update(params[:financial_transaction_class])
|
||||
redirect_to update_transaction_types_admin_finances_url, status: 303
|
||||
redirect_to update_transaction_types_admin_finances_url, status: :see_other
|
||||
else
|
||||
render action: 'new', layout: false
|
||||
end
|
||||
|
@ -33,9 +33,9 @@ class Admin::FinancialTransactionClassesController < Admin::BaseController
|
|||
def destroy
|
||||
@financial_transaction_class = FinancialTransactionClass.find(params[:id])
|
||||
@financial_transaction_class.destroy!
|
||||
redirect_to update_transaction_types_admin_finances_url, status: 303
|
||||
rescue => error
|
||||
flash.now[:alert] = error.message
|
||||
redirect_to update_transaction_types_admin_finances_url, status: :see_other
|
||||
rescue StandardError => e
|
||||
flash.now[:alert] = e.message
|
||||
render template: 'shared/alert'
|
||||
end
|
||||
end
|
||||
|
|
|
@ -7,25 +7,25 @@ class Admin::FinancialTransactionTypesController < Admin::BaseController
|
|||
render layout: false
|
||||
end
|
||||
|
||||
def create
|
||||
@financial_transaction_type = FinancialTransactionType.new(params[:financial_transaction_type])
|
||||
if @financial_transaction_type.save
|
||||
redirect_to update_transaction_types_admin_finances_url, status: 303
|
||||
else
|
||||
render action: 'new', layout: false
|
||||
end
|
||||
end
|
||||
|
||||
def edit
|
||||
@financial_transaction_type = FinancialTransactionType.find(params[:id])
|
||||
render action: 'new', layout: false
|
||||
end
|
||||
|
||||
def create
|
||||
@financial_transaction_type = FinancialTransactionType.new(params[:financial_transaction_type])
|
||||
if @financial_transaction_type.save
|
||||
redirect_to update_transaction_types_admin_finances_url, status: :see_other
|
||||
else
|
||||
render action: 'new', layout: false
|
||||
end
|
||||
end
|
||||
|
||||
def update
|
||||
@financial_transaction_type = FinancialTransactionType.find(params[:id])
|
||||
|
||||
if @financial_transaction_type.update(params[:financial_transaction_type])
|
||||
redirect_to update_transaction_types_admin_finances_url, status: 303
|
||||
redirect_to update_transaction_types_admin_finances_url, status: :see_other
|
||||
else
|
||||
render action: 'new', layout: false
|
||||
end
|
||||
|
@ -34,9 +34,9 @@ class Admin::FinancialTransactionTypesController < Admin::BaseController
|
|||
def destroy
|
||||
@financial_transaction_type = FinancialTransactionType.find(params[:id])
|
||||
@financial_transaction_type.destroy!
|
||||
redirect_to update_transaction_types_admin_finances_url, status: 303
|
||||
rescue => error
|
||||
flash.now[:alert] = error.message
|
||||
redirect_to update_transaction_types_admin_finances_url, status: :see_other
|
||||
rescue StandardError => e
|
||||
flash.now[:alert] = e.message
|
||||
render template: 'shared/alert'
|
||||
end
|
||||
end
|
||||
|
|
|
@ -3,28 +3,28 @@ class Admin::MailDeliveryStatusController < Admin::BaseController
|
|||
|
||||
def index
|
||||
@maildeliverystatus = MailDeliveryStatus.order(created_at: :desc)
|
||||
@maildeliverystatus = @maildeliverystatus.where(email: params[:email]) unless params[:email].blank?
|
||||
@maildeliverystatus = @maildeliverystatus.where(email: params[:email]) if params[:email].present?
|
||||
@maildeliverystatus = @maildeliverystatus.page(params[:page]).per(@per_page)
|
||||
end
|
||||
|
||||
def show
|
||||
@maildeliverystatus = MailDeliveryStatus.find(params[:id])
|
||||
filename = "maildeliverystatus_#{params[:id]}.#{MIME::Types[@maildeliverystatus.attachment_mime].first.preferred_extension}"
|
||||
send_data(@maildeliverystatus.attachment_data, :filename => filename, :type => @maildeliverystatus.attachment_mime)
|
||||
send_data(@maildeliverystatus.attachment_data, filename: filename, type: @maildeliverystatus.attachment_mime)
|
||||
end
|
||||
|
||||
def destroy_all
|
||||
@maildeliverystatus = MailDeliveryStatus.delete_all
|
||||
redirect_to admin_mail_delivery_status_index_path, notice: t('.notice')
|
||||
rescue => error
|
||||
redirect_to admin_mail_delivery_status_index_path, alert: I18n.t('errors.general_msg', msg: error.message)
|
||||
rescue StandardError => e
|
||||
redirect_to admin_mail_delivery_status_index_path, alert: I18n.t('errors.general_msg', msg: e.message)
|
||||
end
|
||||
|
||||
def destroy
|
||||
@maildeliverystatus = MailDeliveryStatus.find(params[:id])
|
||||
@maildeliverystatus.destroy
|
||||
redirect_to admin_mail_delivery_status_index_path, notice: t('.notice')
|
||||
rescue => error
|
||||
redirect_to admin_mail_delivery_status_index_path, alert: I18n.t('errors.general_msg', msg: error.message)
|
||||
rescue StandardError => e
|
||||
redirect_to admin_mail_delivery_status_index_path, alert: I18n.t('errors.general_msg', msg: e.message)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -2,16 +2,15 @@ class Admin::OrdergroupsController < Admin::BaseController
|
|||
inherit_resources
|
||||
|
||||
def index
|
||||
@ordergroups = Ordergroup.undeleted.sort_by_param(params["sort"])
|
||||
@ordergroups = Ordergroup.undeleted.sort_by_param(params['sort'])
|
||||
|
||||
if request.format.csv?
|
||||
send_data OrdergroupsCsv.new(@ordergroups).to_csv, filename: 'ordergroups.csv', type: 'text/csv'
|
||||
send_data OrdergroupsCsv.new(@ordergroups).to_csv, filename: 'ordergroups.csv',
|
||||
type: 'text/csv'
|
||||
end
|
||||
|
||||
# if somebody uses the search field:
|
||||
unless params[:query].blank?
|
||||
@ordergroups = @ordergroups.where('name LIKE ?', "%#{params[:query]}%")
|
||||
end
|
||||
@ordergroups = @ordergroups.where('name LIKE ?', "%#{params[:query]}%") if params[:query].present?
|
||||
|
||||
@ordergroups = @ordergroups.page(params[:page]).per(@per_page)
|
||||
end
|
||||
|
@ -19,8 +18,8 @@ class Admin::OrdergroupsController < Admin::BaseController
|
|||
def destroy
|
||||
@ordergroup = Ordergroup.find(params[:id])
|
||||
@ordergroup.mark_as_deleted
|
||||
redirect_to admin_ordergroups_url, notice: t('admin.ordergroups.destroy.notice')
|
||||
rescue => error
|
||||
redirect_to admin_ordergroups_url, alert: t('admin.ordergroups.destroy.error')
|
||||
redirect_to admin_ordergroups_url, notice: t('.notice')
|
||||
rescue StandardError => e
|
||||
redirect_to admin_ordergroups_url, alert: t('.error')
|
||||
end
|
||||
end
|
||||
|
|
|
@ -6,6 +6,11 @@ class Admin::SupplierCategoriesController < Admin::BaseController
|
|||
render layout: false
|
||||
end
|
||||
|
||||
def edit
|
||||
@supplier_category = SupplierCategory.find(params[:id])
|
||||
render action: 'new', layout: false
|
||||
end
|
||||
|
||||
def create
|
||||
@supplier_category = SupplierCategory.new(params[:supplier_category])
|
||||
if @supplier_category.valid? && @supplier_category.save
|
||||
|
@ -15,11 +20,6 @@ class Admin::SupplierCategoriesController < Admin::BaseController
|
|||
end
|
||||
end
|
||||
|
||||
def edit
|
||||
@supplier_category = SupplierCategory.find(params[:id])
|
||||
render action: 'new', layout: false
|
||||
end
|
||||
|
||||
def update
|
||||
@supplier_category = SupplierCategory.find(params[:id])
|
||||
|
||||
|
|
|
@ -3,16 +3,14 @@ class Admin::UsersController < Admin::BaseController
|
|||
|
||||
def index
|
||||
@users = params[:show_deleted] ? User.deleted : User.undeleted
|
||||
@users = @users.sort_by_param(params["sort"])
|
||||
@users = @users.sort_by_param(params['sort'])
|
||||
|
||||
@users = @users.includes(:mail_delivery_status)
|
||||
|
||||
if request.format.csv?
|
||||
send_data UsersCsv.new(@users).to_csv, filename: 'users.csv', type: 'text/csv'
|
||||
end
|
||||
send_data UsersCsv.new(@users).to_csv, filename: 'users.csv', type: 'text/csv' if request.format.csv?
|
||||
|
||||
# if somebody uses the search field:
|
||||
@users = @users.natural_search(params[:user_name]) unless params[:user_name].blank?
|
||||
@users = @users.natural_search(params[:user_name]) if params[:user_name].present?
|
||||
|
||||
@users = @users.page(params[:page]).per(@per_page)
|
||||
end
|
||||
|
@ -20,17 +18,17 @@ class Admin::UsersController < Admin::BaseController
|
|||
def destroy
|
||||
@user = User.find(params[:id])
|
||||
@user.mark_as_deleted
|
||||
redirect_to admin_users_url, notice: t('admin.users.destroy.notice')
|
||||
rescue => error
|
||||
redirect_to admin_users_url, alert: t('admin.users.destroy.error', error: error.message)
|
||||
redirect_to admin_users_url, notice: t('.notice')
|
||||
rescue StandardError => e
|
||||
redirect_to admin_users_url, alert: t('.error', error: e.message)
|
||||
end
|
||||
|
||||
def restore
|
||||
@user = User.find(params[:id])
|
||||
@user.restore
|
||||
redirect_to admin_users_url, notice: t('admin.users.restore.notice')
|
||||
rescue => error
|
||||
redirect_to admin_users_url, alert: t('admin.users.restore.error', error: error.message)
|
||||
redirect_to admin_users_url, notice: t('.notice')
|
||||
rescue StandardError => e
|
||||
redirect_to admin_users_url, alert: t('.error', error: e.message)
|
||||
end
|
||||
|
||||
def sudo
|
||||
|
|
|
@ -4,7 +4,7 @@ class Admin::WorkgroupsController < Admin::BaseController
|
|||
def index
|
||||
@workgroups = Workgroup.order('name ASC')
|
||||
# if somebody uses the search field:
|
||||
@workgroups = @workgroups.where('name LIKE ?', "%#{params[:query]}%") unless params[:query].blank?
|
||||
@workgroups = @workgroups.where('name LIKE ?', "%#{params[:query]}%") if params[:query].present?
|
||||
|
||||
@workgroups = @workgroups.page(params[:page]).per(@per_page)
|
||||
end
|
||||
|
@ -12,8 +12,8 @@ class Admin::WorkgroupsController < Admin::BaseController
|
|||
def destroy
|
||||
@workgroup = Workgroup.find(params[:id])
|
||||
@workgroup.destroy
|
||||
redirect_to admin_workgroups_url, notice: t('admin.workgroups.destroy.notice')
|
||||
rescue => error
|
||||
redirect_to admin_workgroups_url, alert: t('admin.workgroups.destroy.error', error: error.message)
|
||||
redirect_to admin_workgroups_url, notice: t('.notice')
|
||||
rescue StandardError => e
|
||||
redirect_to admin_workgroups_url, alert: t('.error', error: e.message)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -20,29 +20,30 @@ class Api::V1::BaseController < ApplicationController
|
|||
|
||||
def require_ordergroup
|
||||
authenticate
|
||||
unless current_ordergroup.present?
|
||||
raise Api::Errors::PermissionRequired.new('Forbidden, must be in an ordergroup')
|
||||
end
|
||||
return if current_ordergroup.present?
|
||||
|
||||
raise Api::Errors::PermissionRequired, 'Forbidden, must be in an ordergroup'
|
||||
end
|
||||
|
||||
def require_minimum_balance
|
||||
minimum_balance = FoodsoftConfig[:minimum_balance] or return
|
||||
if current_ordergroup.account_balance < minimum_balance
|
||||
raise Api::Errors::PermissionRequired.new(t('application.controller.error_minimum_balance', min: minimum_balance))
|
||||
end
|
||||
return unless current_ordergroup.account_balance < minimum_balance
|
||||
|
||||
raise Api::Errors::PermissionRequired, t('application.controller.error_minimum_balance', min: minimum_balance)
|
||||
end
|
||||
|
||||
def require_enough_apples
|
||||
if current_ordergroup.not_enough_apples?
|
||||
s = t('group_orders.messages.not_enough_apples', apples: current_ordergroup.apples, stop_ordering_under: FoodsoftConfig[:stop_ordering_under])
|
||||
raise Api::Errors::PermissionRequired.new(s)
|
||||
end
|
||||
return unless current_ordergroup.not_enough_apples?
|
||||
|
||||
s = t('group_orders.messages.not_enough_apples', apples: current_ordergroup.apples,
|
||||
stop_ordering_under: FoodsoftConfig[:stop_ordering_under])
|
||||
raise Api::Errors::PermissionRequired, s
|
||||
end
|
||||
|
||||
def require_config_enabled(config)
|
||||
unless FoodsoftConfig[config]
|
||||
raise Api::Errors::PermissionRequired.new(t('application.controller.error_not_enabled', config: config))
|
||||
end
|
||||
return if FoodsoftConfig[config]
|
||||
|
||||
raise Api::Errors::PermissionRequired, t('application.controller.error_not_enabled', config: config)
|
||||
end
|
||||
|
||||
def skip_session
|
||||
|
@ -52,12 +53,12 @@ class Api::V1::BaseController < ApplicationController
|
|||
def not_found_handler(e)
|
||||
# remove where-clauses from error message (not suitable for end-users)
|
||||
msg = e.message.try { |m| m.sub(/\s*\[.*?\]\s*$/, '') } || 'Not found'
|
||||
render status: 404, json: { error: 'not_found', error_description: msg }
|
||||
render status: :not_found, json: { error: 'not_found', error_description: msg }
|
||||
end
|
||||
|
||||
def not_acceptable_handler(e)
|
||||
msg = e.message || 'Data not acceptable'
|
||||
render status: 422, json: { error: 'not_acceptable', error_description: msg }
|
||||
render status: :unprocessable_entity, json: { error: 'not_acceptable', error_description: msg }
|
||||
end
|
||||
|
||||
def doorkeeper_unauthorized_render_options(error:)
|
||||
|
@ -70,11 +71,11 @@ class Api::V1::BaseController < ApplicationController
|
|||
|
||||
def permission_required_handler(e)
|
||||
msg = e.message || 'Forbidden, user has no access'
|
||||
render status: 403, json: { error: 'forbidden', error_description: msg }
|
||||
render status: :forbidden, json: { error: 'forbidden', error_description: msg }
|
||||
end
|
||||
|
||||
# @todo something with ApplicationHelper#show_user
|
||||
def show_user(user = current_user, **options)
|
||||
def show_user(user = current_user, **_options)
|
||||
user.display
|
||||
end
|
||||
end
|
||||
|
|
|
@ -16,7 +16,8 @@ class Api::V1::User::FinancialTransactionsController < Api::V1::BaseController
|
|||
|
||||
def create
|
||||
transaction_type = FinancialTransactionType.find(create_params[:financial_transaction_type_id])
|
||||
ft = current_ordergroup.add_financial_transaction!(create_params[:amount], create_params[:note], current_user, transaction_type)
|
||||
ft = current_ordergroup.add_financial_transaction!(create_params[:amount], create_params[:note], current_user,
|
||||
transaction_type)
|
||||
render json: ft
|
||||
end
|
||||
|
||||
|
|
|
@ -4,8 +4,8 @@ class Api::V1::User::GroupOrderArticlesController < Api::V1::BaseController
|
|||
before_action -> { doorkeeper_authorize! 'group_orders:user' }
|
||||
|
||||
before_action :require_ordergroup
|
||||
before_action :require_minimum_balance, only: [:create, :update] # destroy is ok
|
||||
before_action :require_enough_apples, only: [:create, :update] # destroy is ok
|
||||
before_action :require_minimum_balance, only: %i[create update] # destroy is ok
|
||||
before_action :require_enough_apples, only: %i[create update] # destroy is ok
|
||||
# @todo allow decreasing amounts when minimum balance isn't met
|
||||
|
||||
def index
|
||||
|
@ -35,7 +35,8 @@ class Api::V1::User::GroupOrderArticlesController < Api::V1::BaseController
|
|||
goa = nil
|
||||
GroupOrderArticle.transaction do
|
||||
goa = scope_for_update.includes(:group_order_article_quantities).find(params.require(:id))
|
||||
goa.update_quantities((update_params[:quantity] || goa.quantity).to_i, (update_params[:tolerance] || goa.tolerance).to_i)
|
||||
goa.update_quantities((update_params[:quantity] || goa.quantity).to_i,
|
||||
(update_params[:tolerance] || goa.tolerance).to_i)
|
||||
goa.order_article.update_results!
|
||||
goa.group_order.update_price!
|
||||
goa.group_order.update!(updated_by: current_user)
|
||||
|
|
|
@ -8,13 +8,13 @@ class Api::V1::User::OrdergroupController < Api::V1::BaseController
|
|||
financial_overview: {
|
||||
account_balance: ordergroup.account_balance.to_f,
|
||||
available_funds: ordergroup.get_available_funds.to_f,
|
||||
financial_transaction_class_sums: FinancialTransactionClass.sorted.map { |c|
|
||||
financial_transaction_class_sums: FinancialTransactionClass.sorted.map do |c|
|
||||
{
|
||||
id: c.id,
|
||||
name: c.display,
|
||||
amount: ordergroup["sum_of_class_#{c.id}"].to_f
|
||||
}
|
||||
}
|
||||
end
|
||||
}
|
||||
}
|
||||
end
|
||||
|
|
|
@ -19,10 +19,10 @@ class ApplicationController < ActionController::Base
|
|||
private
|
||||
|
||||
def set_user_last_activity
|
||||
if current_user && (session[:last_activity] == nil || session[:last_activity] < 1.minutes.ago)
|
||||
current_user.update_attribute(:last_activity, Time.now)
|
||||
session[:last_activity] = Time.now
|
||||
end
|
||||
return unless current_user && (session[:last_activity].nil? || session[:last_activity] < 1.minute.ago)
|
||||
|
||||
current_user.update_attribute(:last_activity, Time.now)
|
||||
session[:last_activity] = Time.now
|
||||
end
|
||||
|
||||
# Many plugins can be turned on and off on the fly with a `use_` configuration option.
|
||||
|
@ -64,11 +64,11 @@ class ApplicationController < ActionController::Base
|
|||
end
|
||||
|
||||
def items_per_page
|
||||
if params[:per_page] && params[:per_page].to_i > 0 && params[:per_page].to_i <= 500
|
||||
@per_page = params[:per_page].to_i
|
||||
else
|
||||
@per_page = 20
|
||||
end
|
||||
@per_page = if params[:per_page] && params[:per_page].to_i > 0 && params[:per_page].to_i <= 500
|
||||
params[:per_page].to_i
|
||||
else
|
||||
20
|
||||
end
|
||||
end
|
||||
|
||||
# Set timezone according to foodcoop preference.
|
||||
|
|
|
@ -4,17 +4,17 @@ class ArticleCategoriesController < ApplicationController
|
|||
before_action :authenticate_article_meta
|
||||
|
||||
def create
|
||||
create!(:notice => I18n.t('article_categories.create.notice')) { article_categories_path }
|
||||
create!(notice: I18n.t('article_categories.create.notice')) { article_categories_path }
|
||||
end
|
||||
|
||||
def update
|
||||
update!(:notice => I18n.t('article_categories.update.notice')) { article_categories_path }
|
||||
update!(notice: I18n.t('article_categories.update.notice')) { article_categories_path }
|
||||
end
|
||||
|
||||
def destroy
|
||||
destroy!
|
||||
rescue => error
|
||||
redirect_to article_categories_path, alert: I18n.t('article_categories.destroy.error', message: error.message)
|
||||
rescue StandardError => e
|
||||
redirect_to article_categories_path, alert: I18n.t('article_categories.destroy.error', message: e.message)
|
||||
end
|
||||
|
||||
protected
|
||||
|
|
|
@ -2,24 +2,24 @@ class ArticlesController < ApplicationController
|
|||
before_action :authenticate_article_meta, :find_supplier
|
||||
|
||||
def index
|
||||
if params['sort']
|
||||
sort = case params['sort']
|
||||
when "name" then "articles.name"
|
||||
when "unit" then "articles.unit"
|
||||
when "article_category" then "article_categories.name"
|
||||
when "note" then "articles.note"
|
||||
when "availability" then "articles.availability"
|
||||
when "name_reverse" then "articles.name DESC"
|
||||
when "unit_reverse" then "articles.unit DESC"
|
||||
when "article_category_reverse" then "article_categories.name DESC"
|
||||
when "note_reverse" then "articles.note DESC"
|
||||
when "availability_reverse" then "articles.availability DESC"
|
||||
sort = if params['sort']
|
||||
case params['sort']
|
||||
when 'name' then 'articles.name'
|
||||
when 'unit' then 'articles.unit'
|
||||
when 'article_category' then 'article_categories.name'
|
||||
when 'note' then 'articles.note'
|
||||
when 'availability' then 'articles.availability'
|
||||
when 'name_reverse' then 'articles.name DESC'
|
||||
when 'unit_reverse' then 'articles.unit DESC'
|
||||
when 'article_category_reverse' then 'article_categories.name DESC'
|
||||
when 'note_reverse' then 'articles.note DESC'
|
||||
when 'availability_reverse' then 'articles.availability DESC'
|
||||
end
|
||||
else
|
||||
sort = "article_categories.name, articles.name"
|
||||
end
|
||||
else
|
||||
'article_categories.name, articles.name'
|
||||
end
|
||||
|
||||
@articles = Article.undeleted.where(supplier_id: @supplier, :type => nil).includes(:article_category).order(sort)
|
||||
@articles = Article.undeleted.where(supplier_id: @supplier, type: nil).includes(:article_category).order(sort)
|
||||
|
||||
if request.format.csv?
|
||||
send_data ArticlesCsv.new(@articles, encoding: 'utf-8').to_csv, filename: 'articles.csv', type: 'text/csv'
|
||||
|
@ -32,42 +32,42 @@ class ArticlesController < ApplicationController
|
|||
|
||||
respond_to do |format|
|
||||
format.html
|
||||
format.js { render :layout => false }
|
||||
format.js { render layout: false }
|
||||
end
|
||||
end
|
||||
|
||||
def new
|
||||
@article = @supplier.articles.build(:tax => FoodsoftConfig[:tax_default])
|
||||
render :layout => false
|
||||
@article = @supplier.articles.build(tax: FoodsoftConfig[:tax_default])
|
||||
render layout: false
|
||||
end
|
||||
|
||||
def copy
|
||||
@article = @supplier.articles.find(params[:article_id]).dup
|
||||
render :layout => false
|
||||
render layout: false
|
||||
end
|
||||
|
||||
def edit
|
||||
@article = Article.find(params[:id])
|
||||
render action: 'new', layout: false
|
||||
end
|
||||
|
||||
def create
|
||||
@article = Article.new(params[:article])
|
||||
if @article.valid? && @article.save
|
||||
render :layout => false
|
||||
render layout: false
|
||||
else
|
||||
render :action => 'new', :layout => false
|
||||
render action: 'new', layout: false
|
||||
end
|
||||
end
|
||||
|
||||
def edit
|
||||
@article = Article.find(params[:id])
|
||||
render :action => 'new', :layout => false
|
||||
end
|
||||
|
||||
# Updates one Article and highlights the line if succeded
|
||||
def update
|
||||
@article = Article.find(params[:id])
|
||||
|
||||
if @article.update(params[:article])
|
||||
render :layout => false
|
||||
render layout: false
|
||||
else
|
||||
render :action => 'new', :layout => false
|
||||
render action: 'new', layout: false
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -75,7 +75,7 @@ class ArticlesController < ApplicationController
|
|||
def destroy
|
||||
@article = Article.find(params[:id])
|
||||
@article.mark_as_deleted unless @order = @article.in_open_order # If article is in an active Order, the Order will be returned
|
||||
render :layout => false
|
||||
render layout: false
|
||||
end
|
||||
|
||||
# Renders a form for editing all articles from a supplier
|
||||
|
@ -87,19 +87,17 @@ class ArticlesController < ApplicationController
|
|||
def update_all
|
||||
invalid_articles = false
|
||||
|
||||
begin
|
||||
Article.transaction do
|
||||
unless params[:articles].blank?
|
||||
# Update other article attributes...
|
||||
@articles = Article.find(params[:articles].keys)
|
||||
@articles.each do |article|
|
||||
unless article.update(params[:articles][article.id.to_s])
|
||||
invalid_articles = true unless invalid_articles # Remember that there are validation errors
|
||||
end
|
||||
Article.transaction do
|
||||
if params[:articles].present?
|
||||
# Update other article attributes...
|
||||
@articles = Article.find(params[:articles].keys)
|
||||
@articles.each do |article|
|
||||
unless article.update(params[:articles][article.id.to_s])
|
||||
invalid_articles ||= true # Remember that there are validation errors
|
||||
end
|
||||
|
||||
raise ActiveRecord::Rollback if invalid_articles # Rollback all changes
|
||||
end
|
||||
|
||||
raise ActiveRecord::Rollback if invalid_articles # Rollback all changes
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -134,16 +132,15 @@ class ArticlesController < ApplicationController
|
|||
end
|
||||
end
|
||||
# action succeded
|
||||
redirect_to supplier_articles_url(@supplier, :per_page => params[:per_page])
|
||||
rescue => error
|
||||
redirect_to supplier_articles_url(@supplier, :per_page => params[:per_page]),
|
||||
:alert => I18n.t('errors.general_msg', :msg => error)
|
||||
redirect_to supplier_articles_url(@supplier, per_page: params[:per_page])
|
||||
rescue StandardError => e
|
||||
redirect_to supplier_articles_url(@supplier, per_page: params[:per_page]),
|
||||
alert: I18n.t('errors.general_msg', msg: e)
|
||||
end
|
||||
|
||||
# lets start with parsing articles from uploaded file, yeah
|
||||
# Renders the upload form
|
||||
def upload
|
||||
end
|
||||
def upload; end
|
||||
|
||||
# Update articles from a spreadsheet
|
||||
def parse_upload
|
||||
|
@ -151,13 +148,15 @@ class ArticlesController < ApplicationController
|
|||
options = { filename: uploaded_file.original_filename }
|
||||
options[:outlist_absent] = (params[:articles]['outlist_absent'] == '1')
|
||||
options[:convert_units] = (params[:articles]['convert_units'] == '1')
|
||||
@updated_article_pairs, @outlisted_articles, @new_articles = @supplier.sync_from_file uploaded_file.tempfile, options
|
||||
@updated_article_pairs, @outlisted_articles, @new_articles = @supplier.sync_from_file uploaded_file.tempfile,
|
||||
options
|
||||
if @updated_article_pairs.empty? && @outlisted_articles.empty? && @new_articles.empty?
|
||||
redirect_to supplier_articles_path(@supplier), :notice => I18n.t('articles.controller.parse_upload.notice')
|
||||
redirect_to supplier_articles_path(@supplier),
|
||||
notice: I18n.t('articles.controller.parse_upload.notice')
|
||||
end
|
||||
@ignored_article_count = 0
|
||||
rescue => error
|
||||
redirect_to upload_supplier_articles_path(@supplier), :alert => I18n.t('errors.general_msg', :msg => error.message)
|
||||
rescue StandardError => e
|
||||
redirect_to upload_supplier_articles_path(@supplier), alert: I18n.t('errors.general_msg', msg: e.message)
|
||||
end
|
||||
|
||||
# sync all articles with the external database
|
||||
|
@ -165,13 +164,14 @@ class ArticlesController < ApplicationController
|
|||
def sync
|
||||
# check if there is an shared_supplier
|
||||
unless @supplier.shared_supplier
|
||||
redirect_to supplier_articles_url(@supplier), :alert => I18n.t('articles.controller.sync.shared_alert', :supplier => @supplier.name)
|
||||
redirect_to supplier_articles_url(@supplier),
|
||||
alert: I18n.t('articles.controller.sync.shared_alert', supplier: @supplier.name)
|
||||
end
|
||||
# sync articles against external database
|
||||
@updated_article_pairs, @outlisted_articles, @new_articles = @supplier.sync_all
|
||||
if @updated_article_pairs.empty? && @outlisted_articles.empty? && @new_articles.empty?
|
||||
redirect_to supplier_articles_path(@supplier), :notice => I18n.t('articles.controller.sync.notice')
|
||||
end
|
||||
return unless @updated_article_pairs.empty? && @outlisted_articles.empty? && @new_articles.empty?
|
||||
|
||||
redirect_to supplier_articles_path(@supplier), notice: I18n.t('articles.controller.sync.notice')
|
||||
end
|
||||
|
||||
# Updates, deletes articles when upload or sync form is submitted
|
||||
|
@ -186,7 +186,7 @@ class ArticlesController < ApplicationController
|
|||
# delete articles
|
||||
begin
|
||||
@outlisted_articles.each(&:mark_as_deleted)
|
||||
rescue
|
||||
rescue StandardError
|
||||
# raises an exception when used in current order
|
||||
has_error = true
|
||||
end
|
||||
|
@ -198,15 +198,15 @@ class ArticlesController < ApplicationController
|
|||
raise ActiveRecord::Rollback if has_error
|
||||
end
|
||||
|
||||
if !has_error
|
||||
redirect_to supplier_articles_path(@supplier), notice: I18n.t('articles.controller.update_sync.notice')
|
||||
else
|
||||
if has_error
|
||||
@updated_article_pairs = @updated_articles.map do |article|
|
||||
orig_article = Article.find(article.id)
|
||||
[article, orig_article.unequal_attributes(article)]
|
||||
end
|
||||
flash.now.alert = I18n.t('articles.controller.error_invalid')
|
||||
render params[:from_action] == 'sync' ? :sync : :parse_upload
|
||||
else
|
||||
redirect_to supplier_articles_path(@supplier), notice: I18n.t('articles.controller.update_sync.notice')
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -218,18 +218,18 @@ class ArticlesController < ApplicationController
|
|||
q[:name_cont_all] = params.fetch(:name_cont_all_joined, '').split(' ')
|
||||
search = @supplier.shared_supplier.shared_articles.ransack(q)
|
||||
@articles = search.result.page(params[:page]).per(10)
|
||||
render :layout => false
|
||||
render layout: false
|
||||
end
|
||||
|
||||
# fills a form whith values of the selected shared_article
|
||||
# when the direct parameter is set and the article is valid, it is imported directly
|
||||
def import
|
||||
@article = SharedArticle.find(params[:shared_article_id]).build_new_article(@supplier)
|
||||
@article.article_category_id = params[:article_category_id] unless params[:article_category_id].blank?
|
||||
if params[:direct] && !params[:article_category_id].blank? && @article.valid? && @article.save
|
||||
render :action => 'create', :layout => false
|
||||
@article.article_category_id = params[:article_category_id] if params[:article_category_id].present?
|
||||
if params[:direct] && params[:article_category_id].present? && @article.valid? && @article.save
|
||||
render action: 'create', layout: false
|
||||
else
|
||||
render :action => 'new', :layout => false
|
||||
render action: 'new', layout: false
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -9,15 +9,19 @@ module Concerns::Auth
|
|||
|
||||
def current_user
|
||||
# check if there is a valid session and return the logged-in user (its object)
|
||||
if session[:user_id] && params[:foodcoop]
|
||||
# for shared-host installations. check if the cookie-subdomain fits to request.
|
||||
@current_user ||= User.undeleted.find_by_id(session[:user_id]) if session[:scope] == FoodsoftConfig.scope
|
||||
end
|
||||
return unless session[:user_id] && params[:foodcoop]
|
||||
|
||||
# for shared-host installations. check if the cookie-subdomain fits to request.
|
||||
@current_user ||= User.undeleted.find_by_id(session[:user_id]) if session[:scope] == FoodsoftConfig.scope
|
||||
end
|
||||
|
||||
def deny_access
|
||||
session[:return_to] = request.original_url
|
||||
redirect_to root_url, alert: I18n.t('application.controller.error_denied', sign_in: ActionController::Base.helpers.link_to(t('application.controller.error_denied_sign_in'), login_path))
|
||||
redirect_to root_url,
|
||||
alert: I18n.t('application.controller.error_denied',
|
||||
sign_in: ActionController::Base.helpers.link_to(
|
||||
t('application.controller.error_denied_sign_in'), login_path
|
||||
))
|
||||
end
|
||||
|
||||
private
|
||||
|
@ -47,12 +51,7 @@ module Concerns::Auth
|
|||
|
||||
def authenticate(role = 'any')
|
||||
# Attempt to retrieve authenticated user from controller instance or session...
|
||||
if !current_user
|
||||
# No user at all: redirect to login page.
|
||||
logout
|
||||
session[:return_to] = request.original_url
|
||||
redirect_to_login :alert => I18n.t('application.controller.error_authn')
|
||||
else
|
||||
if current_user
|
||||
# We have an authenticated user, now check role...
|
||||
# Roles gets the user through his memberships.
|
||||
hasRole = case role
|
||||
|
@ -73,6 +72,11 @@ module Concerns::Auth
|
|||
else
|
||||
deny_access
|
||||
end
|
||||
else
|
||||
# No user at all: redirect to login page.
|
||||
logout
|
||||
session[:return_to] = request.original_url
|
||||
redirect_to_login alert: I18n.t('application.controller.error_authn')
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -116,13 +120,13 @@ module Concerns::Auth
|
|||
# if fails the user will redirected to startpage
|
||||
def authenticate_membership_or_admin(group_id = params[:id])
|
||||
@group = Group.find(group_id)
|
||||
unless @group.member?(@current_user) || @current_user.role_admin?
|
||||
redirect_to root_path, alert: I18n.t('application.controller.error_members_only')
|
||||
end
|
||||
return if @group.member?(@current_user) || @current_user.role_admin?
|
||||
|
||||
redirect_to root_path, alert: I18n.t('application.controller.error_members_only')
|
||||
end
|
||||
|
||||
def authenticate_or_token(prefix, role = 'any')
|
||||
if not params[:token].blank?
|
||||
if params[:token].present?
|
||||
begin
|
||||
TokenVerifier.new(prefix).verify(params[:token])
|
||||
rescue ActiveSupport::MessageVerifier::InvalidSignature
|
||||
|
|
|
@ -36,9 +36,9 @@ module Concerns::AuthApi
|
|||
# Make sure that at least one the given OAuth scopes is valid for the current user's permissions.
|
||||
# @raise Api::Errors::PermissionsRequired
|
||||
def doorkeeper_authorize_roles!(*scopes)
|
||||
unless scopes.any? { |scope| doorkeeper_scope_permitted?(scope) }
|
||||
raise Api::Errors::PermissionRequired.new('Forbidden, no permission')
|
||||
end
|
||||
return if scopes.any? { |scope| doorkeeper_scope_permitted?(scope) }
|
||||
|
||||
raise Api::Errors::PermissionRequired, 'Forbidden, no permission'
|
||||
end
|
||||
|
||||
# Check whether a given OAuth scope is permitted for the current user.
|
||||
|
@ -48,9 +48,7 @@ module Concerns::AuthApi
|
|||
def doorkeeper_scope_permitted?(scope)
|
||||
scope_parts = scope.split(':')
|
||||
# user sub-scopes like +config:user+ are always permitted
|
||||
if scope_parts.last == 'user'
|
||||
return true
|
||||
end
|
||||
return true if scope_parts.last == 'user'
|
||||
|
||||
case scope_parts.first
|
||||
when 'user' then return true # access to the current user's own profile
|
||||
|
@ -64,8 +62,8 @@ module Concerns::AuthApi
|
|||
end
|
||||
|
||||
case scope
|
||||
when 'orders:read' then return true
|
||||
when 'orders:write' then return current_user.role_orders?
|
||||
when 'orders:read' then true
|
||||
when 'orders:write' then current_user.role_orders?
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -24,12 +24,12 @@ module Concerns::FoodcoopScope
|
|||
elsif FoodsoftConfig.allowed_foodcoop? foodcoop
|
||||
FoodsoftConfig.select_foodcoop foodcoop
|
||||
else
|
||||
raise ActionController::RoutingError.new 'Foodcoop Not Found'
|
||||
raise ActionController::RoutingError, 'Foodcoop Not Found'
|
||||
end
|
||||
end
|
||||
|
||||
# Always stay in foodcoop url scope
|
||||
def default_url_options(options = {})
|
||||
def default_url_options(_options = {})
|
||||
super().merge({ foodcoop: FoodsoftConfig.scope })
|
||||
end
|
||||
end
|
||||
|
|
|
@ -18,7 +18,7 @@ module Concerns::Locale
|
|||
end
|
||||
|
||||
def browser_language
|
||||
request.env['HTTP_ACCEPT_LANGUAGE'] ? request.env['HTTP_ACCEPT_LANGUAGE'].scan(/^[a-z]{2}/).first : nil
|
||||
request.env['HTTP_ACCEPT_LANGUAGE']&.scan(/^[a-z]{2}/)&.first
|
||||
end
|
||||
|
||||
def default_language
|
||||
|
@ -30,7 +30,7 @@ module Concerns::Locale
|
|||
def select_language_according_to_priority
|
||||
language = explicitly_requested_language || session_language || user_settings_language
|
||||
language ||= browser_language unless FoodsoftConfig[:ignore_browser_locale]
|
||||
language.presence&.to_sym unless language.blank?
|
||||
language.presence&.to_sym if language.present?
|
||||
end
|
||||
|
||||
def available_locales
|
||||
|
@ -38,11 +38,11 @@ module Concerns::Locale
|
|||
end
|
||||
|
||||
def set_locale
|
||||
if available_locales.include?(select_language_according_to_priority)
|
||||
::I18n.locale = select_language_according_to_priority
|
||||
else
|
||||
::I18n.locale = default_language
|
||||
end
|
||||
::I18n.locale = if available_locales.include?(select_language_according_to_priority)
|
||||
select_language_according_to_priority
|
||||
else
|
||||
default_language
|
||||
end
|
||||
|
||||
locale = session[:locale] = ::I18n.locale
|
||||
logger.info("Set locale to #{locale}")
|
||||
|
|
|
@ -3,7 +3,7 @@ module Concerns::SendOrderPdf
|
|||
|
||||
protected
|
||||
|
||||
def send_order_pdf order, document
|
||||
def send_order_pdf(order, document)
|
||||
klass = case document
|
||||
when 'groups' then OrderByGroups
|
||||
when 'articles' then OrderByArticles
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
class DeliveriesController < ApplicationController
|
||||
before_action :find_supplier, :exclude => :fill_new_stock_article_form
|
||||
before_action :find_supplier, exclude: :fill_new_stock_article_form
|
||||
|
||||
def index
|
||||
@deliveries = @supplier.deliveries.order('date DESC')
|
||||
|
@ -15,6 +15,10 @@ class DeliveriesController < ApplicationController
|
|||
@delivery.date = Date.today # TODO: move to model/database
|
||||
end
|
||||
|
||||
def edit
|
||||
@delivery = Delivery.find(params[:id])
|
||||
end
|
||||
|
||||
def create
|
||||
@delivery = Delivery.new(params[:delivery])
|
||||
|
||||
|
@ -22,14 +26,10 @@ class DeliveriesController < ApplicationController
|
|||
flash[:notice] = I18n.t('deliveries.create.notice')
|
||||
redirect_to [@supplier, @delivery]
|
||||
else
|
||||
render :action => "new"
|
||||
render action: 'new'
|
||||
end
|
||||
end
|
||||
|
||||
def edit
|
||||
@delivery = Delivery.find(params[:id])
|
||||
end
|
||||
|
||||
def update
|
||||
@delivery = Delivery.find(params[:id])
|
||||
|
||||
|
@ -37,7 +37,7 @@ class DeliveriesController < ApplicationController
|
|||
flash[:notice] = I18n.t('deliveries.update.notice')
|
||||
redirect_to [@supplier, @delivery]
|
||||
else
|
||||
render :action => "edit"
|
||||
render action: 'edit'
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -52,18 +52,18 @@ class DeliveriesController < ApplicationController
|
|||
def add_stock_change
|
||||
@stock_change = StockChange.new
|
||||
@stock_change.stock_article = StockArticle.find(params[:stock_article_id])
|
||||
render :layout => false
|
||||
render layout: false
|
||||
end
|
||||
|
||||
def form_on_stock_article_create # See publish/subscribe design pattern in /doc.
|
||||
@stock_article = StockArticle.find(params[:id])
|
||||
|
||||
render :layout => false
|
||||
render layout: false
|
||||
end
|
||||
|
||||
def form_on_stock_article_update # See publish/subscribe design pattern in /doc.
|
||||
@stock_article = StockArticle.find(params[:id])
|
||||
|
||||
render :layout => false
|
||||
render layout: false
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
class FeedbackController < ApplicationController
|
||||
def new
|
||||
end
|
||||
def new; end
|
||||
|
||||
def create
|
||||
if params[:message].present?
|
||||
Mailer.feedback(current_user, params[:message]).deliver_now
|
||||
redirect_to root_url, notice: t('feedback.create.notice')
|
||||
redirect_to root_url, notice: t('.notice')
|
||||
else
|
||||
render :action => 'new'
|
||||
render action: 'new'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -5,7 +5,7 @@ class Finance::BalancingController < Finance::BaseController
|
|||
|
||||
def new
|
||||
@order = Order.find(params[:order_id])
|
||||
flash.now.alert = t('finance.balancing.new.alert') if @order.closed?
|
||||
flash.now.alert = t('.alert') if @order.closed?
|
||||
@comments = @order.comments
|
||||
|
||||
@articles = @order.order_articles.ordered_or_member.includes(:article, :article_price,
|
||||
|
@ -13,13 +13,13 @@ class Finance::BalancingController < Finance::BaseController
|
|||
|
||||
sort_param = params['sort'] || 'name'
|
||||
@articles = case sort_param
|
||||
when 'name' then
|
||||
when 'name'
|
||||
@articles.order('articles.name ASC')
|
||||
when 'name_reverse' then
|
||||
when 'name_reverse'
|
||||
@articles.order('articles.name DESC')
|
||||
when 'order_number' then
|
||||
when 'order_number'
|
||||
@articles.order('articles.order_number ASC')
|
||||
when 'order_number_reverse' then
|
||||
when 'order_number_reverse'
|
||||
@articles.order('articles.order_number DESC')
|
||||
else
|
||||
@articles
|
||||
|
@ -31,13 +31,13 @@ class Finance::BalancingController < Finance::BaseController
|
|||
def new_on_order_article_create # See publish/subscribe design pattern in /doc.
|
||||
@order_article = OrderArticle.find(params[:order_article_id])
|
||||
|
||||
render :layout => false
|
||||
render layout: false
|
||||
end
|
||||
|
||||
def new_on_order_article_update # See publish/subscribe design pattern in /doc.
|
||||
@order_article = OrderArticle.find(params[:order_article_id])
|
||||
|
||||
render :layout => false
|
||||
render layout: false
|
||||
end
|
||||
|
||||
def update_summary
|
||||
|
@ -46,29 +46,29 @@ class Finance::BalancingController < Finance::BaseController
|
|||
|
||||
def edit_note
|
||||
@order = Order.find(params[:id])
|
||||
render :layout => false
|
||||
render layout: false
|
||||
end
|
||||
|
||||
def update_note
|
||||
@order = Order.find(params[:id])
|
||||
if @order.update(params[:order])
|
||||
render :layout => false
|
||||
render layout: false
|
||||
else
|
||||
render :action => :edit_note, :layout => false
|
||||
render action: :edit_note, layout: false
|
||||
end
|
||||
end
|
||||
|
||||
def edit_transport
|
||||
@order = Order.find(params[:id])
|
||||
render :layout => false
|
||||
render layout: false
|
||||
end
|
||||
|
||||
def update_transport
|
||||
@order = Order.find(params[:id])
|
||||
@order.update!(params[:order])
|
||||
redirect_to new_finance_order_path(order_id: @order.id)
|
||||
rescue => error
|
||||
redirect_to new_finance_order_path(order_id: @order.id), alert: t('errors.general_msg', msg: error.message)
|
||||
rescue StandardError => e
|
||||
redirect_to new_finance_order_path(order_id: @order.id), alert: t('errors.general_msg', msg: e.message)
|
||||
end
|
||||
|
||||
# before the order will booked, a view lists all Ordergroups and its order_prices
|
||||
|
@ -81,18 +81,18 @@ class Finance::BalancingController < Finance::BaseController
|
|||
@order = Order.find(params[:id])
|
||||
@type = FinancialTransactionType.find_by_id(params.permit(:type)[:type])
|
||||
@order.close!(@current_user, @type)
|
||||
redirect_to finance_order_index_url, notice: t('finance.balancing.close.notice')
|
||||
rescue => error
|
||||
redirect_to new_finance_order_url(order_id: @order.id), alert: t('finance.balancing.close.alert', message: error.message)
|
||||
redirect_to finance_order_index_url, notice: t('.notice')
|
||||
rescue StandardError => e
|
||||
redirect_to new_finance_order_url(order_id: @order.id), alert: t('.alert', message: e.message)
|
||||
end
|
||||
|
||||
# Close the order directly, without automaticly updating ordergroups account balances
|
||||
def close_direct
|
||||
@order = Order.find(params[:id])
|
||||
@order.close_direct!(@current_user)
|
||||
redirect_to finance_order_index_url, notice: t('finance.balancing.close_direct.notice')
|
||||
rescue => error
|
||||
redirect_to finance_order_index_url, alert: t('finance.balancing.close_direct.alert', message: error.message)
|
||||
redirect_to finance_order_index_url, notice: t('.notice')
|
||||
rescue StandardError => e
|
||||
redirect_to finance_order_index_url, alert: t('.alert', message: e.message)
|
||||
end
|
||||
|
||||
def close_all_direct_with_invoice
|
||||
|
@ -103,8 +103,8 @@ class Finance::BalancingController < Finance::BaseController
|
|||
count += 1
|
||||
end
|
||||
end
|
||||
redirect_to finance_order_index_url, notice: t('finance.balancing.close_all_direct_with_invoice.notice', count: count)
|
||||
rescue => error
|
||||
redirect_to finance_order_index_url, alert: t('errors.general_msg', msg: error.message)
|
||||
redirect_to finance_order_index_url, notice: t('.notice', count: count)
|
||||
rescue StandardError => e
|
||||
redirect_to finance_order_index_url, alert: t('errors.general_msg', msg: e.message)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -8,8 +8,8 @@ class Finance::BankAccountsController < Finance::BaseController
|
|||
@bank_account = BankAccount.find(params[:id])
|
||||
count = @bank_account.assign_unlinked_transactions
|
||||
redirect_to finance_bank_account_transactions_url(@bank_account), notice: t('.notice', count: count)
|
||||
rescue => error
|
||||
redirect_to finance_bank_account_transactions_url(@bank_account), alert: t('errors.general_msg', msg: error.message)
|
||||
rescue StandardError => e
|
||||
redirect_to finance_bank_account_transactions_url(@bank_account), alert: t('errors.general_msg', msg: e.message)
|
||||
end
|
||||
|
||||
def import
|
||||
|
@ -33,8 +33,8 @@ class Finance::BankAccountsController < Finance::BaseController
|
|||
end
|
||||
|
||||
needs_redirect = ok
|
||||
rescue => error
|
||||
flash.alert = t('errors.general_msg', msg: error.message)
|
||||
rescue StandardError => e
|
||||
flash.alert = t('errors.general_msg', msg: e.message)
|
||||
needs_redirect = true
|
||||
ensure
|
||||
return unless needs_redirect
|
||||
|
|
|
@ -3,26 +3,30 @@ class Finance::BankTransactionsController < ApplicationController
|
|||
inherit_resources
|
||||
|
||||
def index
|
||||
if params["sort"]
|
||||
sort = case params["sort"]
|
||||
when "date" then "date"
|
||||
when "amount" then "amount"
|
||||
when "financial_link" then "financial_link_id"
|
||||
when "date_reverse" then "date DESC"
|
||||
when "amount_reverse" then "amount DESC"
|
||||
when "financial_link_reverse" then "financial_link_id DESC"
|
||||
sort = if params['sort']
|
||||
case params['sort']
|
||||
when 'date' then 'date'
|
||||
when 'amount' then 'amount'
|
||||
when 'financial_link' then 'financial_link_id'
|
||||
when 'date_reverse' then 'date DESC'
|
||||
when 'amount_reverse' then 'amount DESC'
|
||||
when 'financial_link_reverse' then 'financial_link_id DESC'
|
||||
end
|
||||
else
|
||||
sort = "date DESC"
|
||||
end
|
||||
else
|
||||
'date DESC'
|
||||
end
|
||||
|
||||
@bank_account = BankAccount.find(params[:bank_account_id])
|
||||
@bank_transactions_all = @bank_account.bank_transactions.order(sort).includes(:financial_link)
|
||||
@bank_transactions_all = @bank_transactions_all.where('reference LIKE ? OR text LIKE ?', "%#{params[:query]}%", "%#{params[:query]}%") unless params[:query].nil?
|
||||
unless params[:query].nil?
|
||||
@bank_transactions_all = @bank_transactions_all.where('reference LIKE ? OR text LIKE ?', "%#{params[:query]}%",
|
||||
"%#{params[:query]}%")
|
||||
end
|
||||
@bank_transactions = @bank_transactions_all.page(params[:page]).per(@per_page)
|
||||
|
||||
respond_to do |format|
|
||||
format.js; format.html { render }
|
||||
format.js
|
||||
format.html { render }
|
||||
format.csv do
|
||||
send_data BankTransactionsCsv.new(@bank_transactions_all).to_csv, filename: 'transactions.csv', type: 'text/csv'
|
||||
end
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
class Finance::FinancialLinksController < Finance::BaseController
|
||||
before_action :find_financial_link, except: [:create, :incomplete]
|
||||
before_action :find_financial_link, except: %i[create incomplete]
|
||||
|
||||
def show
|
||||
@items = @financial_link.bank_transactions.map do |bt|
|
||||
|
@ -37,7 +37,7 @@ class Finance::FinancialLinksController < Finance::BaseController
|
|||
|
||||
def create
|
||||
@financial_link = FinancialLink.first_unused_or_create
|
||||
if params[:bank_transaction] then
|
||||
if params[:bank_transaction]
|
||||
bank_transaction = BankTransaction.find(params[:bank_transaction])
|
||||
bank_transaction.update_attribute :financial_link, @financial_link
|
||||
end
|
||||
|
@ -72,14 +72,16 @@ class Finance::FinancialLinksController < Finance::BaseController
|
|||
|
||||
def create_financial_transaction
|
||||
financial_transaction = FinancialTransaction.new(financial_transaction_params)
|
||||
financial_transaction.ordergroup.add_financial_transaction! financial_transaction.amount, financial_transaction.note, current_user, financial_transaction.financial_transaction_type, @financial_link
|
||||
financial_transaction.ordergroup.add_financial_transaction! financial_transaction.amount,
|
||||
financial_transaction.note, current_user, financial_transaction.financial_transaction_type, @financial_link
|
||||
redirect_to finance_link_url(@financial_link), notice: t('.notice')
|
||||
rescue => error
|
||||
redirect_to finance_link_url(@financial_link), alert: t('errors.general_msg', msg: error)
|
||||
rescue StandardError => e
|
||||
redirect_to finance_link_url(@financial_link), alert: t('errors.general_msg', msg: e)
|
||||
end
|
||||
|
||||
def index_financial_transaction
|
||||
@financial_transactions = FinancialTransaction.without_financial_link.includes(:financial_transaction_type, :ordergroup)
|
||||
@financial_transactions = FinancialTransaction.without_financial_link.includes(:financial_transaction_type,
|
||||
:ordergroup)
|
||||
end
|
||||
|
||||
def add_financial_transaction
|
||||
|
@ -123,7 +125,7 @@ class Finance::FinancialLinksController < Finance::BaseController
|
|||
end
|
||||
|
||||
def find_best_fitting_ordergroup_id_for_financial_link(financial_link_id)
|
||||
FinancialTransaction.joins(<<-SQL).order(created_on: :desc).pluck(:ordergroup_id).first
|
||||
FinancialTransaction.joins(<<-SQL).order(created_on: :desc).pick(:ordergroup_id)
|
||||
JOIN bank_transactions a ON financial_transactions.financial_link_id = a.financial_link_id
|
||||
JOIN bank_transactions b ON a.iban = b.iban AND b.financial_link_id = #{financial_link_id.to_i}
|
||||
SQL
|
||||
|
|
|
@ -1,24 +1,24 @@
|
|||
class Finance::FinancialTransactionsController < ApplicationController
|
||||
before_action :authenticate_finance
|
||||
before_action :find_ordergroup, :except => [:new_collection, :create_collection, :index_collection]
|
||||
before_action :find_ordergroup, except: %i[new_collection create_collection index_collection]
|
||||
inherit_resources
|
||||
# belongs_to :ordergroup
|
||||
|
||||
def index
|
||||
if params['sort']
|
||||
sort = case params['sort']
|
||||
when "date" then "created_on"
|
||||
when "note" then "note"
|
||||
when "amount" then "amount"
|
||||
when "date_reverse" then "created_on DESC"
|
||||
when "note_reverse" then "note DESC"
|
||||
when "amount_reverse" then "amount DESC"
|
||||
sort = if params['sort']
|
||||
case params['sort']
|
||||
when 'date' then 'created_on'
|
||||
when 'note' then 'note'
|
||||
when 'amount' then 'amount'
|
||||
when 'date_reverse' then 'created_on DESC'
|
||||
when 'note_reverse' then 'note DESC'
|
||||
when 'amount_reverse' then 'amount DESC'
|
||||
end
|
||||
else
|
||||
sort = "created_on DESC"
|
||||
end
|
||||
else
|
||||
'created_on DESC'
|
||||
end
|
||||
|
||||
@q = FinancialTransaction.search(params[:q])
|
||||
@q = FinancialTransaction.ransack(params[:q])
|
||||
@financial_transactions_all = @q.result(distinct: true).includes(:user).order(sort)
|
||||
@financial_transactions_all = @financial_transactions_all.visible unless params[:show_hidden]
|
||||
@financial_transactions_all = @financial_transactions_all.where(ordergroup_id: @ordergroup.id) if @ordergroup
|
||||
|
@ -26,9 +26,11 @@ class Finance::FinancialTransactionsController < ApplicationController
|
|||
@financial_transactions = @financial_transactions_all.page(params[:page]).per(@per_page)
|
||||
|
||||
respond_to do |format|
|
||||
format.js; format.html { render }
|
||||
format.js
|
||||
format.html { render }
|
||||
format.csv do
|
||||
send_data FinancialTransactionsCsv.new(@financial_transactions_all).to_csv, filename: 'transactions.csv', type: 'text/csv'
|
||||
send_data FinancialTransactionsCsv.new(@financial_transactions_all).to_csv, filename: 'transactions.csv',
|
||||
type: 'text/csv'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -38,31 +40,29 @@ class Finance::FinancialTransactionsController < ApplicationController
|
|||
end
|
||||
|
||||
def new
|
||||
if @ordergroup
|
||||
@financial_transaction = @ordergroup.financial_transactions.build
|
||||
else
|
||||
@financial_transaction = FinancialTransaction.new
|
||||
end
|
||||
@financial_transaction = if @ordergroup
|
||||
@ordergroup.financial_transactions.build
|
||||
else
|
||||
FinancialTransaction.new
|
||||
end
|
||||
end
|
||||
|
||||
def create
|
||||
@financial_transaction = FinancialTransaction.new(params[:financial_transaction])
|
||||
@financial_transaction.user = current_user
|
||||
if @financial_transaction.ordergroup
|
||||
@financial_transaction.add_transaction!
|
||||
else
|
||||
@financial_transaction.save!
|
||||
end
|
||||
redirect_to finance_group_transactions_path(@ordergroup), notice: I18n.t('finance.financial_transactions.controller.create.notice')
|
||||
rescue ActiveRecord::RecordInvalid => error
|
||||
flash.now[:alert] = error.message
|
||||
render :action => :new
|
||||
@financial_transaction.save!
|
||||
redirect_to finance_group_transactions_path(@ordergroup),
|
||||
notice: I18n.t('finance.financial_transactions.controller.create.notice')
|
||||
rescue ActiveRecord::RecordInvalid => e
|
||||
flash.now[:alert] = e.message
|
||||
render action: :new
|
||||
end
|
||||
|
||||
def destroy
|
||||
transaction = FinancialTransaction.find(params[:id])
|
||||
transaction.revert!(current_user)
|
||||
redirect_to finance_group_transactions_path(transaction.ordergroup), notice: t('finance.financial_transactions.controller.destroy.notice')
|
||||
redirect_to finance_group_transactions_path(transaction.ordergroup),
|
||||
notice: t('finance.financial_transactions.controller.destroy.notice')
|
||||
end
|
||||
|
||||
def new_collection
|
||||
|
@ -88,17 +88,17 @@ class Finance::FinancialTransactionsController < ApplicationController
|
|||
|
||||
params[:financial_transactions].each do |trans|
|
||||
# ignore empty amount fields ...
|
||||
unless trans[:amount].blank?
|
||||
amount = LocalizeInput.parse(trans[:amount]).to_f
|
||||
note = params[:note]
|
||||
ordergroup = Ordergroup.find(trans[:ordergroup_id])
|
||||
if params[:set_balance]
|
||||
note += " (#{amount})"
|
||||
amount -= ordergroup.financial_transaction_class_balance(type.financial_transaction_class)
|
||||
end
|
||||
ordergroup.add_financial_transaction!(amount, note, @current_user, type, financial_link)
|
||||
foodcoop_amount -= amount
|
||||
next if trans[:amount].blank?
|
||||
|
||||
amount = LocalizeInput.parse(trans[:amount]).to_f
|
||||
note = params[:note]
|
||||
ordergroup = Ordergroup.find(trans[:ordergroup_id])
|
||||
if params[:set_balance]
|
||||
note += " (#{amount})"
|
||||
amount -= ordergroup.financial_transaction_class_balance(type.financial_transaction_class)
|
||||
end
|
||||
ordergroup.add_financial_transaction!(amount, note, @current_user, type, financial_link)
|
||||
foodcoop_amount -= amount
|
||||
end
|
||||
|
||||
if params[:create_foodcoop_transaction]
|
||||
|
@ -107,7 +107,7 @@ class Finance::FinancialTransactionsController < ApplicationController
|
|||
user: @current_user,
|
||||
amount: foodcoop_amount,
|
||||
note: params[:note],
|
||||
financial_link: financial_link,
|
||||
financial_link: financial_link
|
||||
})
|
||||
ft.save!
|
||||
end
|
||||
|
@ -117,8 +117,8 @@ class Finance::FinancialTransactionsController < ApplicationController
|
|||
|
||||
url = financial_link ? finance_link_url(financial_link.id) : finance_ordergroups_url
|
||||
redirect_to url, notice: I18n.t('finance.financial_transactions.controller.create_collection.notice')
|
||||
rescue => error
|
||||
flash.now[:alert] = error.message
|
||||
rescue StandardError => e
|
||||
flash.now[:alert] = e.message
|
||||
render action: :new_collection
|
||||
end
|
||||
|
||||
|
|
|
@ -1,15 +1,16 @@
|
|||
class Finance::InvoicesController < ApplicationController
|
||||
before_action :authenticate_finance_or_invoices
|
||||
|
||||
before_action :find_invoice, only: [:show, :edit, :update, :destroy]
|
||||
before_action :ensure_can_edit, only: [:edit, :update, :destroy]
|
||||
before_action :find_invoice, only: %i[show edit update destroy]
|
||||
before_action :ensure_can_edit, only: %i[edit update destroy]
|
||||
|
||||
def index
|
||||
@invoices_all = Invoice.includes(:supplier, :deliveries, :orders).order('date DESC')
|
||||
@invoices = @invoices_all.page(params[:page]).per(@per_page)
|
||||
|
||||
respond_to do |format|
|
||||
format.js; format.html { render }
|
||||
format.js
|
||||
format.html { render }
|
||||
format.csv do
|
||||
send_data InvoicesCsv.new(@invoices_all).to_csv, filename: 'invoices.csv', type: 'text/csv'
|
||||
end
|
||||
|
@ -20,11 +21,10 @@ class Finance::InvoicesController < ApplicationController
|
|||
@suppliers = Supplier.includes(:invoices).where('invoices.paid_on IS NULL').references(:invoices)
|
||||
end
|
||||
|
||||
def show
|
||||
end
|
||||
def show; end
|
||||
|
||||
def new
|
||||
@invoice = Invoice.new :supplier_id => params[:supplier_id]
|
||||
@invoice = Invoice.new supplier_id: params[:supplier_id]
|
||||
@invoice.deliveries << Delivery.find_by_id(params[:delivery_id]) if params[:delivery_id]
|
||||
@invoice.orders << Order.find_by_id(params[:order_id]) if params[:order_id]
|
||||
fill_deliveries_and_orders_collection @invoice.id, @invoice.supplier_id
|
||||
|
@ -36,12 +36,14 @@ class Finance::InvoicesController < ApplicationController
|
|||
|
||||
def form_on_supplier_id_change
|
||||
fill_deliveries_and_orders_collection params[:invoice_id], params[:supplier_id]
|
||||
render :layout => false
|
||||
render layout: false
|
||||
end
|
||||
|
||||
def fill_deliveries_and_orders_collection(invoice_id, supplier_id)
|
||||
@deliveries_collection = Delivery.where('invoice_id = ? OR (invoice_id IS NULL AND supplier_id = ?)', invoice_id, supplier_id).order(date: :desc).limit(25)
|
||||
@orders_collection = Order.where('invoice_id = ? OR (invoice_id IS NULL AND supplier_id = ?)', invoice_id, supplier_id).order(ends: :desc).limit(25)
|
||||
@deliveries_collection = Delivery.where('invoice_id = ? OR (invoice_id IS NULL AND supplier_id = ?)', invoice_id,
|
||||
supplier_id).order(date: :desc).limit(25)
|
||||
@orders_collection = Order.where('invoice_id = ? OR (invoice_id IS NULL AND supplier_id = ?)', invoice_id,
|
||||
supplier_id).order(ends: :desc).limit(25)
|
||||
end
|
||||
|
||||
def create
|
||||
|
@ -58,7 +60,7 @@ class Finance::InvoicesController < ApplicationController
|
|||
end
|
||||
else
|
||||
fill_deliveries_and_orders_collection @invoice.id, @invoice.supplier_id
|
||||
render :action => "new"
|
||||
render action: 'new'
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -81,7 +83,7 @@ class Finance::InvoicesController < ApplicationController
|
|||
@invoice = Invoice.find(params[:invoice_id])
|
||||
type = MIME::Types[@invoice.attachment_mime].first
|
||||
filename = "invoice_#{@invoice.id}_attachment.#{type.preferred_extension}"
|
||||
send_data(@invoice.attachment_data, :filename => filename, :type => type)
|
||||
send_data(@invoice.attachment_data, filename: filename, type: type)
|
||||
end
|
||||
|
||||
private
|
||||
|
@ -92,8 +94,8 @@ class Finance::InvoicesController < ApplicationController
|
|||
|
||||
# Returns true if @current_user can edit the invoice..
|
||||
def ensure_can_edit
|
||||
unless @invoice.user_can_edit?(current_user)
|
||||
deny_access
|
||||
end
|
||||
return if @invoice.user_can_edit?(current_user)
|
||||
|
||||
deny_access
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,17 +1,20 @@
|
|||
class Finance::OrdergroupsController < Finance::BaseController
|
||||
def index
|
||||
m = /^(?<col>name|sum_of_class_\d+)(?<reverse>_reverse)?$/.match params["sort"]
|
||||
m = /^(?<col>name|sum_of_class_\d+)(?<reverse>_reverse)?$/.match params['sort']
|
||||
if m
|
||||
sort = m[:col]
|
||||
sort += ' DESC' if m[:reverse]
|
||||
else
|
||||
sort = "name"
|
||||
sort = 'name'
|
||||
end
|
||||
|
||||
@ordergroups = Ordergroup.undeleted.order(sort)
|
||||
@ordergroups = @ordergroups.include_transaction_class_sum
|
||||
@ordergroups = @ordergroups.where('groups.name LIKE ?', "%#{params[:query]}%") unless params[:query].nil?
|
||||
|
||||
@ordergroups = @ordergroups.page(params[:page]).per(@per_page)
|
||||
|
||||
@total_balances = FinancialTransactionClass.sorted.each_with_object({}) do |c, tmp|
|
||||
tmp[c.id] = c.financial_transactions.reduce(0) { |sum, t| sum + (t.amount || 0) }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,20 +1,16 @@
|
|||
class Foodcoop::OrdergroupsController < ApplicationController
|
||||
def index
|
||||
@ordergroups = Ordergroup.undeleted.sort_by_param(params["sort"])
|
||||
@ordergroups = Ordergroup.undeleted.sort_by_param(params['sort'])
|
||||
|
||||
unless params[:name].blank? # Search by name
|
||||
@ordergroups = @ordergroups.where('name LIKE ?', "%#{params[:name]}%")
|
||||
end
|
||||
@ordergroups = @ordergroups.where('name LIKE ?', "%#{params[:name]}%") if params[:name].present? # Search by name
|
||||
|
||||
if params[:only_active] # Select only active groups
|
||||
@ordergroups = @ordergroups.active
|
||||
end
|
||||
@ordergroups = @ordergroups.active if params[:only_active] # Select only active groups
|
||||
|
||||
@ordergroups = @ordergroups.page(params[:page]).per(@per_page)
|
||||
|
||||
respond_to do |format|
|
||||
format.html # index.html.erb
|
||||
format.js { render :layout => false }
|
||||
format.js { render layout: false }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,19 +1,22 @@
|
|||
class Foodcoop::UsersController < ApplicationController
|
||||
before_action -> { require_config_disabled :disable_members_overview }
|
||||
|
||||
def index
|
||||
@users = User.undeleted.sort_by_param(params["sort"])
|
||||
@users = User.undeleted.sort_by_param(params['sort'])
|
||||
|
||||
# if somebody uses the search field:
|
||||
@users = @users.natural_search(params[:user_name]) unless params[:user_name].blank?
|
||||
@users = @users.natural_search(params[:user_name]) if params[:user_name].present?
|
||||
|
||||
if params[:ordergroup_name]
|
||||
@users = @users.joins(:groups).where("groups.type = 'Ordergroup' AND groups.name LIKE ?", "%#{params[:ordergroup_name]}%")
|
||||
@users = @users.joins(:groups).where("groups.type = 'Ordergroup' AND groups.name LIKE ?",
|
||||
"%#{params[:ordergroup_name]}%")
|
||||
end
|
||||
|
||||
@users = @users.page(params[:page]).per(@per_page)
|
||||
|
||||
respond_to do |format|
|
||||
format.html # index.html.haml
|
||||
format.js { render :layout => false } # index.js.erb
|
||||
format.js { render layout: false } # index.js.erb
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
class Foodcoop::WorkgroupsController < ApplicationController
|
||||
before_action :authenticate_membership_or_admin,
|
||||
:except => [:index]
|
||||
except: [:index]
|
||||
|
||||
def index
|
||||
@workgroups = Workgroup.order("name")
|
||||
@workgroups = Workgroup.order('name')
|
||||
end
|
||||
|
||||
def edit
|
||||
|
@ -13,9 +13,9 @@ class Foodcoop::WorkgroupsController < ApplicationController
|
|||
def update
|
||||
@workgroup = Workgroup.find(params[:id])
|
||||
if @workgroup.update(params[:workgroup])
|
||||
redirect_to foodcoop_workgroups_url, :notice => I18n.t('workgroups.update.notice')
|
||||
redirect_to foodcoop_workgroups_url, notice: I18n.t('workgroups.update.notice')
|
||||
else
|
||||
render :action => 'edit'
|
||||
render action: 'edit'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
class GroupOrderArticlesController < ApplicationController
|
||||
before_action :authenticate_finance
|
||||
before_action :find_group_order_article, except: [:new, :create]
|
||||
before_action :find_group_order_article, except: %i[new create]
|
||||
|
||||
layout false # We only use this controller to server js snippets, no need for layout rendering
|
||||
|
||||
|
|
|
@ -3,9 +3,9 @@
|
|||
class GroupOrdersController < ApplicationController
|
||||
# Security
|
||||
before_action :ensure_ordergroup_member
|
||||
before_action :ensure_open_order, :only => [:new, :create, :edit, :update, :order, :stock_order, :saveOrder]
|
||||
before_action :ensure_my_group_order, only: [:show, :edit, :update]
|
||||
before_action :enough_apples?, only: [:new, :create]
|
||||
before_action :ensure_open_order, only: %i[new create edit update order stock_order saveOrder]
|
||||
before_action :ensure_my_group_order, only: %i[show edit update]
|
||||
before_action :enough_apples?, only: %i[new create]
|
||||
|
||||
# Index page.
|
||||
def index
|
||||
|
@ -13,9 +13,17 @@ class GroupOrdersController < ApplicationController
|
|||
@finished_not_closed_orders_including_group_order = Order.finished_not_closed.ordergroup_group_orders_map(@ordergroup)
|
||||
end
|
||||
|
||||
def show
|
||||
@order = @group_order.order
|
||||
end
|
||||
|
||||
def new
|
||||
ordergroup = params[:stock_order] ? nil : @ordergroup
|
||||
@group_order = @order.group_orders.build(:ordergroup => ordergroup, :updated_by => current_user)
|
||||
@group_order = @order.group_orders.build(ordergroup: ordergroup, updated_by: current_user)
|
||||
@ordering_data = @group_order.load_data
|
||||
end
|
||||
|
||||
def edit
|
||||
@ordering_data = @group_order.load_data
|
||||
end
|
||||
|
||||
|
@ -23,34 +31,26 @@ class GroupOrdersController < ApplicationController
|
|||
@group_order = GroupOrder.new(params[:group_order])
|
||||
begin
|
||||
@group_order.save_ordering!
|
||||
redirect_to group_order_url(@group_order), :notice => I18n.t('group_orders.create.notice')
|
||||
redirect_to group_order_url(@group_order), notice: I18n.t('group_orders.create.notice')
|
||||
rescue ActiveRecord::StaleObjectError
|
||||
redirect_to group_orders_url, :alert => I18n.t('group_orders.create.error_stale')
|
||||
rescue => exception
|
||||
logger.error('Failed to update order: ' + exception.message)
|
||||
redirect_to group_orders_url, :alert => I18n.t('group_orders.create.error_general')
|
||||
redirect_to group_orders_url, alert: I18n.t('group_orders.create.error_stale')
|
||||
rescue StandardError => e
|
||||
logger.error('Failed to update order: ' + e.message)
|
||||
redirect_to group_orders_url, alert: I18n.t('group_orders.create.error_general')
|
||||
end
|
||||
end
|
||||
|
||||
def show
|
||||
@order = @group_order.order
|
||||
end
|
||||
|
||||
def edit
|
||||
@ordering_data = @group_order.load_data
|
||||
end
|
||||
|
||||
def update
|
||||
@group_order.attributes = params[:group_order]
|
||||
@group_order.updated_by = current_user
|
||||
begin
|
||||
@group_order.save_ordering!
|
||||
redirect_to group_order_url(@group_order), :notice => I18n.t('group_orders.update.notice')
|
||||
redirect_to group_order_url(@group_order), notice: I18n.t('group_orders.update.notice')
|
||||
rescue ActiveRecord::StaleObjectError
|
||||
redirect_to group_orders_url, :alert => I18n.t('group_orders.update.error_stale')
|
||||
rescue => exception
|
||||
logger.error('Failed to update order: ' + exception.message)
|
||||
redirect_to group_orders_url, :alert => I18n.t('group_orders.update.error_general')
|
||||
redirect_to group_orders_url, alert: I18n.t('group_orders.update.error_stale')
|
||||
rescue StandardError => e
|
||||
logger.error('Failed to update order: ' + e.message)
|
||||
redirect_to group_orders_url, alert: I18n.t('group_orders.update.error_general')
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -74,16 +74,16 @@ class GroupOrdersController < ApplicationController
|
|||
# Used as a :before_action by OrdersController.
|
||||
def ensure_ordergroup_member
|
||||
@ordergroup = @current_user.ordergroup
|
||||
if @ordergroup.nil?
|
||||
redirect_to root_url, :alert => I18n.t('group_orders.errors.no_member')
|
||||
end
|
||||
return unless @ordergroup.nil?
|
||||
|
||||
redirect_to root_url, alert: I18n.t('group_orders.errors.no_member')
|
||||
end
|
||||
|
||||
def ensure_open_order
|
||||
@order = Order.includes([:supplier, :order_articles]).find(order_id_param)
|
||||
@order = Order.includes(%i[supplier order_articles]).find(order_id_param)
|
||||
unless @order.open?
|
||||
flash[:notice] = I18n.t('group_orders.errors.closed')
|
||||
redirect_to :action => 'index'
|
||||
redirect_to action: 'index'
|
||||
end
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
redirect_to group_orders_url, alert: I18n.t('group_orders.errors.notfound')
|
||||
|
@ -91,17 +91,17 @@ class GroupOrdersController < ApplicationController
|
|||
|
||||
def ensure_my_group_order
|
||||
@group_order = GroupOrder.find(params[:id])
|
||||
if @group_order.ordergroup != @ordergroup && (@group_order.ordergroup || !current_user.role_orders?)
|
||||
redirect_to group_orders_url, alert: I18n.t('group_orders.errors.notfound')
|
||||
end
|
||||
return unless @group_order.ordergroup != @ordergroup && (@group_order.ordergroup || !current_user.role_orders?)
|
||||
|
||||
redirect_to group_orders_url, alert: I18n.t('group_orders.errors.notfound')
|
||||
end
|
||||
|
||||
def enough_apples?
|
||||
if @ordergroup.not_enough_apples?
|
||||
redirect_to group_orders_url,
|
||||
alert: t('not_enough_apples', scope: 'group_orders.messages', apples: @ordergroup.apples,
|
||||
stop_ordering_under: FoodsoftConfig[:stop_ordering_under])
|
||||
end
|
||||
return unless @ordergroup.not_enough_apples?
|
||||
|
||||
redirect_to group_orders_url,
|
||||
alert: t('not_enough_apples', scope: 'group_orders.messages', apples: @ordergroup.apples,
|
||||
stop_ordering_under: FoodsoftConfig[:stop_ordering_under])
|
||||
end
|
||||
|
||||
def order_id_param
|
||||
|
|
|
@ -9,8 +9,7 @@ class HomeController < ApplicationController
|
|||
@unassigned_tasks = Task.order(:due_date).next_unassigned_tasks_for(current_user)
|
||||
end
|
||||
|
||||
def profile
|
||||
end
|
||||
def profile; end
|
||||
|
||||
def reference_calculator
|
||||
if current_user.ordergroup
|
||||
|
@ -36,40 +35,43 @@ class HomeController < ApplicationController
|
|||
@user = @current_user
|
||||
@ordergroup = @user.ordergroup
|
||||
|
||||
unless @ordergroup.nil?
|
||||
if @ordergroup.nil?
|
||||
redirect_to root_path, alert: I18n.t('home.no_ordergroups')
|
||||
else
|
||||
|
||||
@ordergroup = Ordergroup.include_transaction_class_sum.find(@ordergroup.id)
|
||||
|
||||
if params['sort']
|
||||
sort = case params['sort']
|
||||
when "date" then "created_on"
|
||||
when "note" then "note"
|
||||
when "amount" then "amount"
|
||||
when "date_reverse" then "created_on DESC"
|
||||
when "note_reverse" then "note DESC"
|
||||
when "amount_reverse" then "amount DESC"
|
||||
sort = if params['sort']
|
||||
case params['sort']
|
||||
when 'date' then 'created_on'
|
||||
when 'note' then 'note'
|
||||
when 'amount' then 'amount'
|
||||
when 'date_reverse' then 'created_on DESC'
|
||||
when 'note_reverse' then 'note DESC'
|
||||
when 'amount_reverse' then 'amount DESC'
|
||||
end
|
||||
else
|
||||
sort = "created_on DESC"
|
||||
end
|
||||
else
|
||||
'created_on DESC'
|
||||
end
|
||||
|
||||
@financial_transactions = @ordergroup.financial_transactions.visible.page(params[:page]).per(@per_page).order(sort)
|
||||
@financial_transactions = @financial_transactions.where('financial_transactions.note LIKE ?', "%#{params[:query]}%") if params[:query].present?
|
||||
if params[:query].present?
|
||||
@financial_transactions = @financial_transactions.where('financial_transactions.note LIKE ?',
|
||||
"%#{params[:query]}%")
|
||||
end
|
||||
|
||||
else
|
||||
redirect_to root_path, alert: I18n.t('home.no_ordergroups')
|
||||
end
|
||||
end
|
||||
|
||||
# cancel personal memberships direct from the myProfile-page
|
||||
def cancel_membership
|
||||
if params[:membership_id]
|
||||
membership = @current_user.memberships.find!(params[:membership_id])
|
||||
else
|
||||
membership = @current_user.memberships.find_by_group_id!(params[:group_id])
|
||||
end
|
||||
membership = if params[:membership_id]
|
||||
@current_user.memberships.find(params[:membership_id])
|
||||
else
|
||||
@current_user.memberships.find_by_group_id!(params[:group_id])
|
||||
end
|
||||
membership.destroy
|
||||
redirect_to my_profile_path, notice: I18n.t('home.ordergroup_cancelled', :group => membership.group.name)
|
||||
redirect_to my_profile_path, notice: I18n.t('home.ordergroup_cancelled', group: membership.group.name)
|
||||
end
|
||||
|
||||
protected
|
||||
|
@ -82,8 +84,8 @@ class HomeController < ApplicationController
|
|||
end
|
||||
|
||||
def ordergroup_params
|
||||
if params[:user][:ordergroup]
|
||||
params.require(:user).require(:ordergroup).permit(:contact_address)
|
||||
end
|
||||
return unless params[:user][:ordergroup]
|
||||
|
||||
params.require(:user).require(:ordergroup).permit(:contact_address)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -3,7 +3,7 @@ class InvitesController < ApplicationController
|
|||
before_action -> { require_config_disabled :disable_invite }
|
||||
|
||||
def new
|
||||
@invite = Invite.new(:user => @current_user, :group => @group)
|
||||
@invite = Invite.new(user: @current_user, group: @group)
|
||||
end
|
||||
|
||||
def create
|
||||
|
@ -27,6 +27,10 @@ class InvitesController < ApplicationController
|
|||
protected
|
||||
|
||||
def authenticate_membership_or_admin_for_invites
|
||||
authenticate_membership_or_admin((params[:invite][:group_id] rescue params[:id]))
|
||||
authenticate_membership_or_admin(begin
|
||||
params[:invite][:group_id]
|
||||
rescue StandardError
|
||||
params[:id]
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
class LoginController < ApplicationController
|
||||
skip_before_action :authenticate # no authentication since this is the login page
|
||||
before_action :validate_token, :only => [:new_password, :update_password]
|
||||
before_action :validate_token, only: %i[new_password update_password]
|
||||
|
||||
# Display the form to enter an email address requesting a token to set a new password.
|
||||
def forgot_password
|
||||
|
@ -9,20 +9,17 @@ class LoginController < ApplicationController
|
|||
|
||||
# Sends an email to a user with the token that allows setting a new password through action "password".
|
||||
def reset_password
|
||||
if request.get? || params[:user].nil? # Catch for get request and give better error message.
|
||||
redirect_to forgot_password_url, alert: I18n.t('errors.general_again') and return
|
||||
end
|
||||
redirect_to forgot_password_url, alert: I18n.t('errors.general_again') and return if request.get? || params[:user].nil? # Catch for get request and give better error message.
|
||||
|
||||
if (user = User.undeleted.find_by_email(params[:user][:email]))
|
||||
user.request_password_reset!
|
||||
end
|
||||
redirect_to login_url, :notice => I18n.t('login.controller.reset_password.notice')
|
||||
redirect_to login_url, notice: I18n.t('login.controller.reset_password.notice')
|
||||
end
|
||||
|
||||
# Set a new password with a token from the password reminder email.
|
||||
# Called with params :id => User.id and :token => User.reset_password_token to specify a new password.
|
||||
def new_password
|
||||
end
|
||||
def new_password; end
|
||||
|
||||
# Sets a new password.
|
||||
# Called with params :id => User.id and :token => User.reset_password_token to specify a new password.
|
||||
|
@ -32,7 +29,7 @@ class LoginController < ApplicationController
|
|||
@user.reset_password_token = nil
|
||||
@user.reset_password_expires = nil
|
||||
@user.save
|
||||
redirect_to login_url, :notice => I18n.t('login.controller.update_password.notice')
|
||||
redirect_to login_url, notice: I18n.t('login.controller.update_password.notice')
|
||||
else
|
||||
render :new_password
|
||||
end
|
||||
|
@ -50,14 +47,14 @@ class LoginController < ApplicationController
|
|||
@user = User.new(params[:user])
|
||||
@user.email = @invite.email
|
||||
if @user.save
|
||||
Membership.new(:user => @user, :group => @invite.group).save!
|
||||
Membership.new(user: @user, group: @invite.group).save!
|
||||
@invite.destroy
|
||||
session[:locale] = @user.locale
|
||||
redirect_to login_url, notice: I18n.t('login.controller.accept_invitation.notice')
|
||||
end
|
||||
end
|
||||
else
|
||||
@user = User.new(:email => @invite.email)
|
||||
@user = User.new(email: @invite.email)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -65,8 +62,8 @@ class LoginController < ApplicationController
|
|||
|
||||
def validate_token
|
||||
@user = User.find_by_id_and_reset_password_token(params[:id], params[:token])
|
||||
if (@user.nil? || @user.reset_password_expires < Time.now)
|
||||
redirect_to forgot_password_url, alert: I18n.t('login.controller.error_token_invalid')
|
||||
end
|
||||
return unless @user.nil? || @user.reset_password_expires < Time.now
|
||||
|
||||
redirect_to forgot_password_url, alert: I18n.t('login.controller.error_token_invalid')
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
class OrderArticlesController < ApplicationController
|
||||
before_action :fetch_order, except: :destroy
|
||||
before_action :authenticate_finance_or_invoices, except: [:new, :create]
|
||||
before_action :authenticate_finance_orders_or_pickup, except: [:edit, :update, :destroy]
|
||||
before_action :authenticate_finance_or_invoices, except: %i[new create]
|
||||
before_action :authenticate_finance_orders_or_pickup, except: %i[edit update destroy]
|
||||
|
||||
layout false # We only use this controller to serve js snippets, no need for layout rendering
|
||||
|
||||
|
@ -9,28 +9,26 @@ class OrderArticlesController < ApplicationController
|
|||
@order_article = @order.order_articles.build(params[:order_article])
|
||||
end
|
||||
|
||||
def edit
|
||||
@order_article = OrderArticle.find(params[:id])
|
||||
end
|
||||
|
||||
def create
|
||||
# The article may be ordered with zero units - in that case do not complain.
|
||||
# If order_article is ordered and a new order_article is created, an error message will be
|
||||
# given mentioning that the article already exists, which is desired.
|
||||
@order_article = @order.order_articles.where(:article_id => params[:order_article][:article_id]).first
|
||||
unless @order_article && @order_article.units_to_order == 0
|
||||
@order_article = @order.order_articles.build(params[:order_article])
|
||||
end
|
||||
@order_article = @order.order_articles.where(article_id: params[:order_article][:article_id]).first
|
||||
@order_article = @order.order_articles.build(params[:order_article]) unless @order_article && @order_article.units_to_order == 0
|
||||
@order_article.save!
|
||||
rescue
|
||||
rescue StandardError
|
||||
render action: :new
|
||||
end
|
||||
|
||||
def edit
|
||||
@order_article = OrderArticle.find(params[:id])
|
||||
end
|
||||
|
||||
def update
|
||||
@order_article = OrderArticle.find(params[:id])
|
||||
begin
|
||||
@order_article.update_article_and_price!(params[:order_article], params[:article], params[:article_price])
|
||||
rescue
|
||||
rescue StandardError
|
||||
render action: :edit
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
class OrderCommentsController < ApplicationController
|
||||
def new
|
||||
@order = Order.find(params[:order_id])
|
||||
@order_comment = @order.comments.build(:user => current_user)
|
||||
@order_comment = @order.comments.build(user: current_user)
|
||||
end
|
||||
|
||||
def create
|
||||
@order_comment = OrderComment.new(params[:order_comment])
|
||||
if @order_comment.save
|
||||
render :layout => false
|
||||
render layout: false
|
||||
else
|
||||
render :action => :new, :layout => false
|
||||
render action: :new, layout: false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -5,25 +5,26 @@ class OrdersController < ApplicationController
|
|||
include Concerns::SendOrderPdf
|
||||
|
||||
before_action :authenticate_pickups_or_orders
|
||||
before_action :authenticate_orders, except: [:receive, :receive_on_order_article_create, :receive_on_order_article_update, :show]
|
||||
before_action :remove_empty_article, only: [:create, :update]
|
||||
before_action :authenticate_orders,
|
||||
except: %i[receive receive_on_order_article_create receive_on_order_article_update show]
|
||||
before_action :remove_empty_article, only: %i[create update]
|
||||
|
||||
# List orders
|
||||
def index
|
||||
@open_orders = Order.open.includes(:supplier)
|
||||
@finished_orders = Order.finished_not_closed.includes(:supplier)
|
||||
@per_page = 15
|
||||
if params['sort']
|
||||
sort = case params['sort']
|
||||
when "supplier" then "suppliers.name, ends DESC"
|
||||
when "pickup" then "pickup DESC"
|
||||
when "ends" then "ends DESC"
|
||||
when "supplier_reverse" then "suppliers.name DESC"
|
||||
when "ends_reverse" then "ends"
|
||||
sort = if params['sort']
|
||||
case params['sort']
|
||||
when 'supplier' then 'suppliers.name, ends DESC'
|
||||
when 'pickup' then 'pickup DESC'
|
||||
when 'ends' then 'ends DESC'
|
||||
when 'supplier_reverse' then 'suppliers.name DESC'
|
||||
when 'ends_reverse' then 'ends'
|
||||
end
|
||||
else
|
||||
sort = "ends DESC"
|
||||
end
|
||||
else
|
||||
'ends DESC'
|
||||
end
|
||||
@suppliers = Supplier.having_articles.order('suppliers.name')
|
||||
@orders = Order.closed.includes(:supplier).reorder(sort).page(params[:page]).per(@per_page)
|
||||
end
|
||||
|
@ -43,7 +44,7 @@ class OrdersController < ApplicationController
|
|||
respond_to do |format|
|
||||
format.html
|
||||
format.js do
|
||||
render :layout => false
|
||||
render layout: false
|
||||
end
|
||||
format.pdf do
|
||||
send_order_pdf @order, params[:document]
|
||||
|
@ -66,8 +67,14 @@ class OrdersController < ApplicationController
|
|||
else
|
||||
@order = Order.new(supplier_id: params[:supplier_id]).init_dates
|
||||
end
|
||||
rescue => error
|
||||
redirect_to orders_url, alert: t('errors.general_msg', msg: error.message)
|
||||
rescue StandardError => e
|
||||
redirect_to orders_url, alert: t('errors.general_msg', msg: e.message)
|
||||
end
|
||||
|
||||
# Page to edit an exsiting order.
|
||||
# editing finished orders is done in FinanceController
|
||||
def edit
|
||||
@order = Order.includes(:articles).find(params[:id])
|
||||
end
|
||||
|
||||
# Save a new order.
|
||||
|
@ -81,31 +88,25 @@ class OrdersController < ApplicationController
|
|||
redirect_to @order
|
||||
else
|
||||
logger.debug "[debug] order errors: #{@order.errors.messages}"
|
||||
render :action => 'new'
|
||||
render action: 'new'
|
||||
end
|
||||
end
|
||||
|
||||
# Page to edit an exsiting order.
|
||||
# editing finished orders is done in FinanceController
|
||||
def edit
|
||||
@order = Order.includes(:articles).find(params[:id])
|
||||
end
|
||||
|
||||
# Update an existing order.
|
||||
def update
|
||||
@order = Order.find params[:id]
|
||||
if @order.update(params[:order].merge(updated_by: current_user))
|
||||
flash[:notice] = I18n.t('orders.update.notice')
|
||||
redirect_to :action => 'show', :id => @order
|
||||
redirect_to action: 'show', id: @order
|
||||
else
|
||||
render :action => 'edit'
|
||||
render action: 'edit'
|
||||
end
|
||||
end
|
||||
|
||||
# Delete an order.
|
||||
def destroy
|
||||
Order.find(params[:id]).destroy
|
||||
redirect_to :action => 'index'
|
||||
redirect_to action: 'index'
|
||||
end
|
||||
|
||||
# Finish a current order.
|
||||
|
@ -113,8 +114,8 @@ class OrdersController < ApplicationController
|
|||
order = Order.find(params[:id])
|
||||
order.finish!(@current_user)
|
||||
redirect_to order, notice: I18n.t('orders.finish.notice')
|
||||
rescue => error
|
||||
redirect_to orders_url, alert: I18n.t('errors.general_msg', :msg => error.message)
|
||||
rescue StandardError => e
|
||||
redirect_to orders_url, alert: I18n.t('errors.general_msg', msg: e.message)
|
||||
end
|
||||
|
||||
# Send a order to the supplier.
|
||||
|
@ -122,20 +123,18 @@ class OrdersController < ApplicationController
|
|||
order = Order.find(params[:id])
|
||||
order.send_to_supplier!(@current_user)
|
||||
redirect_to order, notice: I18n.t('orders.send_to_supplier.notice')
|
||||
rescue => error
|
||||
redirect_to order, alert: I18n.t('errors.general_msg', :msg => error.message)
|
||||
rescue StandardError => e
|
||||
redirect_to order, alert: I18n.t('errors.general_msg', msg: e.message)
|
||||
end
|
||||
|
||||
def receive
|
||||
@order = Order.find(params[:id])
|
||||
unless request.post?
|
||||
@order_articles = @order.order_articles.ordered_or_member.includes(:article).order('articles.order_number, articles.name')
|
||||
else
|
||||
if request.post?
|
||||
Order.transaction do
|
||||
s = update_order_amounts
|
||||
@order.update_attribute(:state, 'received') if @order.state != 'received'
|
||||
|
||||
flash[:notice] = (s ? I18n.t('orders.receive.notice', :msg => s) : I18n.t('orders.receive.notice_none'))
|
||||
flash[:notice] = (s ? I18n.t('orders.receive.notice', msg: s) : I18n.t('orders.receive.notice_none'))
|
||||
end
|
||||
NotifyReceivedOrderJob.perform_later(@order)
|
||||
if current_user.role_orders? || current_user.role_finance?
|
||||
|
@ -145,23 +144,25 @@ class OrdersController < ApplicationController
|
|||
else
|
||||
redirect_to receive_order_path(@order)
|
||||
end
|
||||
else
|
||||
@order_articles = @order.order_articles.ordered_or_member.includes(:article).order('articles.order_number, articles.name')
|
||||
end
|
||||
end
|
||||
|
||||
def receive_on_order_article_create # See publish/subscribe design pattern in /doc.
|
||||
@order_article = OrderArticle.find(params[:order_article_id])
|
||||
render :layout => false
|
||||
render layout: false
|
||||
end
|
||||
|
||||
def receive_on_order_article_update # See publish/subscribe design pattern in /doc.
|
||||
@order_article = OrderArticle.find(params[:order_article_id])
|
||||
render :layout => false
|
||||
render layout: false
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def update_order_amounts
|
||||
return if not params[:order_articles]
|
||||
return unless params[:order_articles]
|
||||
|
||||
# where to leave remainder during redistribution
|
||||
rest_to = []
|
||||
|
@ -176,35 +177,42 @@ class OrdersController < ApplicationController
|
|||
# "MySQL lock timeout exceeded" errors. It's ok to do
|
||||
# this article-by-article anway.
|
||||
params[:order_articles].each do |oa_id, oa_params|
|
||||
unless oa_params.blank?
|
||||
oa = OrderArticle.find(oa_id)
|
||||
# update attributes; don't use update_attribute because it calls save
|
||||
# which makes received_changed? not work anymore
|
||||
oa.attributes = oa_params
|
||||
if oa.units_received_changed?
|
||||
counts[0] += 1
|
||||
unless oa.units_received.blank?
|
||||
cunits[0] += oa.units_received * oa.article.unit_quantity
|
||||
oacounts = oa.redistribute oa.units_received * oa.price.unit_quantity, rest_to
|
||||
oacounts.each_with_index { |c, i| cunits[i + 1] += c; counts[i + 1] += 1 if c > 0 }
|
||||
next if oa_params.blank?
|
||||
|
||||
oa = OrderArticle.find(oa_id)
|
||||
# update attributes; don't use update_attribute because it calls save
|
||||
# which makes received_changed? not work anymore
|
||||
oa.attributes = oa_params
|
||||
if oa.units_received_changed?
|
||||
counts[0] += 1
|
||||
if oa.units_received.present?
|
||||
cunits[0] += oa.units_received * oa.article.unit_quantity
|
||||
oacounts = oa.redistribute oa.units_received * oa.price.unit_quantity, rest_to
|
||||
oacounts.each_with_index do |c, i|
|
||||
cunits[i + 1] += c
|
||||
counts[i + 1] += 1 if c > 0
|
||||
end
|
||||
end
|
||||
oa.save!
|
||||
end
|
||||
oa.save!
|
||||
end
|
||||
return nil if counts[0] == 0
|
||||
|
||||
notice = []
|
||||
notice << I18n.t('orders.update_order_amounts.msg1', count: counts[0], units: cunits[0])
|
||||
notice << I18n.t('orders.update_order_amounts.msg2', count: counts[1], units: cunits[1]) if params[:rest_to_tolerance]
|
||||
if params[:rest_to_tolerance]
|
||||
notice << I18n.t('orders.update_order_amounts.msg2', count: counts[1],
|
||||
units: cunits[1])
|
||||
end
|
||||
notice << I18n.t('orders.update_order_amounts.msg3', count: counts[2], units: cunits[2]) if params[:rest_to_stock]
|
||||
if counts[3] > 0 || cunits[3] > 0
|
||||
notice << I18n.t('orders.update_order_amounts.msg4', count: counts[3], units: cunits[3])
|
||||
notice << I18n.t('orders.update_order_amounts.msg4', count: counts[3],
|
||||
units: cunits[3])
|
||||
end
|
||||
notice.join(', ')
|
||||
end
|
||||
|
||||
def remove_empty_article
|
||||
params[:order][:article_ids].reject!(&:blank?) if params[:order] && params[:order][:article_ids]
|
||||
params[:order][:article_ids].compact_blank! if params[:order] && params[:order][:article_ids]
|
||||
end
|
||||
end
|
||||
|
|
|
@ -12,16 +12,20 @@ class SessionsController < ApplicationController
|
|||
user = User.authenticate(params[:nick], params[:password])
|
||||
if user
|
||||
user.update_attribute(:last_login, Time.now)
|
||||
login_and_redirect_to_return_to user, :notice => I18n.t('sessions.logged_in')
|
||||
login_and_redirect_to_return_to user, notice: I18n.t('sessions.logged_in')
|
||||
else
|
||||
flash.now.alert = I18n.t(FoodsoftConfig[:use_nick] ? 'sessions.login_invalid_nick' : 'sessions.login_invalid_email')
|
||||
render "new"
|
||||
render 'new'
|
||||
end
|
||||
end
|
||||
|
||||
def destroy
|
||||
logout
|
||||
redirect_to login_url, :notice => I18n.t('sessions.logged_out')
|
||||
if FoodsoftConfig[:logout_redirect_url].present?
|
||||
redirect_to FoodsoftConfig[:logout_redirect_url]
|
||||
else
|
||||
redirect_to login_url, notice: I18n.t('sessions.logged_out')
|
||||
end
|
||||
end
|
||||
|
||||
# redirect to root, going to default foodcoop when none given
|
||||
|
|
|
@ -7,21 +7,21 @@ class StockTakingsController < ApplicationController
|
|||
|
||||
def new
|
||||
@stock_taking = StockTaking.new
|
||||
StockArticle.undeleted.each { |a| @stock_taking.stock_changes.build(:stock_article => a) }
|
||||
StockArticle.undeleted.each { |a| @stock_taking.stock_changes.build(stock_article: a) }
|
||||
end
|
||||
|
||||
def new_on_stock_article_create # See publish/subscribe design pattern in /doc.
|
||||
stock_article = StockArticle.find(params[:stock_article_id])
|
||||
@stock_change = StockChange.new(:stock_article => stock_article)
|
||||
@stock_change = StockChange.new(stock_article: stock_article)
|
||||
|
||||
render :layout => false
|
||||
render layout: false
|
||||
end
|
||||
|
||||
def create
|
||||
create!(:notice => I18n.t('stock_takings.create.notice'))
|
||||
create!(notice: I18n.t('stock_takings.create.notice'))
|
||||
end
|
||||
|
||||
def update
|
||||
update!(:notice => I18n.t('stock_takings.update.notice'))
|
||||
update!(notice: I18n.t('stock_takings.update.notice'))
|
||||
end
|
||||
end
|
||||
|
|
|
@ -7,57 +7,13 @@ class StockitController < ApplicationController
|
|||
def index_on_stock_article_create # See publish/subscribe design pattern in /doc.
|
||||
@stock_article = StockArticle.find(params[:id])
|
||||
|
||||
render :layout => false
|
||||
render layout: false
|
||||
end
|
||||
|
||||
def index_on_stock_article_update # See publish/subscribe design pattern in /doc.
|
||||
@stock_article = StockArticle.find(params[:id])
|
||||
|
||||
render :layout => false
|
||||
end
|
||||
|
||||
# three possibilites to fill a new_stock_article form
|
||||
# (1) start from blank or use params
|
||||
def new
|
||||
@stock_article = StockArticle.new(params[:stock_article])
|
||||
|
||||
render :layout => false
|
||||
end
|
||||
|
||||
# (2) StockArticle as template
|
||||
def copy
|
||||
@stock_article = StockArticle.find(params[:stock_article_id]).dup
|
||||
|
||||
render :layout => false
|
||||
end
|
||||
|
||||
# (3) non-stock Article as template
|
||||
def derive
|
||||
@stock_article = Article.find(params[:old_article_id]).becomes(StockArticle).dup
|
||||
|
||||
render :layout => false
|
||||
end
|
||||
|
||||
def create
|
||||
@stock_article = StockArticle.new({ quantity: 0 }.merge(params[:stock_article]))
|
||||
@stock_article.save!
|
||||
render :layout => false
|
||||
rescue ActiveRecord::RecordInvalid
|
||||
render :action => 'new', :layout => false
|
||||
end
|
||||
|
||||
def edit
|
||||
@stock_article = StockArticle.find(params[:id])
|
||||
|
||||
render :layout => false
|
||||
end
|
||||
|
||||
def update
|
||||
@stock_article = StockArticle.find(params[:id])
|
||||
@stock_article.update!(params[:stock_article])
|
||||
render :layout => false
|
||||
rescue ActiveRecord::RecordInvalid
|
||||
render :action => 'edit', :layout => false
|
||||
render layout: false
|
||||
end
|
||||
|
||||
def show
|
||||
|
@ -65,24 +21,68 @@ class StockitController < ApplicationController
|
|||
@stock_changes = @stock_article.stock_changes.order('stock_changes.created_at DESC')
|
||||
end
|
||||
|
||||
# three possibilites to fill a new_stock_article form
|
||||
# (1) start from blank or use params
|
||||
def new
|
||||
@stock_article = StockArticle.new(params[:stock_article])
|
||||
|
||||
render layout: false
|
||||
end
|
||||
|
||||
# (2) StockArticle as template
|
||||
def copy
|
||||
@stock_article = StockArticle.find(params[:stock_article_id]).dup
|
||||
|
||||
render layout: false
|
||||
end
|
||||
|
||||
# (3) non-stock Article as template
|
||||
def derive
|
||||
@stock_article = Article.find(params[:old_article_id]).becomes(StockArticle).dup
|
||||
|
||||
render layout: false
|
||||
end
|
||||
|
||||
def edit
|
||||
@stock_article = StockArticle.find(params[:id])
|
||||
|
||||
render layout: false
|
||||
end
|
||||
|
||||
def create
|
||||
@stock_article = StockArticle.new({ quantity: 0 }.merge(params[:stock_article]))
|
||||
@stock_article.save!
|
||||
render layout: false
|
||||
rescue ActiveRecord::RecordInvalid
|
||||
render action: 'new', layout: false
|
||||
end
|
||||
|
||||
def update
|
||||
@stock_article = StockArticle.find(params[:id])
|
||||
@stock_article.update!(params[:stock_article])
|
||||
render layout: false
|
||||
rescue ActiveRecord::RecordInvalid
|
||||
render action: 'edit', layout: false
|
||||
end
|
||||
|
||||
def show_on_stock_article_update # See publish/subscribe design pattern in /doc.
|
||||
@stock_article = StockArticle.find(params[:id])
|
||||
|
||||
render :layout => false
|
||||
render layout: false
|
||||
end
|
||||
|
||||
def destroy
|
||||
@stock_article = StockArticle.find(params[:id])
|
||||
@stock_article.mark_as_deleted
|
||||
render :layout => false
|
||||
rescue => error
|
||||
render :partial => "destroy_fail", :layout => false,
|
||||
:locals => { :fail_msg => I18n.t('errors.general_msg', :msg => error.message) }
|
||||
render layout: false
|
||||
rescue StandardError => e
|
||||
render partial: 'destroy_fail', layout: false,
|
||||
locals: { fail_msg: I18n.t('errors.general_msg', msg: e.message) }
|
||||
end
|
||||
|
||||
# TODO: Fix this!!
|
||||
def articles_search
|
||||
@articles = Article.not_in_stock.limit(8).where('name LIKE ?', "%#{params[:term]}%")
|
||||
render :json => @articles.map(&:name)
|
||||
render json: @articles.map(&:name)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -9,7 +9,7 @@ class StylesController < ApplicationController
|
|||
def foodcoop
|
||||
css = FoodsoftConfig[:custom_css]
|
||||
if css.blank?
|
||||
render body: nil, content_type: 'text/css', status: 404
|
||||
render body: nil, content_type: 'text/css', status: :not_found
|
||||
else
|
||||
expires_in 1.week, public: true if params[:md5].present?
|
||||
render body: css, content_type: 'text/css'
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
class SuppliersController < ApplicationController
|
||||
before_action :authenticate_suppliers, :except => [:index, :list]
|
||||
before_action :authenticate_suppliers, except: %i[index list]
|
||||
helper :deliveries
|
||||
|
||||
def index
|
||||
|
@ -24,6 +24,10 @@ class SuppliersController < ApplicationController
|
|||
end
|
||||
end
|
||||
|
||||
def edit
|
||||
@supplier = Supplier.find(params[:id])
|
||||
end
|
||||
|
||||
def create
|
||||
@supplier = Supplier.new(supplier_params)
|
||||
@supplier.supplier_category ||= SupplierCategory.first
|
||||
|
@ -31,21 +35,17 @@ class SuppliersController < ApplicationController
|
|||
flash[:notice] = I18n.t('suppliers.create.notice')
|
||||
redirect_to suppliers_path
|
||||
else
|
||||
render :action => 'new'
|
||||
render action: 'new'
|
||||
end
|
||||
end
|
||||
|
||||
def edit
|
||||
@supplier = Supplier.find(params[:id])
|
||||
end
|
||||
|
||||
def update
|
||||
@supplier = Supplier.find(params[:id])
|
||||
if @supplier.update(supplier_params)
|
||||
flash[:notice] = I18n.t('suppliers.update.notice')
|
||||
redirect_to @supplier
|
||||
else
|
||||
render :action => 'edit'
|
||||
render action: 'edit'
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -54,8 +54,8 @@ class SuppliersController < ApplicationController
|
|||
@supplier.mark_as_deleted
|
||||
flash[:notice] = I18n.t('suppliers.destroy.notice')
|
||||
redirect_to suppliers_path
|
||||
rescue => e
|
||||
flash[:error] = I18n.t('errors.general_msg', :msg => e.message)
|
||||
rescue StandardError => e
|
||||
flash[:error] = I18n.t('errors.general_msg', msg: e.message)
|
||||
redirect_to @supplier
|
||||
end
|
||||
|
||||
|
|
|
@ -11,35 +11,33 @@ class TasksController < ApplicationController
|
|||
@accepted_tasks = Task.accepted_tasks_for(current_user)
|
||||
end
|
||||
|
||||
def new
|
||||
@task = Task.new(current_user_id: current_user.id)
|
||||
end
|
||||
|
||||
def create
|
||||
@task = Task.new(current_user_id: current_user.id)
|
||||
@task.created_by = current_user
|
||||
@task.attributes = (task_params)
|
||||
if params[:periodic]
|
||||
@task.periodic_task_group = PeriodicTaskGroup.new
|
||||
end
|
||||
if @task.save
|
||||
@task.periodic_task_group.create_tasks_for_upfront_days if params[:periodic]
|
||||
redirect_to tasks_url, :notice => I18n.t('tasks.create.notice')
|
||||
else
|
||||
render :template => "tasks/new"
|
||||
end
|
||||
end
|
||||
|
||||
def show
|
||||
@task = Task.find(params[:id])
|
||||
end
|
||||
|
||||
def new
|
||||
@task = Task.new(current_user_id: current_user.id)
|
||||
end
|
||||
|
||||
def edit
|
||||
@task = Task.find(params[:id])
|
||||
@periodic = !!params[:periodic]
|
||||
@task.current_user_id = current_user.id
|
||||
end
|
||||
|
||||
def create
|
||||
@task = Task.new(current_user_id: current_user.id)
|
||||
@task.created_by = current_user
|
||||
@task.attributes = (task_params)
|
||||
@task.periodic_task_group = PeriodicTaskGroup.new if params[:periodic]
|
||||
if @task.save
|
||||
@task.periodic_task_group.create_tasks_for_upfront_days if params[:periodic]
|
||||
redirect_to tasks_url, notice: I18n.t('tasks.create.notice')
|
||||
else
|
||||
render template: 'tasks/new'
|
||||
end
|
||||
end
|
||||
|
||||
def update
|
||||
@task = Task.find(params[:id])
|
||||
task_group = @task.periodic_task_group
|
||||
|
@ -50,16 +48,14 @@ class TasksController < ApplicationController
|
|||
if @task.errors.empty? && @task.save
|
||||
task_group.update_tasks_including(@task, prev_due_date) if params[:periodic]
|
||||
flash[:notice] = I18n.t('tasks.update.notice')
|
||||
if was_periodic && !@task.periodic?
|
||||
flash[:notice] = I18n.t('tasks.update.notice_converted')
|
||||
end
|
||||
flash[:notice] = I18n.t('tasks.update.notice_converted') if was_periodic && !@task.periodic?
|
||||
if @task.workgroup
|
||||
redirect_to workgroup_tasks_url(workgroup_id: @task.workgroup_id)
|
||||
else
|
||||
redirect_to tasks_url
|
||||
end
|
||||
else
|
||||
render :template => "tasks/edit"
|
||||
render template: 'tasks/edit'
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -75,7 +71,7 @@ class TasksController < ApplicationController
|
|||
end
|
||||
task.update_ordergroup_stats(user_ids)
|
||||
|
||||
redirect_to tasks_url, :notice => I18n.t('tasks.destroy.notice')
|
||||
redirect_to tasks_url, notice: I18n.t('tasks.destroy.notice')
|
||||
end
|
||||
|
||||
# assign current_user to the task and set the assignment to "accepted"
|
||||
|
@ -85,20 +81,20 @@ class TasksController < ApplicationController
|
|||
if ass = task.is_assigned?(current_user)
|
||||
ass.update_attribute(:accepted, true)
|
||||
else
|
||||
task.assignments.create(:user => current_user, :accepted => true)
|
||||
task.assignments.create(user: current_user, accepted: true)
|
||||
end
|
||||
redirect_to user_tasks_path, :notice => I18n.t('tasks.accept.notice')
|
||||
redirect_to user_tasks_path, notice: I18n.t('tasks.accept.notice')
|
||||
end
|
||||
|
||||
# deletes assignment between current_user and given taskcurrent_user_id: current_user.id
|
||||
def reject
|
||||
Task.find(params[:id]).users.delete(current_user)
|
||||
redirect_to :action => "index"
|
||||
redirect_to action: 'index'
|
||||
end
|
||||
|
||||
def set_done
|
||||
Task.find(params[:id]).update_attribute :done, true
|
||||
redirect_to tasks_url, :notice => I18n.t('tasks.set_done.notice')
|
||||
redirect_to tasks_url, notice: I18n.t('tasks.set_done.notice')
|
||||
end
|
||||
|
||||
# Shows all tasks, which are already done
|
||||
|
@ -109,9 +105,9 @@ class TasksController < ApplicationController
|
|||
# shows workgroup (normal group) to edit weekly_tasks_template
|
||||
def workgroup
|
||||
@group = Group.find(params[:workgroup_id])
|
||||
if @group.is_a? Ordergroup
|
||||
redirect_to tasks_url, :alert => I18n.t('tasks.error_not_found')
|
||||
end
|
||||
return unless @group.is_a? Ordergroup
|
||||
|
||||
redirect_to tasks_url, alert: I18n.t('tasks.error_not_found')
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
@ -3,7 +3,7 @@ class UsersController < ApplicationController
|
|||
def index
|
||||
@users = User.undeleted.natural_search(params[:q])
|
||||
respond_to do |format|
|
||||
format.json { render :json => @users.map(&:token_attributes).to_json }
|
||||
format.json { render json: @users.map(&:token_attributes).to_json }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
class OrderByArticles < OrderPdf
|
||||
def filename
|
||||
I18n.t('documents.order_by_articles.filename', :name => order.name, :date => order.ends.to_date) + '.pdf'
|
||||
I18n.t('documents.order_by_articles.filename', name: order.name, date: order.ends.to_date) + '.pdf'
|
||||
end
|
||||
|
||||
def title
|
||||
I18n.t('documents.order_by_articles.title', :name => order.name,
|
||||
:date => order.ends.strftime(I18n.t('date.formats.default')))
|
||||
I18n.t('documents.order_by_articles.title', name: order.name,
|
||||
date: order.ends.strftime(I18n.t('date.formats.default')))
|
||||
end
|
||||
|
||||
def body
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
class OrderByGroups < OrderPdf
|
||||
def filename
|
||||
I18n.t('documents.order_by_groups.filename', :name => order.name, :date => order.ends.to_date) + '.pdf'
|
||||
I18n.t('documents.order_by_groups.filename', name: order.name, date: order.ends.to_date) + '.pdf'
|
||||
end
|
||||
|
||||
def title
|
||||
I18n.t('documents.order_by_groups.title', :name => order.name,
|
||||
:date => order.ends.strftime(I18n.t('date.formats.default')))
|
||||
I18n.t('documents.order_by_groups.title', name: order.name,
|
||||
date: order.ends.strftime(I18n.t('date.formats.default')))
|
||||
end
|
||||
|
||||
def body
|
||||
|
|
|
@ -2,7 +2,7 @@ class OrderFax < OrderPdf
|
|||
BATCH_SIZE = 250
|
||||
|
||||
def filename
|
||||
I18n.t('documents.order_fax.filename', :name => order.name, :date => order.ends.to_date) + '.pdf'
|
||||
I18n.t('documents.order_fax.filename', name: order.name, date: order.ends.to_date) + '.pdf'
|
||||
end
|
||||
|
||||
def title
|
||||
|
@ -20,16 +20,18 @@ class OrderFax < OrderPdf
|
|||
move_down 5
|
||||
text "#{contact[:zip_code]} #{contact[:city]}", size: fontsize(9), align: :right
|
||||
move_down 5
|
||||
unless order.supplier.try(:customer_number).blank?
|
||||
text "#{Supplier.human_attribute_name :customer_number}: #{order.supplier[:customer_number]}", size: fontsize(9), align: :right
|
||||
if order.supplier.try(:customer_number).present?
|
||||
text "#{Supplier.human_attribute_name :customer_number}: #{order.supplier[:customer_number]}",
|
||||
size: fontsize(9), align: :right
|
||||
move_down 5
|
||||
end
|
||||
unless contact[:phone].blank?
|
||||
if contact[:phone].present?
|
||||
text "#{Supplier.human_attribute_name :phone}: #{contact[:phone]}", size: fontsize(9), align: :right
|
||||
move_down 5
|
||||
end
|
||||
unless contact[:email].blank?
|
||||
text "#{Supplier.human_attribute_name :email}: #{contact[:email]}", size: fontsize(9), align: :right
|
||||
if contact[:email].present?
|
||||
text "#{Supplier.human_attribute_name :email}: #{contact[:email]}", size: fontsize(9),
|
||||
align: :right
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -38,7 +40,7 @@ class OrderFax < OrderPdf
|
|||
text order.name
|
||||
move_down 5
|
||||
text order.supplier.try(:address).to_s
|
||||
unless order.supplier.try(:fax).blank?
|
||||
if order.supplier.try(:fax).present?
|
||||
move_down 5
|
||||
text "#{Supplier.human_attribute_name :fax}: #{order.supplier[:fax]}"
|
||||
end
|
||||
|
@ -50,7 +52,7 @@ class OrderFax < OrderPdf
|
|||
move_down 10
|
||||
text "#{Delivery.human_attribute_name :date}:"
|
||||
move_down 10
|
||||
unless order.supplier.try(:contact_person).blank?
|
||||
if order.supplier.try(:contact_person).present?
|
||||
text "#{Supplier.human_attribute_name :contact_person}: #{order.supplier[:contact_person]}"
|
||||
move_down 10
|
||||
end
|
||||
|
@ -78,8 +80,8 @@ class OrderFax < OrderPdf
|
|||
table.row(0).border_bottom_width = 2
|
||||
table.columns(1).align = :right
|
||||
table.columns(3..6).align = :right
|
||||
table.row(data.length - 1).columns(0..5).borders = [:top, :bottom]
|
||||
table.row(data.length - 1).columns(0).borders = [:top, :bottom, :left]
|
||||
table.row(data.length - 1).columns(0..5).borders = %i[top bottom]
|
||||
table.row(data.length - 1).columns(0).borders = %i[top bottom left]
|
||||
table.row(data.length - 1).border_top_width = 2
|
||||
end
|
||||
# font_size: fontsize(8),
|
||||
|
@ -98,7 +100,7 @@ class OrderFax < OrderPdf
|
|||
.preload(:article, :article_price)
|
||||
end
|
||||
|
||||
def each_order_article
|
||||
order_articles.find_each_with_order(batch_size: BATCH_SIZE) { |oa| yield oa }
|
||||
def each_order_article(&block)
|
||||
order_articles.find_each_with_order(batch_size: BATCH_SIZE, &block)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -3,12 +3,12 @@ class OrderMatrix < OrderPdf
|
|||
PLACEHOLDER_CHAR = 'X'
|
||||
|
||||
def filename
|
||||
I18n.t('documents.order_matrix.filename', :name => @order.name, :date => @order.ends.to_date) + '.pdf'
|
||||
I18n.t('documents.order_matrix.filename', name: @order.name, date: @order.ends.to_date) + '.pdf'
|
||||
end
|
||||
|
||||
def title
|
||||
I18n.t('documents.order_matrix.title', :name => @order.name,
|
||||
:date => @order.ends.strftime(I18n.t('date.formats.default')))
|
||||
I18n.t('documents.order_matrix.title', name: @order.name,
|
||||
date: @order.ends.strftime(I18n.t('date.formats.default')))
|
||||
end
|
||||
|
||||
def body
|
||||
|
@ -87,7 +87,7 @@ class OrderMatrix < OrderPdf
|
|||
table.cells.border_width = 0.5
|
||||
table.cells.border_color = '666666'
|
||||
|
||||
table.row(0).borders = [:bottom, :left]
|
||||
table.row(0).borders = %i[bottom left]
|
||||
table.row(0).padding = [2, 0, 2, 0]
|
||||
table.row(1..-1).height = row_height_1
|
||||
table.column(0..1).borders = []
|
||||
|
@ -106,7 +106,7 @@ class OrderMatrix < OrderPdf
|
|||
table.column(2 + idx).border_width = 2
|
||||
end
|
||||
|
||||
table.row_colors = ['dddddd', 'ffffff']
|
||||
table.row_colors = %w[dddddd ffffff]
|
||||
end
|
||||
|
||||
first_page = false
|
||||
|
|
|
@ -28,7 +28,11 @@ module Admin::ConfigsHelper
|
|||
options[:default] = options[:input_html].delete(:value)
|
||||
return form.input key, options, &block
|
||||
end
|
||||
block ||= proc { config_input_field form, key, options.merge(options[:input_html]) } if options[:as] == :select_recurring
|
||||
if options[:as] == :select_recurring
|
||||
block ||= proc {
|
||||
config_input_field form, key, options.merge(options[:input_html])
|
||||
}
|
||||
end
|
||||
form.input key, options, &block
|
||||
end
|
||||
|
||||
|
@ -57,11 +61,12 @@ module Admin::ConfigsHelper
|
|||
unchecked_value = options.delete(:unchecked_value) || 'false'
|
||||
options[:checked] = 'checked' if v = options.delete(:value) && v != 'false'
|
||||
# different key for hidden field so that allow clocking on label focuses the control
|
||||
form.hidden_field(key, id: "#{key}_", value: unchecked_value, as: :hidden) + form.check_box(key, options, checked_value, false)
|
||||
form.hidden_field(key, id: "#{key}_", value: unchecked_value,
|
||||
as: :hidden) + form.check_box(key, options, checked_value, false)
|
||||
elsif options[:as] == :select_recurring
|
||||
options[:value] = FoodsoftDateUtil.rule_from(options[:value])
|
||||
options[:rules] ||= []
|
||||
options[:rules].unshift options[:value] unless options[:value].blank?
|
||||
options[:rules].unshift options[:value] if options[:value].present?
|
||||
options[:rules].push [I18n.t('recurring_select.not_recurring'), '{}'] if options.delete(:allow_blank) # blank after current value
|
||||
form.select_recurring key, options.delete(:rules).uniq, options
|
||||
else
|
||||
|
@ -73,7 +78,7 @@ module Admin::ConfigsHelper
|
|||
# @param form [ActionView::Helpers::FormBuilder] Form object.
|
||||
# @param key [Symbol, String] Configuration key of a boolean (e.g. +use_messages+).
|
||||
# @option options [String] :label Label to show
|
||||
def config_use_heading(form, key, options = {})
|
||||
def config_use_heading(form, key, options = {}, &block)
|
||||
head = content_tag :label do
|
||||
lbl = options[:label] || config_input_label(form, key)
|
||||
field = config_input_field(form, key, as: :boolean, boolean_style: :inline,
|
||||
|
@ -83,9 +88,7 @@ module Admin::ConfigsHelper
|
|||
content_tag :span, (lbl + field).html_safe, config_input_tooltip_options(form, key, {})
|
||||
end
|
||||
end
|
||||
fields = content_tag(:fieldset, id: "#{key}-fields", class: "collapse#{' in' if @cfg[key]}") do
|
||||
yield
|
||||
end
|
||||
fields = content_tag(:fieldset, id: "#{key}-fields", class: "collapse#{' in' if @cfg[key]}", &block)
|
||||
head + fields
|
||||
end
|
||||
|
||||
|
@ -127,7 +130,7 @@ module Admin::ConfigsHelper
|
|||
# tooltip with help info to the right
|
||||
cfg_path = form.lookup_model_names[1..-1] + [key]
|
||||
tooltip = I18n.t("config.hints.#{cfg_path.map(&:to_s).join('.')}", default: '')
|
||||
unless tooltip.blank?
|
||||
if tooltip.present?
|
||||
options[:data] ||= {}
|
||||
options[:data][:toggle] ||= 'tooltip'
|
||||
options[:data][:placement] ||= 'right'
|
||||
|
|
|
@ -2,9 +2,7 @@ module Admin::OrdergroupsHelper
|
|||
def ordergroup_members_title(ordergroup)
|
||||
s = ''
|
||||
s += ordergroup.users.map(&:name).join(', ') if ordergroup.users.any?
|
||||
if ordergroup.contact_person.present?
|
||||
s += "\n" + Ordergroup.human_attribute_name(:contact) + ": " + ordergroup.contact_person
|
||||
end
|
||||
s += "\n" + Ordergroup.human_attribute_name(:contact) + ': ' + ordergroup.contact_person if ordergroup.contact_person.present?
|
||||
s
|
||||
end
|
||||
end
|
||||
|
|
|
@ -4,7 +4,7 @@ module ApplicationHelper
|
|||
include PathHelper
|
||||
|
||||
def format_time(time = Time.now)
|
||||
I18n.l(time, :format => "%d.%m.%Y %H:%M") unless time.nil?
|
||||
I18n.l(time, format: :foodsoft_datetime) unless time.nil?
|
||||
end
|
||||
|
||||
def format_date(time = Time.now)
|
||||
|
@ -16,7 +16,7 @@ module ApplicationHelper
|
|||
end
|
||||
|
||||
def format_datetime_timespec(time, format)
|
||||
I18n.l(time, :format => format) unless (time.nil? || format.nil?)
|
||||
I18n.l(time, format: format) unless time.nil? || format.nil?
|
||||
end
|
||||
|
||||
def format_currency(amount)
|
||||
|
@ -26,28 +26,28 @@ module ApplicationHelper
|
|||
|
||||
# Splits an IBAN into groups of 4 digits displayed with margins in between
|
||||
def format_iban(iban)
|
||||
iban && iban.scan(/..?.?.?/).map { |item| content_tag(:span, item, style: "margin-right: 0.5em;") }.join.html_safe
|
||||
iban && iban.scan(/..?.?.?/).map { |item| content_tag(:span, item, style: 'margin-right: 0.5em;') }.join.html_safe
|
||||
end
|
||||
|
||||
# Creates ajax-controlled-links for pagination
|
||||
def pagination_links_remote(collection, options = {})
|
||||
per_page = options[:per_page] || @per_page
|
||||
params = options[:params] || {}
|
||||
params = params.merge({ :per_page => per_page })
|
||||
paginate collection, :params => params, :remote => true
|
||||
params = params.merge({ per_page: per_page })
|
||||
paginate collection, params: params, remote: true
|
||||
end
|
||||
|
||||
# Link-collection for per_page-options when using the pagination-plugin
|
||||
def items_per_page(options = {})
|
||||
per_page_options = options[:per_page_options] || [20, 50, 100, 500]
|
||||
current = options[:current] || @per_page
|
||||
params = params || {}
|
||||
params ||= {}
|
||||
|
||||
links = per_page_options.map do |per_page|
|
||||
params.merge!({ :per_page => per_page })
|
||||
params.merge!({ per_page: per_page })
|
||||
link_class = 'btn'
|
||||
link_class << ' disabled' if per_page == current
|
||||
link_to(per_page, params, :remote => true, class: link_class)
|
||||
link_to(per_page, params, remote: true, class: link_class)
|
||||
end
|
||||
|
||||
if options[:wrap] == false
|
||||
|
@ -63,21 +63,19 @@ module ApplicationHelper
|
|||
# Hmtl options
|
||||
remote = options[:remote].nil? ? true : options[:remote]
|
||||
class_name = case params[:sort]
|
||||
when key then
|
||||
when key
|
||||
'sortup'
|
||||
when key + '_reverse' then
|
||||
when key + '_reverse'
|
||||
'sortdown'
|
||||
else
|
||||
nil
|
||||
end
|
||||
html_options = {
|
||||
:title => I18n.t('helpers.application.sort_by', text: text),
|
||||
:remote => remote,
|
||||
:class => class_name
|
||||
title: I18n.t('helpers.application.sort_by', text: text),
|
||||
remote: remote,
|
||||
class: class_name
|
||||
}
|
||||
|
||||
# Url options
|
||||
key += "_reverse" if params[:sort] == key
|
||||
key += '_reverse' if params[:sort] == key
|
||||
per_page = options[:per_page] || @per_page
|
||||
url_options = params.merge(per_page: per_page, sort: key)
|
||||
url_options.merge!({ page: params[:page] }) if params[:page]
|
||||
|
@ -95,14 +93,16 @@ module ApplicationHelper
|
|||
# be overridden by the option 'desc'.
|
||||
# Other options are passed through to I18n.
|
||||
def heading_helper(model, attribute, options = {})
|
||||
i18nopts = { count: 2 }.merge(options.select { |a| !['short', 'desc'].include?(a) })
|
||||
i18nopts = { count: 2 }.merge(options.select { |a| !%w[short desc].include?(a) })
|
||||
s = model.human_attribute_name(attribute, i18nopts)
|
||||
if options[:short]
|
||||
desc = options[:desc]
|
||||
desc ||= model.human_attribute_name("#{attribute}_desc".to_sym, options.merge({ fallback: true, default: '', count: 2 }))
|
||||
desc ||= model.human_attribute_name("#{attribute}_desc".to_sym,
|
||||
options.merge({ fallback: true, default: '', count: 2 }))
|
||||
desc.blank? && desc = s
|
||||
sshort = model.human_attribute_name("#{attribute}_short".to_sym, options.merge({ fallback: true, default: '', count: 2 }))
|
||||
s = raw "<abbr title='#{desc}'>#{sshort}</abbr>" unless sshort.blank?
|
||||
sshort = model.human_attribute_name("#{attribute}_short".to_sym,
|
||||
options.merge({ fallback: true, default: '', count: 2 }))
|
||||
s = raw "<abbr title='#{desc}'>#{sshort}</abbr>" if sshort.present?
|
||||
end
|
||||
s
|
||||
end
|
||||
|
@ -117,7 +117,7 @@ module ApplicationHelper
|
|||
# Returns the weekday. 0 is sunday, 1 is monday and so on
|
||||
def weekday(dayNumber)
|
||||
weekdays = I18n.t('date.day_names')
|
||||
return weekdays[dayNumber]
|
||||
weekdays[dayNumber]
|
||||
end
|
||||
|
||||
# to set a title for both the h1-tag and the title in the header
|
||||
|
@ -136,13 +136,13 @@ module ApplicationHelper
|
|||
|
||||
def icon(name, options = {})
|
||||
icons = {
|
||||
:delete => { :file => 'b_drop.png', :alt => I18n.t('ui.delete') },
|
||||
:edit => { :file => 'b_edit.png', :alt => I18n.t('ui.edit') },
|
||||
:members => { :file => 'b_users.png', :alt => I18n.t('helpers.application.edit_user') }
|
||||
delete: { file: 'b_drop.png', alt: I18n.t('ui.delete') },
|
||||
edit: { file: 'b_edit.png', alt: I18n.t('ui.edit') },
|
||||
members: { file: 'b_users.png', alt: I18n.t('helpers.application.edit_user') }
|
||||
}
|
||||
options[:alt] ||= icons[name][:alt]
|
||||
options[:title] ||= icons[name][:title]
|
||||
options.merge!({ :size => '16x16', :border => "0" })
|
||||
options.merge!({ size: '16x16', border: '0' })
|
||||
|
||||
image_tag icons[name][:file], options
|
||||
end
|
||||
|
@ -150,27 +150,29 @@ module ApplicationHelper
|
|||
# Remote links with default 'loader'.gif during request
|
||||
def remote_link_to(text, options = {})
|
||||
remote_options = {
|
||||
:before => "Element.show('loader')",
|
||||
:success => "Element.hide('loader')",
|
||||
:method => :get
|
||||
before: "Element.show('loader')",
|
||||
success: "Element.hide('loader')",
|
||||
method: :get
|
||||
}
|
||||
link_to(text, options[:url], remote_options.merge(options))
|
||||
end
|
||||
|
||||
def format_roles(record, icon = false)
|
||||
roles = %w(suppliers article_meta orders pickups finance invoices admin)
|
||||
roles = %w[suppliers article_meta orders pickups finance invoices admin]
|
||||
roles.select! { |role| record.send "role_#{role}?" }
|
||||
names = Hash[roles.map { |r| [r, I18n.t("helpers.application.role_#{r}")] }]
|
||||
names = roles.index_with { |r| I18n.t("helpers.application.role_#{r}") }
|
||||
if icon
|
||||
roles.map { |r| image_tag("role-#{r}.png", size: '22x22', border: 0, alt: names[r], title: names[r]) }.join(' ').html_safe
|
||||
roles.map do |r|
|
||||
image_tag("role-#{r}.png", size: '22x22', border: 0, alt: names[r], title: names[r])
|
||||
end.join(' ').html_safe
|
||||
else
|
||||
roles.map { |r| names[r] }.join(', ')
|
||||
end
|
||||
end
|
||||
|
||||
def link_to_gmaps(address)
|
||||
link_to h(address), "http://maps.google.com/?q=#{h(address)}", :title => I18n.t('helpers.application.show_google_maps'),
|
||||
:target => "_blank"
|
||||
link_to h(address), "http://maps.google.com/?q=#{h(address)}", title: I18n.t('helpers.application.show_google_maps'),
|
||||
target: '_blank', rel: 'noopener'
|
||||
end
|
||||
|
||||
# Returns flash messages html.
|
||||
|
@ -186,8 +188,8 @@ module ApplicationHelper
|
|||
type = :success if type == 'notice'
|
||||
type = :error if type == 'alert'
|
||||
text = content_tag(:div,
|
||||
content_tag(:button, I18n.t('ui.marks.close').html_safe, :class => "close", "data-dismiss" => "alert") +
|
||||
message, :class => "alert fade in alert-#{type}")
|
||||
content_tag(:button, I18n.t('ui.marks.close').html_safe, :class => 'close', 'data-dismiss' => 'alert') +
|
||||
message, class: "alert fade in alert-#{type}")
|
||||
flash_messages << text if message
|
||||
end
|
||||
flash_messages.join("\n").html_safe
|
||||
|
@ -195,17 +197,17 @@ module ApplicationHelper
|
|||
|
||||
# render base errors in a form after failed validation
|
||||
# http://railsapps.github.io/twitter-bootstrap-rails.html
|
||||
def base_errors resource
|
||||
def base_errors(resource)
|
||||
return '' if resource.errors.empty? || resource.errors[:base].empty?
|
||||
|
||||
messages = resource.errors[:base].map { |msg| content_tag(:li, msg) }.join
|
||||
render :partial => 'shared/base_errors', :locals => { :error_messages => messages }
|
||||
render partial: 'shared/base_errors', locals: { error_messages: messages }
|
||||
end
|
||||
|
||||
# show a user, depending on settings
|
||||
def show_user(user = @current_user, options = {})
|
||||
if user.nil?
|
||||
"?"
|
||||
'?'
|
||||
elsif FoodsoftConfig[:use_nick]
|
||||
if options[:full] && options[:markup]
|
||||
raw "<b>#{h user.nick}</b> (#{h user.first_name} #{h user.last_name})"
|
||||
|
@ -216,7 +218,7 @@ module ApplicationHelper
|
|||
user.nick.nil? ? I18n.t('helpers.application.nick_fallback') : user.nick
|
||||
end
|
||||
else
|
||||
"#{user.first_name} #{user.last_name}" + (options[:unique] ? " (\##{user.id})" : '')
|
||||
"#{user.first_name} #{user.last_name}" + (options[:unique] ? " (##{user.id})" : '')
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -258,9 +260,9 @@ module ApplicationHelper
|
|||
|
||||
# @return [String] stylesheet tag for foodcoop CSS style (+custom_css+ foodcoop config)
|
||||
# @see #foodcoop_css_path
|
||||
def foodcoop_css_tag(options = {})
|
||||
unless FoodsoftConfig[:custom_css].blank?
|
||||
stylesheet_link_tag foodcoop_css_path, media: 'all'
|
||||
end
|
||||
def foodcoop_css_tag(_options = {})
|
||||
return if FoodsoftConfig[:custom_css].blank?
|
||||
|
||||
stylesheet_link_tag foodcoop_css_path, media: 'all'
|
||||
end
|
||||
end
|
||||
|
|
|
@ -3,13 +3,13 @@ module ArticlesHelper
|
|||
def highlight_new(unequal_attributes, attribute)
|
||||
return unless unequal_attributes
|
||||
|
||||
unequal_attributes.has_key?(attribute) ? "background-color: yellow" : ""
|
||||
unequal_attributes.has_key?(attribute) ? 'background-color: yellow' : ''
|
||||
end
|
||||
|
||||
def row_classes(article)
|
||||
classes = []
|
||||
classes << "unavailable" if !article.availability
|
||||
classes << "just-updated" if article.recently_updated && article.availability
|
||||
classes.join(" ")
|
||||
classes << 'unavailable' unless article.availability
|
||||
classes << 'just-updated' if article.recently_updated && article.availability
|
||||
classes.join(' ')
|
||||
end
|
||||
end
|
||||
|
|
|
@ -11,11 +11,11 @@ module DeliveriesHelper
|
|||
|
||||
def articles_for_select2(articles, except = [], &block)
|
||||
articles = articles.reorder('articles.name ASC')
|
||||
articles = articles.reject { |a| not except.index(a.id).nil? } if except
|
||||
block_given? or block = Proc.new { |a| "#{a.name} (#{number_to_currency a.price}/#{a.unit})" }
|
||||
articles = articles.reject { |a| !except.index(a.id).nil? } if except
|
||||
block_given? or block = proc { |a| "#{a.name} (#{number_to_currency a.price}/#{a.unit})" }
|
||||
articles.map do |a|
|
||||
{ :id => a.id, :text => block.call(a) }
|
||||
end.unshift({ :id => '', :text => '' })
|
||||
{ id: a.id, text: block.call(a) }
|
||||
end.unshift({ id: '', text: '' })
|
||||
end
|
||||
|
||||
def articles_for_table(articles)
|
||||
|
@ -23,10 +23,14 @@ module DeliveriesHelper
|
|||
end
|
||||
|
||||
def stock_change_remove_link(stock_change_form)
|
||||
return link_to t('deliveries.stock_change_fields.remove_article'), "#", :class => 'remove_new_stock_change btn btn-small' if stock_change_form.object.new_record?
|
||||
if stock_change_form.object.new_record?
|
||||
return link_to t('deliveries.stock_change_fields.remove_article'), '#',
|
||||
class: 'remove_new_stock_change btn btn-small'
|
||||
end
|
||||
|
||||
output = stock_change_form.hidden_field :_destroy
|
||||
output += link_to t('deliveries.stock_change_fields.remove_article'), "#", :class => 'destroy_stock_change btn btn-small'
|
||||
return output.html_safe
|
||||
output += link_to t('deliveries.stock_change_fields.remove_article'), '#',
|
||||
class: 'destroy_stock_change btn btn-small'
|
||||
output.html_safe
|
||||
end
|
||||
end
|
||||
|
|
|
@ -2,11 +2,11 @@ module Finance::BalancingHelper
|
|||
def balancing_view_partial
|
||||
view = params[:view] || 'edit_results'
|
||||
case view
|
||||
when 'edit_results' then
|
||||
when 'edit_results'
|
||||
'edit_results_by_articles'
|
||||
when 'groups_overview' then
|
||||
when 'groups_overview'
|
||||
'shared/articles_by/groups'
|
||||
when 'articles_overview' then
|
||||
when 'articles_overview'
|
||||
'shared/articles_by/articles'
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
module Finance::InvoicesHelper
|
||||
def format_delivery_item delivery
|
||||
def format_delivery_item(delivery)
|
||||
format_date(delivery.date)
|
||||
end
|
||||
|
||||
def format_order_item order
|
||||
def format_order_item(order)
|
||||
"#{format_date(order.ends)} (#{number_to_currency(order.sum)})"
|
||||
end
|
||||
end
|
||||
|
|
|
@ -2,12 +2,12 @@ module GroupOrderArticlesHelper
|
|||
# return an edit field for a GroupOrderArticle result
|
||||
def group_order_article_edit_result(goa)
|
||||
result = number_with_precision goa.result, strip_insignificant_zeros: true
|
||||
unless goa.group_order.order.finished? && current_user.role_finance?
|
||||
result
|
||||
else
|
||||
if goa.group_order.order.finished? && current_user.role_finance?
|
||||
simple_form_for goa, remote: true, html: { 'data-submit-onchange' => 'changed', class: 'delta-input' } do |f|
|
||||
f.input_field :result, as: :delta, class: 'input-nano', data: { min: 0 }, id: "r_#{goa.id}", value: result
|
||||
end
|
||||
else
|
||||
result
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
module GroupOrdersHelper
|
||||
def data_to_js(ordering_data)
|
||||
ordering_data[:order_articles].map { |id, data|
|
||||
[id, data[:price], data[:unit], data[:total_price], data[:others_quantity], data[:others_tolerance], data[:used_quantity], data[:quantity_available]]
|
||||
}.map { |row|
|
||||
ordering_data[:order_articles].map do |id, data|
|
||||
[id, data[:price], data[:unit], data[:total_price], data[:others_quantity], data[:others_tolerance],
|
||||
data[:used_quantity], data[:quantity_available]]
|
||||
end.map do |row|
|
||||
"addData(#{row.join(', ')});"
|
||||
}.join("\n")
|
||||
end.join("\n")
|
||||
end
|
||||
|
||||
# Returns a link to the page where a group_order can be edited.
|
||||
|
@ -14,9 +15,9 @@ module GroupOrdersHelper
|
|||
path = if options[:show] && group_order
|
||||
group_order_path(group_order)
|
||||
elsif group_order
|
||||
edit_group_order_path(group_order, :order_id => order.id)
|
||||
edit_group_order_path(group_order, order_id: order.id)
|
||||
else
|
||||
new_group_order_path(:order_id => order.id)
|
||||
new_group_order_path(order_id: order.id)
|
||||
end
|
||||
options.delete(:show)
|
||||
name = block_given? ? capture(&block) : order.name
|
||||
|
@ -26,7 +27,7 @@ module GroupOrdersHelper
|
|||
# Return css class names for order result table
|
||||
|
||||
def order_article_class_name(quantity, tolerance, result)
|
||||
if (quantity + tolerance > 0)
|
||||
if quantity + tolerance > 0
|
||||
result > 0 ? 'success' : 'failed'
|
||||
else
|
||||
'ignored'
|
||||
|
@ -45,12 +46,12 @@ module GroupOrdersHelper
|
|||
end
|
||||
|
||||
def get_missing_units_css_class(quantity_missing)
|
||||
if (quantity_missing == 1)
|
||||
return 'missing-few';
|
||||
elsif (quantity_missing == 0)
|
||||
return ''
|
||||
if quantity_missing == 1
|
||||
'missing-few'
|
||||
elsif quantity_missing == 0
|
||||
''
|
||||
else
|
||||
return 'missing-many'
|
||||
'missing-many'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
module OrderArticlesHelper
|
||||
def article_label_with_unit(article)
|
||||
pkg_info = pkg_helper(article, plain: true)
|
||||
"#{article.name} (#{[article.unit, pkg_info].reject(&:blank?).join(' ')})"
|
||||
"#{article.name} (#{[article.unit, pkg_info].compact_blank.join(' ')})"
|
||||
end
|
||||
end
|
||||
|
|
|
@ -18,7 +18,7 @@ module OrdersHelper
|
|||
|
||||
def options_for_suppliers_to_select
|
||||
options = [[I18n.t('helpers.orders.option_choose')]]
|
||||
options += Supplier.map { |s| [s.name, url_for(action: "new", supplier_id: s.id)] }
|
||||
options += Supplier.map { |s| [s.name, url_for(action: 'new', supplier_id: s.id)] }
|
||||
options += [[I18n.t('helpers.orders.option_stock'), url_for(action: 'new', supplier_id: nil)]]
|
||||
options_for_select(options)
|
||||
end
|
||||
|
@ -29,13 +29,13 @@ module OrdersHelper
|
|||
nil
|
||||
else
|
||||
units_info = []
|
||||
[:units_to_order, :units_billed, :units_received].map do |unit|
|
||||
if n = order_article.send(unit)
|
||||
line = n.to_s + ' '
|
||||
line += pkg_helper(order_article.price, options) + ' ' unless n == 0
|
||||
line += OrderArticle.human_attribute_name("#{unit}_short", count: n)
|
||||
units_info << line
|
||||
end
|
||||
%i[units_to_order units_billed units_received].map do |unit|
|
||||
next unless n = order_article.send(unit)
|
||||
|
||||
line = n.to_s + ' '
|
||||
line += pkg_helper(order_article.price, options) + ' ' unless n == 0
|
||||
line += OrderArticle.human_attribute_name("#{unit}_short", count: n)
|
||||
units_info << line
|
||||
end
|
||||
units_info.join(', ').html_safe
|
||||
end
|
||||
|
@ -67,8 +67,8 @@ module OrdersHelper
|
|||
def pkg_helper_icon(c = nil, options = {})
|
||||
options = { tag: 'i', class: '' }.merge(options)
|
||||
if c.nil?
|
||||
c = " ".html_safe
|
||||
options[:class] += " icon-only"
|
||||
c = ' '.html_safe
|
||||
options[:class] += ' icon-only'
|
||||
end
|
||||
content_tag(options[:tag], c, class: "package #{options[:class]}").html_safe
|
||||
end
|
||||
|
@ -94,11 +94,12 @@ module OrdersHelper
|
|||
autocomplete: 'off'
|
||||
|
||||
if order_article.result_manually_changed?
|
||||
input_html = content_tag(:span, class: 'input-prepend intable', title: t('orders.edit_amount.field_locked_title', default: '')) {
|
||||
input_html = content_tag(:span, class: 'input-prepend intable',
|
||||
title: t('orders.edit_amount.field_locked_title', default: '')) do
|
||||
button_tag(nil, type: :button, class: 'btn unlocker') {
|
||||
content_tag(:i, nil, class: 'icon icon-unlock')
|
||||
} + input_html
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
input_html.html_safe
|
||||
|
@ -109,18 +110,16 @@ module OrdersHelper
|
|||
def ordergroup_count(order)
|
||||
group_orders = order.group_orders.includes(:ordergroup)
|
||||
txt = "#{group_orders.count} #{Ordergroup.model_name.human count: group_orders.count}"
|
||||
if group_orders.count == 0
|
||||
return txt
|
||||
else
|
||||
desc = group_orders.includes(:ordergroup).map { |g| g.ordergroup_name }.join(', ')
|
||||
content_tag(:abbr, txt, title: desc).html_safe
|
||||
end
|
||||
return txt if group_orders.count == 0
|
||||
|
||||
desc = group_orders.includes(:ordergroup).map { |g| g.ordergroup_name }.join(', ')
|
||||
content_tag(:abbr, txt, title: desc).html_safe
|
||||
end
|
||||
|
||||
# @param order_or_supplier [Order, Supplier] Order or supplier to link to
|
||||
# @return [String] Link to order or supplier, showing its name.
|
||||
def supplier_link(order_or_supplier)
|
||||
if order_or_supplier.kind_of?(Order) && order_or_supplier.stockit?
|
||||
if order_or_supplier.is_a?(Order) && order_or_supplier.stockit?
|
||||
link_to(order_or_supplier.name, stock_articles_path).html_safe
|
||||
else
|
||||
link_to(@order.supplier.name, supplier_path(@order.supplier)).html_safe
|
||||
|
@ -152,7 +151,8 @@ module OrdersHelper
|
|||
if order.stockit?
|
||||
content_tag :div, t('orders.index.action_receive'), class: "btn disabled #{options[:class]}"
|
||||
else
|
||||
link_to t('orders.index.action_receive'), receive_order_path(order), class: "btn#{' btn-success' unless order.received?} #{options[:class]}"
|
||||
link_to t('orders.index.action_receive'), receive_order_path(order),
|
||||
class: "btn#{' btn-success' unless order.received?} #{options[:class]}"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
module StockitHelper
|
||||
def stock_article_classes(article)
|
||||
class_names = []
|
||||
class_names << "unavailable" if article.quantity_available <= 0
|
||||
class_names.join(" ")
|
||||
class_names << 'unavailable' if article.quantity_available <= 0
|
||||
class_names.join(' ')
|
||||
end
|
||||
|
||||
def link_to_stock_change_reason(stock_change)
|
||||
|
@ -17,8 +17,8 @@ module StockitHelper
|
|||
|
||||
def stock_article_price_hint(stock_article)
|
||||
t('simple_form.hints.stock_article.edit_stock_article.price',
|
||||
:stock_article_copy_link => link_to(t('stockit.form.copy_stock_article'),
|
||||
stock_article_copy_path(stock_article),
|
||||
:remote => true))
|
||||
stock_article_copy_link: link_to(t('stockit.form.copy_stock_article'),
|
||||
stock_article_copy_path(stock_article),
|
||||
remote: true))
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
module TasksHelper
|
||||
def task_assignments(task)
|
||||
task.assignments.map do |ass|
|
||||
content_tag :span, show_user(ass.user), :class => (ass.accepted? ? 'accepted' : 'unaccepted')
|
||||
end.join(", ").html_safe
|
||||
content_tag :span, show_user(ass.user), class: (ass.accepted? ? 'accepted' : 'unaccepted')
|
||||
end.join(', ').html_safe
|
||||
end
|
||||
|
||||
# generate colored number of still required users
|
||||
def highlighted_required_users(task)
|
||||
unless task.enough_users_assigned?
|
||||
content_tag :span, task.still_required_users, class: 'badge badge-important',
|
||||
title: I18n.t('helpers.tasks.required_users', :count => task.still_required_users)
|
||||
end
|
||||
return if task.enough_users_assigned?
|
||||
|
||||
content_tag :span, task.still_required_users, class: 'badge badge-important',
|
||||
title: I18n.t('helpers.tasks.required_users', count: task.still_required_users)
|
||||
end
|
||||
|
||||
def task_title(task)
|
||||
|
|
|
@ -6,7 +6,7 @@ class DeltaInput < SimpleForm::Inputs::StringInput
|
|||
options[:data] ||= {}
|
||||
options[:data][:delta] ||= 1
|
||||
options[:autocomplete] ||= 'off'
|
||||
# TODO get generated id, don't know how yet - `add_default_name_and_id_for_value` might be an option
|
||||
# TODO: get generated id, don't know how yet - `add_default_name_and_id_for_value` might be an option
|
||||
|
||||
template.content_tag :div, class: 'delta-input input-prepend input-append' do
|
||||
delta_button(content_tag(:i, nil, class: 'icon icon-minus'), -1, options) +
|
||||
|
|
4
app/javascript/application.js
Normal file
4
app/javascript/application.js
Normal file
|
@ -0,0 +1,4 @@
|
|||
// Configure your import map in config/importmap.rb. Read more: https://github.com/rails/importmap-rails
|
||||
import "trix"
|
||||
import "@rails/actiontext"
|
||||
import "trix-editor-overrides"
|
7
app/javascript/trix-editor-overrides.js
Normal file
7
app/javascript/trix-editor-overrides.js
Normal file
|
@ -0,0 +1,7 @@
|
|||
// app/javascript/trix-editor-overrides.js
|
||||
window.addEventListener("trix-file-accept", function(event) {
|
||||
if (event.file.size > 1024 * 1024 * 512) {
|
||||
event.preventDefault()
|
||||
alert(I18n.t('js.trix_editor.file_size_alert'))
|
||||
}
|
||||
})
|
|
@ -14,23 +14,23 @@ class AppleBar
|
|||
def group_bar_state
|
||||
if apples >= 100
|
||||
'success'
|
||||
elsif FoodsoftConfig[:stop_ordering_under].present? &&
|
||||
(apples >= FoodsoftConfig[:stop_ordering_under])
|
||||
'warning'
|
||||
else
|
||||
if FoodsoftConfig[:stop_ordering_under].present? and
|
||||
apples >= FoodsoftConfig[:stop_ordering_under]
|
||||
'warning'
|
||||
else
|
||||
'danger'
|
||||
end
|
||||
'danger'
|
||||
end
|
||||
end
|
||||
|
||||
# Use apples as percentage, but show at least 10 percent
|
||||
def group_bar_width
|
||||
@ordergroup.apples < 2 ? 2 : @ordergroup.apples
|
||||
[@ordergroup.apples, 2].max
|
||||
end
|
||||
|
||||
def mean_order_amount_per_job
|
||||
(1 / @global_avg).round rescue 0
|
||||
(1 / @global_avg).round
|
||||
rescue StandardError
|
||||
0
|
||||
end
|
||||
|
||||
def apples
|
|
@ -1,4 +1,4 @@
|
|||
class ArticlesCsv < RenderCSV
|
||||
class ArticlesCsv < RenderCsv
|
||||
include ApplicationHelper
|
||||
|
||||
def header
|
||||
|
@ -16,14 +16,14 @@ class ArticlesCsv < RenderCSV
|
|||
Article.human_attribute_name(:unit_quantity),
|
||||
'',
|
||||
'',
|
||||
Article.human_attribute_name(:article_category),
|
||||
Article.human_attribute_name(:article_category)
|
||||
]
|
||||
end
|
||||
|
||||
def data
|
||||
@object.each do |o|
|
||||
yield [
|
||||
'',
|
||||
o.availability ? I18n.t('simple_form.yes') : I18n.t('simple_form.no'),
|
||||
o.order_number,
|
||||
o.name,
|
||||
o.note,
|
||||
|
@ -36,7 +36,7 @@ class ArticlesCsv < RenderCSV
|
|||
o.unit_quantity,
|
||||
'',
|
||||
'',
|
||||
o.article_category.try(:name),
|
||||
o.article_category.try(:name)
|
||||
]
|
||||
end
|
||||
end
|
|
@ -8,9 +8,7 @@ class BankAccountConnector
|
|||
nil
|
||||
end
|
||||
|
||||
def text
|
||||
@text
|
||||
end
|
||||
attr_reader :text
|
||||
end
|
||||
|
||||
class TextField
|
||||
|
@ -24,13 +22,7 @@ class BankAccountConnector
|
|||
nil
|
||||
end
|
||||
|
||||
def name
|
||||
@name
|
||||
end
|
||||
|
||||
def value
|
||||
@value
|
||||
end
|
||||
attr_reader :name, :value
|
||||
|
||||
def label
|
||||
@label || @name.to_s
|
||||
|
@ -49,14 +41,14 @@ class BankAccountConnector
|
|||
end
|
||||
end
|
||||
|
||||
@@registered_classes = Set.new
|
||||
@registered_classes = Set.new
|
||||
|
||||
def self.register(klass)
|
||||
@@registered_classes.add klass
|
||||
@registered_classes.add klass
|
||||
end
|
||||
|
||||
def self.find(iban)
|
||||
@@registered_classes.each do |klass|
|
||||
@registered_classes.each do |klass|
|
||||
return klass if klass.handles(iban)
|
||||
end
|
||||
nil
|
||||
|
@ -73,17 +65,7 @@ class BankAccountConnector
|
|||
@bank_account.iban
|
||||
end
|
||||
|
||||
def auto_submit
|
||||
@auto_submit
|
||||
end
|
||||
|
||||
def controls
|
||||
@controls
|
||||
end
|
||||
|
||||
def count
|
||||
@count
|
||||
end
|
||||
attr_reader :auto_submit, :controls, :count
|
||||
|
||||
def text(data)
|
||||
@controls += [TextItem.new(data)]
|
||||
|
@ -142,11 +124,9 @@ class BankAccountConnector
|
|||
@bank_account.save!
|
||||
end
|
||||
|
||||
def load(data)
|
||||
end
|
||||
def load(data); end
|
||||
|
||||
def dump
|
||||
end
|
||||
def dump; end
|
||||
|
||||
def t(key, args = {})
|
||||
return t(".fields.#{key}") unless key.is_a? String
|
|
@ -17,16 +17,16 @@ class BankAccountInformationImporter
|
|||
ret = 0
|
||||
booked.each do |t|
|
||||
amount = parse_account_information_amount t[:transactionAmount]
|
||||
entityName = amount < 0 ? t[:creditorName] : t[:debtorName]
|
||||
entityAccount = amount < 0 ? t[:creditorAccount] : t[:debtorAccount]
|
||||
entity_name = amount < 0 ? t[:creditorName] : t[:debtorName]
|
||||
entity_account = amount < 0 ? t[:creditorAccount] : t[:debtorAccount]
|
||||
reference = [t[:endToEndId], t[:remittanceInformationUnstructured]].join("\n").strip
|
||||
|
||||
@bank_account.bank_transactions.where(external_id: t[:transactionId]).first_or_create.update({
|
||||
date: t[:bookingDate],
|
||||
amount: amount,
|
||||
iban: entityAccount && entityAccount[:iban],
|
||||
iban: entity_account && entity_account[:iban],
|
||||
reference: reference,
|
||||
text: entityName,
|
||||
text: entity_name,
|
||||
receipt: t[:additionalInformation]
|
||||
})
|
||||
ret += 1
|
||||
|
@ -34,7 +34,7 @@ class BankAccountInformationImporter
|
|||
|
||||
balances = (data[:balances] ? data[:balances].map { |b| [b[:balanceType], b[:balanceAmount]] } : []).to_h
|
||||
balance = balances.values.first
|
||||
%w(closingBooked expected authorised openingBooked interimAvailable forwardAvailable nonInvoiced).each do |type|
|
||||
%w[closingBooked expected authorised openingBooked interimAvailable forwardAvailable nonInvoiced].each do |type|
|
||||
value = balances[type]
|
||||
if value
|
||||
balance = value
|
|
@ -1,7 +1,7 @@
|
|||
class BankTransactionReference
|
||||
# parses a string from a bank transaction field
|
||||
def self.parse(data)
|
||||
m = /(^|[^\w\.])FS(?<group>\d+)(\.(?<user>\d+))?(?<parts>([A-Za-z]+\d+(\.\d+)?)+)([^\w\.]|$)/.match(data)
|
||||
m = /(^|[^\w.])FS(?<group>\d+)(\.(?<user>\d+))?(?<parts>([A-Za-z]+\d+(\.\d+)?)+)([^\w.]|$)/.match(data)
|
||||
return unless m
|
||||
|
||||
parts = {}
|
||||
|
@ -13,7 +13,7 @@ class BankTransactionReference
|
|||
|
||||
ret = { group: m[:group].to_i, parts: parts }
|
||||
ret[:user] = m[:user].to_i if m[:user]
|
||||
return ret
|
||||
ret
|
||||
end
|
||||
|
||||
def self.js_code_for_user(user)
|
|
@ -1,6 +1,6 @@
|
|||
require 'csv'
|
||||
|
||||
class BankTransactionsCsv < RenderCSV
|
||||
class BankTransactionsCsv < RenderCsv
|
||||
include ApplicationHelper
|
||||
|
||||
def header
|
80
app/lib/date_time_attribute_validate.rb
Normal file
80
app/lib/date_time_attribute_validate.rb
Normal file
|
@ -0,0 +1,80 @@
|
|||
# workaround for https://github.com/einzige/date_time_attribute/issues/14
|
||||
require 'date_time_attribute'
|
||||
|
||||
module DateTimeAttributeValidate
|
||||
extend ActiveSupport::Concern
|
||||
include DateTimeAttribute
|
||||
|
||||
module ClassMethods
|
||||
def date_time_attribute(*attributes)
|
||||
super
|
||||
|
||||
attributes.each do |attribute|
|
||||
validate -> { send("#{attribute}_datetime_value_valid") }
|
||||
|
||||
# allow resetting the field to nil
|
||||
before_validation do
|
||||
if instance_variable_get("@#{attribute}_is_set")
|
||||
date = instance_variable_get("@#{attribute}_date_value")
|
||||
time = instance_variable_get("@#{attribute}_time_value")
|
||||
send("#{attribute}=", nil) if date.blank? && time.blank?
|
||||
end
|
||||
end
|
||||
|
||||
# remember old date and time values
|
||||
define_method("#{attribute}_date_value=") do |val|
|
||||
instance_variable_set("@#{attribute}_is_set", true)
|
||||
instance_variable_set("@#{attribute}_date_value", val)
|
||||
begin
|
||||
send("#{attribute}_date=", val)
|
||||
rescue StandardError
|
||||
nil
|
||||
end
|
||||
end
|
||||
define_method("#{attribute}_time_value=") do |val|
|
||||
instance_variable_set("@#{attribute}_is_set", true)
|
||||
instance_variable_set("@#{attribute}_time_value", val)
|
||||
begin
|
||||
send("#{attribute}_time=", val)
|
||||
rescue StandardError
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
# fallback to field when values are not set
|
||||
define_method("#{attribute}_date_value") do
|
||||
instance_variable_get("@#{attribute}_date_value") || send("#{attribute}_date").try do |e|
|
||||
e.strftime('%Y-%m-%d')
|
||||
end
|
||||
end
|
||||
define_method("#{attribute}_time_value") do
|
||||
instance_variable_get("@#{attribute}_time_value") || send("#{attribute}_time").try do |e|
|
||||
e.strftime('%H:%M')
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# validate date and time
|
||||
define_method("#{attribute}_datetime_value_valid") do
|
||||
date = instance_variable_get("@#{attribute}_date_value")
|
||||
unless date.blank? || begin
|
||||
Date.parse(date)
|
||||
rescue StandardError
|
||||
nil
|
||||
end
|
||||
errors.add(attribute, 'is not a valid date') # @todo I18n
|
||||
end
|
||||
time = instance_variable_get("@#{attribute}_time_value")
|
||||
unless time.blank? || begin
|
||||
Time.parse(time)
|
||||
rescue StandardError
|
||||
nil
|
||||
end
|
||||
errors.add(attribute, 'is not a valid time') # @todo I18n
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,6 +1,6 @@
|
|||
require 'csv'
|
||||
|
||||
class FinancialTransactionsCsv < RenderCSV
|
||||
class FinancialTransactionsCsv < RenderCsv
|
||||
include ApplicationHelper
|
||||
|
||||
def header
|
|
@ -14,7 +14,7 @@ module Foodsoft
|
|||
cattr_accessor :variables
|
||||
|
||||
# Hash of variables. Note that keys are Strings.
|
||||
@@variables = {
|
||||
@variables = {
|
||||
'scope' => -> { FoodsoftConfig.scope },
|
||||
'name' => -> { FoodsoftConfig[:name] },
|
||||
'contact.street' => -> { FoodsoftConfig[:contact][:street] },
|
||||
|
@ -39,13 +39,13 @@ module Foodsoft
|
|||
'supplier_count' => -> { Supplier.undeleted.count },
|
||||
'active_supplier_count' => -> { active_supplier_count },
|
||||
'active_suppliers' => -> { active_suppliers },
|
||||
'first_order_date' => -> { I18n.l Order.first.try { |o| o.starts.to_date } }
|
||||
'first_order_date' => -> { I18n.l(Order.first.try { |o| o.starts.to_date }) }
|
||||
}
|
||||
|
||||
# Return expanded variable
|
||||
# @return [String] Expanded variable
|
||||
def self.get(var)
|
||||
s = @@variables[var.to_s]
|
||||
s = @variables[var.to_s]
|
||||
s.respond_to?(:call) ? s.call : s.to_s
|
||||
end
|
||||
|
||||
|
@ -54,8 +54,8 @@ module Foodsoft
|
|||
# @param options [Hash<String, String>] Extra variables to expand
|
||||
# @return [String] Expanded string
|
||||
def self.expand(str, options = {})
|
||||
str.gsub /{{([._a-zA-Z0-9]+)}}/ do
|
||||
options[$1] || self.get($1)
|
||||
str.gsub(/{{([._a-zA-Z0-9]+)}}/) do
|
||||
options[::Regexp.last_match(1)] || get(::Regexp.last_match(1))
|
||||
end
|
||||
end
|
||||
|
|
@ -44,6 +44,8 @@ class FoodsoftConfig
|
|||
# @return [ActiveSupport::HashWithIndifferentAccess] Current configuration from configuration file.
|
||||
mattr_accessor :config
|
||||
|
||||
mattr_accessor :default_config
|
||||
|
||||
# Configuration file location.
|
||||
# Taken from environment variable +FOODSOFT_APP_CONFIG+,
|
||||
# or else +config/app_config.yml+.
|
||||
|
@ -68,7 +70,7 @@ class FoodsoftConfig
|
|||
# Load initial config from development or production
|
||||
set_config Rails.env
|
||||
# Overwrite scope to have a better namescope than 'production'
|
||||
self.scope = config[:default_scope] or raise "No default_scope is set"
|
||||
self.scope = config[:default_scope] or raise 'No default_scope is set'
|
||||
# Set defaults for backward-compatibility
|
||||
set_missing
|
||||
# Make sure relevant configuration is applied, also in single coops mode,
|
||||
|
@ -77,7 +79,7 @@ class FoodsoftConfig
|
|||
end
|
||||
|
||||
def init_mailing
|
||||
[:protocol, :host, :port, :script_name].each do |k|
|
||||
%i[protocol host port script_name].each do |k|
|
||||
ActionMailer::Base.default_url_options[k] = self[k] if self[k]
|
||||
end
|
||||
end
|
||||
|
@ -115,7 +117,7 @@ class FoodsoftConfig
|
|||
# @return [Object] Value of the key.
|
||||
def [](key)
|
||||
if RailsSettings::CachedSettings.table_exists? && allowed_key?(key)
|
||||
value = RailsSettings::CachedSettings["foodcoop.#{self.scope}.#{key}"]
|
||||
value = RailsSettings::CachedSettings["foodcoop.#{scope}.#{key}"]
|
||||
value = config[key] if value.nil?
|
||||
value
|
||||
else
|
||||
|
@ -137,20 +139,20 @@ class FoodsoftConfig
|
|||
if config[key] == value || (config[key].nil? && value == false)
|
||||
# delete (ok if it was already deleted)
|
||||
begin
|
||||
RailsSettings::CachedSettings.destroy "foodcoop.#{self.scope}.#{key}"
|
||||
RailsSettings::CachedSettings.destroy "foodcoop.#{scope}.#{key}"
|
||||
rescue RailsSettings::Settings::SettingNotFound
|
||||
end
|
||||
else
|
||||
# or store
|
||||
RailsSettings::CachedSettings["foodcoop.#{self.scope}.#{key}"] = value
|
||||
RailsSettings::CachedSettings["foodcoop.#{scope}.#{key}"] = value
|
||||
end
|
||||
true
|
||||
end
|
||||
|
||||
# @return [Array<String>] Configuration keys that are set (either in +app_config.yml+ or database).
|
||||
def keys
|
||||
keys = RailsSettings::CachedSettings.get_all("foodcoop.#{self.scope}.").try(:keys) || []
|
||||
keys.map! { |k| k.gsub(/^foodcoop\.#{self.scope}\./, '') }
|
||||
keys = RailsSettings::CachedSettings.get_all("foodcoop.#{scope}.").try(:keys) || []
|
||||
keys.map! { |k| k.gsub(/^foodcoop\.#{scope}\./, '') }
|
||||
keys += config.keys
|
||||
keys.map(&:to_s).uniq
|
||||
end
|
||||
|
@ -179,17 +181,17 @@ class FoodsoftConfig
|
|||
# @return [Boolean] Whether this key may be set in the database
|
||||
def allowed_key?(key)
|
||||
# fast check for keys without nesting
|
||||
if self.config[:protected].include? key
|
||||
!self.config[:protected][key]
|
||||
if config[:protected].include? key
|
||||
!config[:protected][key]
|
||||
else
|
||||
!self.config[:protected][:all]
|
||||
!config[:protected][:all]
|
||||
end
|
||||
# @todo allow to check nested keys as well
|
||||
end
|
||||
|
||||
# @return [Hash] Full configuration.
|
||||
def to_hash
|
||||
keys.to_h { |k| [k, self[k]] }
|
||||
keys.index_with { |k| self[k] }
|
||||
end
|
||||
|
||||
# for using active_model_serializer in the api/v1/configs controller
|
||||
|
@ -216,7 +218,6 @@ class FoodsoftConfig
|
|||
# end
|
||||
#
|
||||
# @return [Hash] Default configuration values
|
||||
mattr_accessor :default_config
|
||||
|
||||
private
|
||||
|
||||
|
@ -229,7 +230,7 @@ class FoodsoftConfig
|
|||
end
|
||||
|
||||
def setup_database
|
||||
database_config = ActiveRecord::Base.configurations[Rails.env]
|
||||
database_config = ActiveRecord::Base.configurations.find_db_config(Rails.env).configuration_hash
|
||||
database_config = database_config.merge(config[:database]) if config[:database].present?
|
||||
ActiveRecord::Base.establish_connection(database_config)
|
||||
end
|
||||
|
@ -286,7 +287,9 @@ class FoodsoftConfig
|
|||
def normalize_value(value)
|
||||
value = value.map { |v| normalize_value(v) } if value.is_a? Array
|
||||
if value.is_a? Hash
|
||||
value = ActiveSupport::HashWithIndifferentAccess[value.to_a.map { |a| [a[0], normalize_value(a[1])] }]
|
||||
value = ActiveSupport::HashWithIndifferentAccess[value.to_a.map do |a|
|
||||
[a[0], normalize_value(a[1])]
|
||||
end]
|
||||
end
|
||||
case value
|
||||
when 'true' then true
|
31
app/lib/foodsoft_date_util.rb
Normal file
31
app/lib/foodsoft_date_util.rb
Normal file
|
@ -0,0 +1,31 @@
|
|||
module FoodsoftDateUtil
|
||||
# find next occurence given a recurring ical string and time
|
||||
def self.next_occurrence(start = Time.now, from = start, options = {})
|
||||
occ = nil
|
||||
if options && options[:recurr]
|
||||
schedule = IceCube::Schedule.new(start)
|
||||
schedule.add_recurrence_rule rule_from(options[:recurr])
|
||||
# @todo handle ical parse errors
|
||||
occ = begin
|
||||
schedule.next_occurrence(from).to_time
|
||||
rescue StandardError
|
||||
nil
|
||||
end
|
||||
end
|
||||
occ = occ.beginning_of_day.advance(seconds: Time.parse(options[:time]).seconds_since_midnight) if options && options[:time] && occ
|
||||
occ
|
||||
end
|
||||
|
||||
# @param rule [String, Symbol, Hash, IceCube::Rule] What to return a rule from.
|
||||
# @return [IceCube::Rule] Recurring rule
|
||||
def self.rule_from(rule)
|
||||
case rule
|
||||
when String
|
||||
IceCube::Rule.from_ical(rule)
|
||||
when Hash
|
||||
IceCube::Rule.from_hash(rule)
|
||||
else
|
||||
rule
|
||||
end
|
||||
end
|
||||
end
|
25
app/lib/foodsoft_file.rb
Normal file
25
app/lib/foodsoft_file.rb
Normal file
|
@ -0,0 +1,25 @@
|
|||
# Foodsoft-file import
|
||||
class FoodsoftFile
|
||||
# parses a string from a foodsoft-file
|
||||
# returns two arrays with articles and outlisted_articles
|
||||
# the parsed article is a simple hash
|
||||
def self.parse(file, options = {})
|
||||
SpreadsheetFile.parse file, options do |row, row_index|
|
||||
next if row[2].blank?
|
||||
|
||||
article = { order_number: row[1],
|
||||
name: row[2],
|
||||
note: row[3],
|
||||
manufacturer: row[4],
|
||||
origin: row[5],
|
||||
unit: row[6],
|
||||
price: row[7],
|
||||
tax: row[8],
|
||||
deposit: (row[9].nil? ? '0' : row[9]),
|
||||
unit_quantity: row[10],
|
||||
article_category: row[13] }
|
||||
status = row[0] && row[0].strip.downcase == 'x' ? :outlisted : nil
|
||||
yield status, article, row_index
|
||||
end
|
||||
end
|
||||
end
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue