Compare commits
81 commits
demo
...
automatic_
Author | SHA1 | Date | |
---|---|---|---|
fd769509af | |||
caa5adbfe2 | |||
fc46281de8 | |||
24c25b5278 | |||
bdeee02873 | |||
bcc647dabb | |||
219b5f2de8 | |||
f98d083647 | |||
636aad0b3e | |||
06aa20ad0f | |||
90c5450525 | |||
de6643722a | |||
505cf8c2f3 | |||
f979face11 | |||
c3d56cdf3b | |||
90e06a475f | |||
f29ab603b6 | |||
|
93143c28f2 | ||
|
6abf998b56 | ||
|
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 |
492 changed files with 11924 additions and 7179 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_DATABASE: test
|
||||||
MYSQL_ROOT_PASSWORD: password
|
MYSQL_ROOT_PASSWORD: password
|
||||||
options: >-
|
options: >-
|
||||||
--health-cmd "mysqladmin ping"
|
--health-cmd "mariadb-admin ping"
|
||||||
--health-interval 10s
|
--health-interval 10s
|
||||||
--health-timeout 5s
|
--health-timeout 5s
|
||||||
--health-retries 5
|
--health-retries 5
|
||||||
|
@ -35,7 +35,9 @@ jobs:
|
||||||
- name: Checkout source code
|
- name: Checkout source code
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2
|
||||||
- name: Setup chromedriver
|
- 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
|
- name: Setup ruby
|
||||||
uses: ruby/setup-ruby@v1
|
uses: ruby/setup-ruby@v1
|
||||||
with:
|
with:
|
||||||
|
|
1814
.rubocop_todo.yml
1814
.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
|
# Foodsoft 4.7.1
|
||||||
(31 December 2020)
|
(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 && \
|
RUN supercronicUrl=https://github.com/aptible/supercronic/releases/download/v0.1.3/supercronic-linux-amd64 && \
|
||||||
supercronicBin=/usr/local/bin/supercronic && \
|
supercronicBin=/usr/local/bin/supercronic && \
|
||||||
|
@ -22,6 +22,7 @@ RUN buildDeps='libmagic-dev' && \
|
||||||
apt-get update && \
|
apt-get update && \
|
||||||
apt-get install --no-install-recommends -y $buildDeps && \
|
apt-get install --no-install-recommends -y $buildDeps && \
|
||||||
echo 'gem: --no-document' >> ~/.gemrc && \
|
echo 'gem: --no-document' >> ~/.gemrc && \
|
||||||
|
gem install bundler -v 2.4.22 && \
|
||||||
bundle config build.nokogiri "--use-system-libraries" && \
|
bundle config build.nokogiri "--use-system-libraries" && \
|
||||||
bundle install --deployment --without development test -j 4 && \
|
bundle install --deployment --without development test -j 4 && \
|
||||||
apt-get purge -y --auto-remove $buildDeps && \
|
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/*
|
rm -Rf /var/lib/apt/lists/* /var/cache/apt/*
|
||||||
|
|
||||||
# Make relevant dirs and files writable for app user
|
# 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 config/app_config.yml && \
|
||||||
chown nobody tmp
|
chown nobody tmp && \
|
||||||
|
chown nobody storage
|
||||||
|
|
||||||
# Run app as unprivileged user
|
# Run app as unprivileged user
|
||||||
USER nobody
|
USER nobody
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
FROM ruby:2.6
|
FROM ruby:2.7
|
||||||
|
|
||||||
# Install dependencies
|
# Install dependencies
|
||||||
RUN deps='libmagic-dev chromium nodejs' && \
|
RUN deps='libmagic-dev chromium nodejs' && \
|
||||||
|
@ -19,6 +19,7 @@ ENV PORT=3000 \
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
|
RUN gem install bundler
|
||||||
RUN bundle config build.nokogiri "--use-system-libraries"
|
RUN bundle config build.nokogiri "--use-system-libraries"
|
||||||
|
|
||||||
EXPOSE 3000
|
EXPOSE 3000
|
||||||
|
|
105
Gemfile
105
Gemfile
|
@ -1,69 +1,76 @@
|
||||||
# A sample Gemfile
|
# 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 'less-rails'
|
||||||
gem 'uglifier', '>= 1.0.3'
|
gem 'sassc-rails'
|
||||||
# See https://github.com/sstephenson/execjs#readme for more supported runtimes
|
# See https://github.com/sstephenson/execjs#readme for more supported runtimes
|
||||||
gem 'therubyracer', platforms: :ruby
|
gem 'therubyracer', platforms: :ruby
|
||||||
|
|
||||||
gem 'jquery-rails'
|
gem 'bootsnap', require: false
|
||||||
gem 'select2-rails'
|
|
||||||
gem 'rails_tokeninput'
|
|
||||||
gem 'bootstrap-datepicker-rails'
|
gem 'bootstrap-datepicker-rails'
|
||||||
gem 'date_time_attribute'
|
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 '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 'rails-i18n'
|
||||||
gem 'bootsnap', require: false
|
gem 'rails_tokeninput'
|
||||||
|
gem 'select2-rails'
|
||||||
|
|
||||||
gem 'mysql2'
|
gem 'active_model_serializers', '~> 0.10.0'
|
||||||
gem 'prawn'
|
gem 'acts_as_tree'
|
||||||
gem 'prawn-table'
|
gem 'attribute_normalizer'
|
||||||
gem 'haml'
|
|
||||||
gem 'haml-rails'
|
|
||||||
gem 'kaminari'
|
|
||||||
gem 'simple_form'
|
|
||||||
gem 'inherited_resources'
|
|
||||||
gem 'daemons'
|
gem 'daemons'
|
||||||
gem 'doorkeeper'
|
gem 'doorkeeper'
|
||||||
gem 'doorkeeper-i18n'
|
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 'rack-cors', require: 'rack/cors'
|
||||||
gem 'active_model_serializers', '~> 0.10.0'
|
gem 'rails-settings-cached', '= 0.4.3' # caching breaks tests until Rails 5 https://github.com/huacnlee/rails-settings-cached/issues/73
|
||||||
gem 'twitter-bootstrap-rails', '~> 2.2.8'
|
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', '~> 3.14.0' # 3.x for simple_navigation_bootstrap
|
||||||
gem 'simple-navigation-bootstrap'
|
gem 'simple-navigation-bootstrap'
|
||||||
gem 'sprockets', '< 4'
|
gem 'sprockets', '< 4'
|
||||||
gem 'ransack'
|
gem 'twitter-bootstrap-rails', '~> 2.2.8'
|
||||||
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 'whenever', require: false # For defining cronjobs, see config/schedule.rb
|
gem 'whenever', require: false # For defining cronjobs, see config/schedule.rb
|
||||||
gem 'ruby-units'
|
# 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 'attribute_normalizer'
|
|
||||||
gem 'ice_cube'
|
|
||||||
gem 'recurring_select'
|
|
||||||
gem 'roo'
|
|
||||||
gem 'roo-xls'
|
|
||||||
gem 'spreadsheet'
|
|
||||||
gem 'exception_notification'
|
gem 'exception_notification'
|
||||||
gem 'gaffe'
|
gem 'gaffe'
|
||||||
gem 'ruby-filemagic'
|
gem 'hashie', '~> 3.4.6', require: false # https://github.com/westfieldlabs/apivore/issues/114
|
||||||
gem 'mime-types'
|
gem "image_processing", "~> 1.12"
|
||||||
|
gem "importmap-rails", "~> 1.1"
|
||||||
gem 'midi-smtp-server'
|
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 'sepa_king'
|
||||||
|
gem "terser", "~> 1.1"
|
||||||
|
|
||||||
# we use the git version of acts_as_versioned, and need to include it in this Gemfile
|
# 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 '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_discourse', path: 'plugins/discourse'
|
||||||
|
gem 'foodsoft_documents', path: 'plugins/documents'
|
||||||
gem 'foodsoft_links', path: 'plugins/links'
|
gem 'foodsoft_links', path: 'plugins/links'
|
||||||
|
gem 'foodsoft_messages', path: 'plugins/messages'
|
||||||
gem 'foodsoft_polls', path: 'plugins/polls'
|
gem 'foodsoft_polls', path: 'plugins/polls'
|
||||||
|
gem 'foodsoft_wiki', path: 'plugins/wiki'
|
||||||
|
|
||||||
# plugins not enabled by default
|
# plugins not enabled by default
|
||||||
# gem 'foodsoft_current_orders', path: 'plugins/current_orders'
|
# gem 'foodsoft_current_orders', path: 'plugins/current_orders'
|
||||||
|
@ -71,17 +78,18 @@ gem 'foodsoft_polls', path: 'plugins/polls'
|
||||||
# gem 'foodsoft_uservoice', path: 'plugins/uservoice'
|
# gem 'foodsoft_uservoice', path: 'plugins/uservoice'
|
||||||
|
|
||||||
group :development do
|
group :development do
|
||||||
gem 'sqlite3', '~> 1.3.6'
|
|
||||||
gem 'mailcatcher'
|
|
||||||
gem 'web-console'
|
|
||||||
gem 'listen'
|
gem 'listen'
|
||||||
|
gem 'mailcatcher'
|
||||||
|
gem 'sqlite3', '~> 1.3.6'
|
||||||
|
gem 'web-console'
|
||||||
|
|
||||||
# Better error output
|
# Better error output
|
||||||
gem 'better_errors'
|
gem 'better_errors'
|
||||||
gem 'binding_of_caller'
|
gem 'binding_of_caller'
|
||||||
# gem "rails-i18n-debug"
|
# gem "rails-i18n-debug"
|
||||||
# chrome debugging extension https://github.com/dejan/rails_panel
|
# 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
|
# Get infos when not using proper eager loading
|
||||||
gem 'bullet'
|
gem 'bullet'
|
||||||
|
@ -101,21 +109,20 @@ group :development, :test do
|
||||||
end
|
end
|
||||||
|
|
||||||
group :test do
|
group :test do
|
||||||
gem 'rspec-rails'
|
gem 'apparition' # Capybara javascript driver
|
||||||
|
gem 'capybara'
|
||||||
|
gem 'connection_pool'
|
||||||
|
gem 'database_cleaner'
|
||||||
gem 'factory_bot_rails'
|
gem 'factory_bot_rails'
|
||||||
gem 'faker'
|
gem 'faker'
|
||||||
gem 'capybara'
|
gem 'rspec-rails'
|
||||||
gem 'apparition' # Capybara javascript driver
|
|
||||||
gem 'database_cleaner'
|
|
||||||
gem 'connection_pool'
|
|
||||||
# need to include rspec components before i18n-spec or rake fails in test environment
|
# need to include rspec components before i18n-spec or rake fails in test environment
|
||||||
|
gem 'i18n-spec'
|
||||||
gem 'rspec-core'
|
gem 'rspec-core'
|
||||||
gem 'rspec-rerun'
|
gem 'rspec-rerun'
|
||||||
gem 'i18n-spec'
|
|
||||||
# code coverage
|
# code coverage
|
||||||
gem 'simplecov', require: false
|
gem 'simplecov', require: false
|
||||||
gem 'simplecov-lcov', require: false
|
gem 'simplecov-lcov', require: false
|
||||||
# api
|
# api
|
||||||
gem 'apivore', require: false
|
gem 'rswag-specs'
|
||||||
gem 'hashie', '~> 3.4.6', require: false # https://github.com/westfieldlabs/apivore/issues/114
|
|
||||||
end
|
end
|
||||||
|
|
402
Gemfile.lock
402
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
|
GIT
|
||||||
remote: https://github.com/technoweenie/acts_as_versioned.git
|
remote: https://github.com/technoweenie/acts_as_versioned.git
|
||||||
revision: 63b1fc8529d028fae632fe80ec0cb25df56cd76b
|
revision: 63b1fc8529d028fae632fe80ec0cb25df56cd76b
|
||||||
|
@ -59,67 +70,83 @@ PATH
|
||||||
GEM
|
GEM
|
||||||
remote: https://rubygems.org/
|
remote: https://rubygems.org/
|
||||||
specs:
|
specs:
|
||||||
actioncable (5.2.8.1)
|
actioncable (7.0.4)
|
||||||
actionpack (= 5.2.8.1)
|
actionpack (= 7.0.4)
|
||||||
|
activesupport (= 7.0.4)
|
||||||
nio4r (~> 2.0)
|
nio4r (~> 2.0)
|
||||||
websocket-driver (>= 0.6.1)
|
websocket-driver (>= 0.6.1)
|
||||||
actionmailer (5.2.8.1)
|
actionmailbox (7.0.4)
|
||||||
actionpack (= 5.2.8.1)
|
actionpack (= 7.0.4)
|
||||||
actionview (= 5.2.8.1)
|
activejob (= 7.0.4)
|
||||||
activejob (= 5.2.8.1)
|
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)
|
mail (~> 2.5, >= 2.5.4)
|
||||||
|
net-imap
|
||||||
|
net-pop
|
||||||
|
net-smtp
|
||||||
rails-dom-testing (~> 2.0)
|
rails-dom-testing (~> 2.0)
|
||||||
actionpack (5.2.8.1)
|
actionpack (7.0.4)
|
||||||
actionview (= 5.2.8.1)
|
actionview (= 7.0.4)
|
||||||
activesupport (= 5.2.8.1)
|
activesupport (= 7.0.4)
|
||||||
rack (~> 2.0, >= 2.0.8)
|
rack (~> 2.0, >= 2.2.0)
|
||||||
rack-test (>= 0.6.3)
|
rack-test (>= 0.6.3)
|
||||||
rails-dom-testing (~> 2.0)
|
rails-dom-testing (~> 2.0)
|
||||||
rails-html-sanitizer (~> 1.0, >= 1.0.2)
|
rails-html-sanitizer (~> 1.0, >= 1.2.0)
|
||||||
actionview (5.2.8.1)
|
actiontext (7.0.4)
|
||||||
activesupport (= 5.2.8.1)
|
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)
|
builder (~> 3.1)
|
||||||
erubi (~> 1.4)
|
erubi (~> 1.4)
|
||||||
rails-dom-testing (~> 2.0)
|
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)
|
active_model_serializers (0.10.13)
|
||||||
actionpack (>= 4.1, < 7.1)
|
actionpack (>= 4.1, < 7.1)
|
||||||
activemodel (>= 4.1, < 7.1)
|
activemodel (>= 4.1, < 7.1)
|
||||||
case_transform (>= 0.2)
|
case_transform (>= 0.2)
|
||||||
jsonapi-renderer (>= 0.1.1.beta1, < 0.3)
|
jsonapi-renderer (>= 0.1.1.beta1, < 0.3)
|
||||||
activejob (5.2.8.1)
|
activejob (7.0.4)
|
||||||
activesupport (= 5.2.8.1)
|
activesupport (= 7.0.4)
|
||||||
globalid (>= 0.3.6)
|
globalid (>= 0.3.6)
|
||||||
activemodel (5.2.8.1)
|
activemodel (7.0.4)
|
||||||
activesupport (= 5.2.8.1)
|
activesupport (= 7.0.4)
|
||||||
activerecord (5.2.8.1)
|
activerecord (7.0.4)
|
||||||
activemodel (= 5.2.8.1)
|
activemodel (= 7.0.4)
|
||||||
activesupport (= 5.2.8.1)
|
activesupport (= 7.0.4)
|
||||||
arel (>= 9.0)
|
activestorage (7.0.4)
|
||||||
activestorage (5.2.8.1)
|
actionpack (= 7.0.4)
|
||||||
actionpack (= 5.2.8.1)
|
activejob (= 7.0.4)
|
||||||
activerecord (= 5.2.8.1)
|
activerecord (= 7.0.4)
|
||||||
marcel (~> 1.0.0)
|
activesupport (= 7.0.4)
|
||||||
activesupport (5.2.8.1)
|
marcel (~> 1.0)
|
||||||
|
mini_mime (>= 1.1.0)
|
||||||
|
activesupport (7.0.4)
|
||||||
concurrent-ruby (~> 1.0, >= 1.0.2)
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
||||||
i18n (>= 0.7, < 2)
|
i18n (>= 1.6, < 2)
|
||||||
minitest (~> 5.1)
|
minitest (>= 5.1)
|
||||||
tzinfo (~> 1.1)
|
tzinfo (~> 2.0)
|
||||||
acts_as_tree (2.9.1)
|
acts_as_tree (2.9.1)
|
||||||
activerecord (>= 3.0.0)
|
activerecord (>= 3.0.0)
|
||||||
addressable (2.8.1)
|
addressable (2.8.1)
|
||||||
public_suffix (>= 2.0.2, < 6.0)
|
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)
|
apparition (0.6.0)
|
||||||
capybara (~> 3.13, < 4)
|
capybara (~> 3.13, < 4)
|
||||||
websocket-driver (>= 0.6.5)
|
websocket-driver (>= 0.6.5)
|
||||||
arel (9.0.0)
|
|
||||||
ast (2.4.2)
|
ast (2.4.2)
|
||||||
attribute_normalizer (1.2.0)
|
attribute_normalizer (1.2.0)
|
||||||
base32 (0.3.4)
|
base32 (0.3.4)
|
||||||
|
@ -130,15 +157,15 @@ GEM
|
||||||
bindex (0.8.1)
|
bindex (0.8.1)
|
||||||
binding_of_caller (1.0.0)
|
binding_of_caller (1.0.0)
|
||||||
debug_inspector (>= 0.0.1)
|
debug_inspector (>= 0.0.1)
|
||||||
bootsnap (1.13.0)
|
bootsnap (1.15.0)
|
||||||
msgpack (~> 1.2)
|
msgpack (~> 1.2)
|
||||||
bootstrap-datepicker-rails (1.9.0.1)
|
bootstrap-datepicker-rails (1.9.0.1)
|
||||||
railties (>= 3.0)
|
railties (>= 3.0)
|
||||||
builder (3.2.4)
|
builder (3.2.4)
|
||||||
bullet (7.0.3)
|
bullet (7.0.7)
|
||||||
activesupport (>= 3.0.0)
|
activesupport (>= 3.0.0)
|
||||||
uniform_notifier (~> 1.11)
|
uniform_notifier (~> 1.11)
|
||||||
capybara (3.36.0)
|
capybara (3.38.0)
|
||||||
addressable
|
addressable
|
||||||
matrix
|
matrix
|
||||||
mini_mime (>= 0.1.3)
|
mini_mime (>= 0.1.3)
|
||||||
|
@ -159,7 +186,7 @@ GEM
|
||||||
execjs
|
execjs
|
||||||
coffee-script-source (1.12.2)
|
coffee-script-source (1.12.2)
|
||||||
commonjs (0.2.7)
|
commonjs (0.2.7)
|
||||||
concurrent-ruby (1.1.10)
|
concurrent-ruby (1.2.2)
|
||||||
connection_pool (2.3.0)
|
connection_pool (2.3.0)
|
||||||
content_for_in_controllers (0.0.2)
|
content_for_in_controllers (0.0.2)
|
||||||
crass (1.0.6)
|
crass (1.0.6)
|
||||||
|
@ -170,6 +197,7 @@ GEM
|
||||||
activerecord (>= 5.a)
|
activerecord (>= 5.a)
|
||||||
database_cleaner-core (~> 2.0.0)
|
database_cleaner-core (~> 2.0.0)
|
||||||
database_cleaner-core (2.0.1)
|
database_cleaner-core (2.0.1)
|
||||||
|
date (3.3.3)
|
||||||
date_time_attribute (0.1.2)
|
date_time_attribute (0.1.2)
|
||||||
activesupport (>= 3.0.0)
|
activesupport (>= 3.0.0)
|
||||||
debug_inspector (1.1.0)
|
debug_inspector (1.1.0)
|
||||||
|
@ -182,13 +210,13 @@ GEM
|
||||||
diff-lcs (1.5.0)
|
diff-lcs (1.5.0)
|
||||||
diffy (3.4.2)
|
diffy (3.4.2)
|
||||||
docile (1.4.0)
|
docile (1.4.0)
|
||||||
doorkeeper (5.6.0)
|
doorkeeper (5.6.6)
|
||||||
railties (>= 5)
|
railties (>= 5)
|
||||||
doorkeeper-i18n (5.2.5)
|
doorkeeper-i18n (5.2.6)
|
||||||
doorkeeper (>= 5.2)
|
doorkeeper (>= 5.2)
|
||||||
email_reply_trimmer (0.1.13)
|
email_reply_trimmer (0.1.13)
|
||||||
erubi (1.11.0)
|
erubi (1.12.0)
|
||||||
eventmachine (1.2.7)
|
eventmachine (1.0.9.1)
|
||||||
exception_notification (4.5.0)
|
exception_notification (4.5.0)
|
||||||
actionmailer (>= 5.2, < 8)
|
actionmailer (>= 5.2, < 8)
|
||||||
activesupport (>= 5.2, < 8)
|
activesupport (>= 5.2, < 8)
|
||||||
|
@ -199,16 +227,15 @@ GEM
|
||||||
factory_bot_rails (6.2.0)
|
factory_bot_rails (6.2.0)
|
||||||
factory_bot (~> 6.2.0)
|
factory_bot (~> 6.2.0)
|
||||||
railties (>= 5.0.0)
|
railties (>= 5.0.0)
|
||||||
faker (2.22.0)
|
faker (3.1.0)
|
||||||
i18n (>= 1.8.11, < 2)
|
i18n (>= 1.8.11, < 2)
|
||||||
ffi (1.15.5)
|
ffi (1.15.5)
|
||||||
gaffe (1.2.0)
|
gaffe (1.2.0)
|
||||||
rails (>= 4.0.0)
|
rails (>= 4.0.0)
|
||||||
globalid (1.0.0)
|
globalid (1.0.1)
|
||||||
activesupport (>= 5.0)
|
activesupport (>= 5.0)
|
||||||
haml (6.0.5)
|
haml (5.2.2)
|
||||||
temple (>= 0.8.2)
|
temple (>= 0.8.0)
|
||||||
thor
|
|
||||||
tilt
|
tilt
|
||||||
haml-rails (2.1.0)
|
haml-rails (2.1.0)
|
||||||
actionpack (>= 5.1)
|
actionpack (>= 5.1)
|
||||||
|
@ -220,13 +247,20 @@ GEM
|
||||||
activesupport (>= 5.2)
|
activesupport (>= 5.2)
|
||||||
hashie (3.4.6)
|
hashie (3.4.6)
|
||||||
htmlentities (4.3.4)
|
htmlentities (4.3.4)
|
||||||
i18n (1.12.0)
|
i18n (1.14.1)
|
||||||
concurrent-ruby (~> 1.0)
|
concurrent-ruby (~> 1.0)
|
||||||
i18n-js (3.0.11)
|
i18n-js (3.0.11)
|
||||||
i18n (>= 0.6.6, < 2)
|
i18n (>= 0.6.6, < 2)
|
||||||
i18n-spec (0.6.0)
|
i18n-spec (0.6.0)
|
||||||
iso
|
iso
|
||||||
|
iban-tools (1.1.0)
|
||||||
ice_cube (0.16.4)
|
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)
|
inherited_resources (1.13.1)
|
||||||
actionpack (>= 5.2, < 7.1)
|
actionpack (>= 5.2, < 7.1)
|
||||||
has_scope (~> 0.6)
|
has_scope (~> 0.6)
|
||||||
|
@ -235,13 +269,13 @@ GEM
|
||||||
interception (0.5)
|
interception (0.5)
|
||||||
iso (0.4.0)
|
iso (0.4.0)
|
||||||
i18n
|
i18n
|
||||||
jquery-rails (4.5.0)
|
jquery-rails (4.5.1)
|
||||||
rails-dom-testing (>= 1, < 3)
|
rails-dom-testing (>= 1, < 3)
|
||||||
railties (>= 4.2.0)
|
railties (>= 4.2.0)
|
||||||
thor (>= 0.14, < 2.0)
|
thor (>= 0.14, < 2.0)
|
||||||
json (2.6.2)
|
json (2.6.3)
|
||||||
json-schema (2.8.1)
|
json-schema (3.0.0)
|
||||||
addressable (>= 2.4)
|
addressable (>= 2.8)
|
||||||
jsonapi-renderer (0.2.2)
|
jsonapi-renderer (0.2.2)
|
||||||
kaminari (1.2.2)
|
kaminari (1.2.2)
|
||||||
activesupport (>= 4.1.0)
|
activesupport (>= 4.1.0)
|
||||||
|
@ -261,15 +295,18 @@ GEM
|
||||||
actionpack (>= 5.0)
|
actionpack (>= 5.0)
|
||||||
less (~> 2.6.0)
|
less (~> 2.6.0)
|
||||||
sprockets (~> 3.0)
|
sprockets (~> 3.0)
|
||||||
libv8 (3.16.14.19)
|
libv8 (3.16.14.19-x86_64-linux)
|
||||||
listen (3.7.1)
|
listen (3.7.1)
|
||||||
rb-fsevent (~> 0.10, >= 0.10.3)
|
rb-fsevent (~> 0.10, >= 0.10.3)
|
||||||
rb-inotify (~> 0.9, >= 0.9.10)
|
rb-inotify (~> 0.9, >= 0.9.10)
|
||||||
loofah (2.19.1)
|
loofah (2.21.3)
|
||||||
crass (~> 1.0.2)
|
crass (~> 1.0.2)
|
||||||
nokogiri (>= 1.5.9)
|
nokogiri (>= 1.12.0)
|
||||||
mail (2.7.1)
|
mail (2.8.1)
|
||||||
mini_mime (>= 0.1.1)
|
mini_mime (>= 0.1.1)
|
||||||
|
net-imap
|
||||||
|
net-pop
|
||||||
|
net-smtp
|
||||||
mailcatcher (0.2.4)
|
mailcatcher (0.2.4)
|
||||||
eventmachine
|
eventmachine
|
||||||
haml
|
haml
|
||||||
|
@ -282,29 +319,34 @@ GEM
|
||||||
thin
|
thin
|
||||||
marcel (1.0.2)
|
marcel (1.0.2)
|
||||||
matrix (0.4.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)
|
method_source (1.0.0)
|
||||||
midi-smtp-server (3.0.3)
|
midi-smtp-server (3.0.3)
|
||||||
mime-types (3.4.1)
|
mime-types (3.4.1)
|
||||||
mime-types-data (~> 3.2015)
|
mime-types-data (~> 3.2015)
|
||||||
mime-types-data (3.2022.0105)
|
mime-types-data (3.2022.0105)
|
||||||
|
mini_magick (4.12.0)
|
||||||
mini_mime (1.1.2)
|
mini_mime (1.1.2)
|
||||||
mini_portile2 (2.8.0)
|
minitest (5.18.0)
|
||||||
minitest (5.16.3)
|
|
||||||
mono_logger (1.1.1)
|
mono_logger (1.1.1)
|
||||||
msgpack (1.6.0)
|
msgpack (1.6.0)
|
||||||
multi_json (1.15.0)
|
multi_json (1.15.0)
|
||||||
mustermann (3.0.0)
|
mustermann (3.0.0)
|
||||||
ruby2_keywords (~> 0.0.1)
|
ruby2_keywords (~> 0.0.1)
|
||||||
mysql2 (0.5.4)
|
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)
|
nio4r (2.5.8)
|
||||||
nokogiri (1.13.10)
|
nokogiri (1.15.2-x86_64-linux)
|
||||||
mini_portile2 (~> 2.8.0)
|
|
||||||
racc (~> 1.4)
|
racc (~> 1.4)
|
||||||
parallel (1.22.1)
|
parallel (1.23.0)
|
||||||
parser (3.1.2.1)
|
parser (3.2.2.1)
|
||||||
ast (~> 2.4.1)
|
ast (~> 2.4.1)
|
||||||
pdf-core (0.9.0)
|
pdf-core (0.9.0)
|
||||||
polyglot (0.3.5)
|
polyglot (0.3.5)
|
||||||
|
@ -322,75 +364,70 @@ GEM
|
||||||
pry-stack_explorer (0.6.1)
|
pry-stack_explorer (0.6.1)
|
||||||
binding_of_caller (~> 1.0)
|
binding_of_caller (~> 1.0)
|
||||||
pry (~> 0.13)
|
pry (~> 0.13)
|
||||||
public_suffix (5.0.0)
|
public_suffix (5.0.1)
|
||||||
puma (5.6.5)
|
puma (6.0.2)
|
||||||
nio4r (~> 2.0)
|
nio4r (~> 2.0)
|
||||||
racc (1.6.1)
|
racc (1.7.0)
|
||||||
rack (2.2.4)
|
rack (2.2.7)
|
||||||
rack-contrib (2.3.0)
|
|
||||||
rack (~> 2.0)
|
|
||||||
rack-cors (1.1.1)
|
rack-cors (1.1.1)
|
||||||
rack (>= 2.0.0)
|
rack (>= 2.0.0)
|
||||||
rack-protection (3.0.4)
|
rack-protection (3.0.5)
|
||||||
rack
|
rack
|
||||||
rack-test (2.0.2)
|
rack-test (2.1.0)
|
||||||
rack (>= 1.3)
|
rack (>= 1.3)
|
||||||
rails (5.2.8.1)
|
rails (7.0.4)
|
||||||
actioncable (= 5.2.8.1)
|
actioncable (= 7.0.4)
|
||||||
actionmailer (= 5.2.8.1)
|
actionmailbox (= 7.0.4)
|
||||||
actionpack (= 5.2.8.1)
|
actionmailer (= 7.0.4)
|
||||||
actionview (= 5.2.8.1)
|
actionpack (= 7.0.4)
|
||||||
activejob (= 5.2.8.1)
|
actiontext (= 7.0.4)
|
||||||
activemodel (= 5.2.8.1)
|
actionview (= 7.0.4)
|
||||||
activerecord (= 5.2.8.1)
|
activejob (= 7.0.4)
|
||||||
activestorage (= 5.2.8.1)
|
activemodel (= 7.0.4)
|
||||||
activesupport (= 5.2.8.1)
|
activerecord (= 7.0.4)
|
||||||
bundler (>= 1.3.0)
|
activestorage (= 7.0.4)
|
||||||
railties (= 5.2.8.1)
|
activesupport (= 7.0.4)
|
||||||
sprockets-rails (>= 2.0.0)
|
bundler (>= 1.15.0)
|
||||||
|
railties (= 7.0.4)
|
||||||
rails-assets-listjs (0.2.0.beta.4)
|
rails-assets-listjs (0.2.0.beta.4)
|
||||||
railties (>= 3.1)
|
railties (>= 3.1)
|
||||||
rails-dom-testing (2.0.3)
|
rails-dom-testing (2.0.3)
|
||||||
activesupport (>= 4.2.0)
|
activesupport (>= 4.2.0)
|
||||||
nokogiri (>= 1.6)
|
nokogiri (>= 1.6)
|
||||||
rails-html-sanitizer (1.4.4)
|
rails-html-sanitizer (1.6.0)
|
||||||
loofah (~> 2.19, >= 2.19.1)
|
loofah (~> 2.21)
|
||||||
rails-i18n (5.1.3)
|
nokogiri (~> 1.14)
|
||||||
|
rails-i18n (7.0.6)
|
||||||
i18n (>= 0.7, < 2)
|
i18n (>= 0.7, < 2)
|
||||||
railties (>= 5.0, < 6)
|
railties (>= 6.0.0, < 8)
|
||||||
rails-settings-cached (0.4.3)
|
rails-settings-cached (0.4.3)
|
||||||
rails (>= 4.2.0)
|
rails (>= 4.2.0)
|
||||||
rails_tokeninput (1.7.0)
|
rails_tokeninput (1.7.0)
|
||||||
railties (>= 3.1.0)
|
railties (>= 3.1.0)
|
||||||
railties (5.2.8.1)
|
railties (7.0.4)
|
||||||
actionpack (= 5.2.8.1)
|
actionpack (= 7.0.4)
|
||||||
activesupport (= 5.2.8.1)
|
activesupport (= 7.0.4)
|
||||||
method_source
|
method_source
|
||||||
rake (>= 0.8.7)
|
rake (>= 12.2)
|
||||||
thor (>= 0.19.0, < 2.0)
|
thor (~> 1.0)
|
||||||
|
zeitwerk (~> 2.5)
|
||||||
rainbow (3.1.1)
|
rainbow (3.1.1)
|
||||||
rake (13.0.6)
|
rake (13.0.6)
|
||||||
ransack (2.5.0)
|
ransack (3.2.1)
|
||||||
activerecord (>= 5.2.4)
|
activerecord (>= 6.1.5)
|
||||||
activesupport (>= 5.2.4)
|
activesupport (>= 6.1.5)
|
||||||
i18n
|
i18n
|
||||||
rb-fsevent (0.11.2)
|
rb-fsevent (0.11.2)
|
||||||
rb-inotify (0.10.1)
|
rb-inotify (0.10.1)
|
||||||
ffi (~> 1.0)
|
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 (5.0.5)
|
||||||
redis-client (>= 0.9.0)
|
redis-client (>= 0.9.0)
|
||||||
redis-client (0.9.0)
|
redis-client (0.11.2)
|
||||||
connection_pool
|
connection_pool
|
||||||
redis-namespace (1.9.0)
|
redis-namespace (1.10.0)
|
||||||
redis (>= 4)
|
redis (>= 4)
|
||||||
ref (2.0.0)
|
ref (2.0.0)
|
||||||
regexp_parser (2.6.0)
|
regexp_parser (2.8.0)
|
||||||
responders (3.0.1)
|
responders (3.0.1)
|
||||||
actionpack (>= 5.0)
|
actionpack (>= 5.0)
|
||||||
railties (>= 5.0)
|
railties (>= 5.0)
|
||||||
|
@ -400,59 +437,71 @@ GEM
|
||||||
redis-namespace (~> 1.6)
|
redis-namespace (~> 1.6)
|
||||||
sinatra (>= 0.9.2)
|
sinatra (>= 0.9.2)
|
||||||
rexml (3.2.5)
|
rexml (3.2.5)
|
||||||
roo (2.8.3)
|
roo (2.9.0)
|
||||||
nokogiri (~> 1)
|
nokogiri (~> 1)
|
||||||
rubyzip (>= 1.3.0, < 3.0.0)
|
rubyzip (>= 1.3.0, < 3.0.0)
|
||||||
roo-xls (1.2.0)
|
roo-xls (1.2.0)
|
||||||
nokogiri
|
nokogiri
|
||||||
roo (>= 2.0.0, < 3)
|
roo (>= 2.0.0, < 3)
|
||||||
spreadsheet (> 0.9.0)
|
spreadsheet (> 0.9.0)
|
||||||
rspec (3.11.0)
|
rspec (3.12.0)
|
||||||
rspec-core (~> 3.11.0)
|
rspec-core (~> 3.12.0)
|
||||||
rspec-expectations (~> 3.11.0)
|
rspec-expectations (~> 3.12.0)
|
||||||
rspec-mocks (~> 3.11.0)
|
rspec-mocks (~> 3.12.0)
|
||||||
rspec-core (3.11.0)
|
rspec-core (3.12.0)
|
||||||
rspec-support (~> 3.11.0)
|
rspec-support (~> 3.12.0)
|
||||||
rspec-expectations (3.11.1)
|
rspec-expectations (3.12.1)
|
||||||
diff-lcs (>= 1.2.0, < 2.0)
|
diff-lcs (>= 1.2.0, < 2.0)
|
||||||
rspec-support (~> 3.11.0)
|
rspec-support (~> 3.12.0)
|
||||||
rspec-mocks (3.11.1)
|
rspec-mocks (3.12.1)
|
||||||
diff-lcs (>= 1.2.0, < 2.0)
|
diff-lcs (>= 1.2.0, < 2.0)
|
||||||
rspec-support (~> 3.11.0)
|
rspec-support (~> 3.12.0)
|
||||||
rspec-rails (5.1.2)
|
rspec-rails (6.0.1)
|
||||||
actionpack (>= 5.2)
|
actionpack (>= 6.1)
|
||||||
activesupport (>= 5.2)
|
activesupport (>= 6.1)
|
||||||
railties (>= 5.2)
|
railties (>= 6.1)
|
||||||
rspec-core (~> 3.10)
|
rspec-core (~> 3.11)
|
||||||
rspec-expectations (~> 3.10)
|
rspec-expectations (~> 3.11)
|
||||||
rspec-mocks (~> 3.10)
|
rspec-mocks (~> 3.11)
|
||||||
rspec-support (~> 3.10)
|
rspec-support (~> 3.11)
|
||||||
rspec-rerun (1.1.0)
|
rspec-rerun (1.1.0)
|
||||||
rspec (~> 3.0)
|
rspec (~> 3.0)
|
||||||
rspec-support (3.11.1)
|
rspec-support (3.12.0)
|
||||||
rubocop (1.36.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)
|
json (~> 2.3)
|
||||||
parallel (~> 1.10)
|
parallel (~> 1.10)
|
||||||
parser (>= 3.1.2.1)
|
parser (>= 3.2.0.0)
|
||||||
rainbow (>= 2.2.2, < 4.0)
|
rainbow (>= 2.2.2, < 4.0)
|
||||||
regexp_parser (>= 1.8, < 3.0)
|
regexp_parser (>= 1.8, < 3.0)
|
||||||
rexml (>= 3.2.5, < 4.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)
|
ruby-progressbar (~> 1.7)
|
||||||
unicode-display_width (>= 1.4.0, < 3.0)
|
unicode-display_width (>= 2.4.0, < 3.0)
|
||||||
rubocop-ast (1.21.0)
|
rubocop-ast (1.28.1)
|
||||||
parser (>= 3.1.1.0)
|
parser (>= 3.2.1.0)
|
||||||
rubocop-rails (2.16.1)
|
rubocop-rails (2.17.4)
|
||||||
activesupport (>= 4.2.0)
|
activesupport (>= 4.2.0)
|
||||||
rack (>= 1.1)
|
rack (>= 1.1)
|
||||||
rubocop (>= 1.33.0, < 2.0)
|
rubocop (>= 1.33.0, < 2.0)
|
||||||
rubocop-rspec (2.13.2)
|
rubocop-rspec (2.16.0)
|
||||||
rubocop (~> 1.33)
|
rubocop (~> 1.33)
|
||||||
ruby-filemagic (0.7.3)
|
ruby-filemagic (0.7.3)
|
||||||
ruby-ole (1.2.12.2)
|
ruby-ole (1.2.12.2)
|
||||||
ruby-prof (1.4.3)
|
ruby-prof (1.4.5)
|
||||||
ruby-progressbar (1.11.0)
|
ruby-progressbar (1.13.0)
|
||||||
ruby-units (3.0.0)
|
ruby-units (3.0.0)
|
||||||
|
ruby-vips (2.1.4)
|
||||||
|
ffi (~> 1.12)
|
||||||
ruby2_keywords (0.0.5)
|
ruby2_keywords (0.0.5)
|
||||||
rubyzip (2.3.2)
|
rubyzip (2.3.2)
|
||||||
sass-rails (6.0.0)
|
sass-rails (6.0.0)
|
||||||
|
@ -467,6 +516,10 @@ GEM
|
||||||
tilt
|
tilt
|
||||||
sd_notify (0.1.1)
|
sd_notify (0.1.1)
|
||||||
select2-rails (4.0.13)
|
select2-rails (4.0.13)
|
||||||
|
sepa_king (0.14.0)
|
||||||
|
activemodel (>= 4.2)
|
||||||
|
iban-tools
|
||||||
|
nokogiri
|
||||||
simple-navigation (3.14.0)
|
simple-navigation (3.14.0)
|
||||||
activesupport (>= 2.3.2)
|
activesupport (>= 2.3.2)
|
||||||
simple-navigation-bootstrap (1.0.2)
|
simple-navigation-bootstrap (1.0.2)
|
||||||
|
@ -475,21 +528,21 @@ GEM
|
||||||
simple_form (5.1.0)
|
simple_form (5.1.0)
|
||||||
actionpack (>= 5.2)
|
actionpack (>= 5.2)
|
||||||
activemodel (>= 5.2)
|
activemodel (>= 5.2)
|
||||||
simplecov (0.21.2)
|
simplecov (0.22.0)
|
||||||
docile (~> 1.1)
|
docile (~> 1.1)
|
||||||
simplecov-html (~> 0.11)
|
simplecov-html (~> 0.11)
|
||||||
simplecov_json_formatter (~> 0.1)
|
simplecov_json_formatter (~> 0.1)
|
||||||
simplecov-html (0.12.3)
|
simplecov-html (0.12.3)
|
||||||
simplecov-lcov (0.8.0)
|
simplecov-lcov (0.8.0)
|
||||||
simplecov_json_formatter (0.1.4)
|
simplecov_json_formatter (0.1.4)
|
||||||
sinatra (3.0.4)
|
sinatra (3.0.5)
|
||||||
mustermann (~> 3.0)
|
mustermann (~> 3.0)
|
||||||
rack (~> 2.2, >= 2.2.4)
|
rack (~> 2.2, >= 2.2.4)
|
||||||
rack-protection (= 3.0.4)
|
rack-protection (= 3.0.5)
|
||||||
tilt (~> 2.0)
|
tilt (~> 2.0)
|
||||||
skinny (0.2.2)
|
skinny (0.2.4)
|
||||||
eventmachine (~> 1.0)
|
eventmachine (~> 1.0.0)
|
||||||
thin
|
thin (>= 1.5, < 1.7)
|
||||||
spreadsheet (1.3.0)
|
spreadsheet (1.3.0)
|
||||||
ruby-ole
|
ruby-ole
|
||||||
sprockets (3.7.2)
|
sprockets (3.7.2)
|
||||||
|
@ -503,17 +556,19 @@ GEM
|
||||||
sqlite3-ruby (1.3.3)
|
sqlite3-ruby (1.3.3)
|
||||||
sqlite3 (>= 1.3.3)
|
sqlite3 (>= 1.3.3)
|
||||||
table_print (1.5.7)
|
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)
|
therubyracer (0.12.3)
|
||||||
libv8 (~> 3.16.14.15)
|
libv8 (~> 3.16.14.15)
|
||||||
ref
|
ref
|
||||||
thin (1.8.1)
|
thin (1.6.2)
|
||||||
daemons (~> 1.0, >= 1.0.9)
|
daemons (>= 1.0.9)
|
||||||
eventmachine (~> 1.0, >= 1.0.4)
|
eventmachine (>= 1.0.0)
|
||||||
rack (>= 1, < 3)
|
rack (>= 1.0.0)
|
||||||
thor (1.2.1)
|
thor (1.2.2)
|
||||||
thread_safe (0.3.6)
|
|
||||||
tilt (2.0.11)
|
tilt (2.0.11)
|
||||||
|
timeout (0.3.1)
|
||||||
ttfunk (1.7.0)
|
ttfunk (1.7.0)
|
||||||
twitter-bootstrap-rails (2.2.8)
|
twitter-bootstrap-rails (2.2.8)
|
||||||
actionpack (>= 3.1)
|
actionpack (>= 3.1)
|
||||||
|
@ -522,20 +577,18 @@ GEM
|
||||||
railties (>= 3.1)
|
railties (>= 3.1)
|
||||||
twitter-text (1.14.7)
|
twitter-text (1.14.7)
|
||||||
unf (~> 0.1.0)
|
unf (~> 0.1.0)
|
||||||
tzinfo (1.2.10)
|
tzinfo (2.0.6)
|
||||||
thread_safe (~> 0.1)
|
concurrent-ruby (~> 1.0)
|
||||||
uglifier (4.2.0)
|
|
||||||
execjs (>= 0.3.0, < 3)
|
|
||||||
unf (0.1.4)
|
unf (0.1.4)
|
||||||
unf_ext
|
unf_ext
|
||||||
unf_ext (0.0.8.2)
|
unf_ext (0.0.8.2)
|
||||||
unicode-display_width (2.3.0)
|
unicode-display_width (2.4.2)
|
||||||
uniform_notifier (1.16.0)
|
uniform_notifier (1.16.0)
|
||||||
web-console (3.7.0)
|
web-console (4.2.0)
|
||||||
actionview (>= 5.0)
|
actionview (>= 6.0.0)
|
||||||
activemodel (>= 5.0)
|
activemodel (>= 6.0.0)
|
||||||
bindex (>= 0.4.0)
|
bindex (>= 0.4.0)
|
||||||
railties (>= 5.0)
|
railties (>= 6.0.0)
|
||||||
websocket-driver (0.7.5)
|
websocket-driver (0.7.5)
|
||||||
websocket-extensions (>= 0.1.0)
|
websocket-extensions (>= 0.1.0)
|
||||||
websocket-extensions (0.1.5)
|
websocket-extensions (0.1.5)
|
||||||
|
@ -549,15 +602,15 @@ GEM
|
||||||
twitter-text
|
twitter-text
|
||||||
xpath (3.2.0)
|
xpath (3.2.0)
|
||||||
nokogiri (~> 1.8)
|
nokogiri (~> 1.8)
|
||||||
|
zeitwerk (2.6.8)
|
||||||
|
|
||||||
PLATFORMS
|
PLATFORMS
|
||||||
ruby
|
x86_64-linux
|
||||||
|
|
||||||
DEPENDENCIES
|
DEPENDENCIES
|
||||||
active_model_serializers (~> 0.10.0)
|
active_model_serializers (~> 0.10.0)
|
||||||
acts_as_tree
|
acts_as_tree
|
||||||
acts_as_versioned!
|
acts_as_versioned!
|
||||||
apivore
|
|
||||||
apparition
|
apparition
|
||||||
attribute_normalizer
|
attribute_normalizer
|
||||||
better_errors
|
better_errors
|
||||||
|
@ -582,19 +635,20 @@ DEPENDENCIES
|
||||||
foodsoft_polls!
|
foodsoft_polls!
|
||||||
foodsoft_wiki!
|
foodsoft_wiki!
|
||||||
gaffe
|
gaffe
|
||||||
haml
|
haml (~> 5.0)
|
||||||
haml-rails
|
haml-rails
|
||||||
hashie (~> 3.4.6)
|
hashie (~> 3.4.6)
|
||||||
i18n-js (~> 3.0.0.rc8)
|
i18n-js (~> 3.0.0.rc8)
|
||||||
i18n-spec
|
i18n-spec
|
||||||
ice_cube
|
ice_cube
|
||||||
|
image_processing (~> 1.12)
|
||||||
|
importmap-rails (~> 1.1)
|
||||||
inherited_resources
|
inherited_resources
|
||||||
jquery-rails
|
jquery-rails
|
||||||
kaminari
|
kaminari
|
||||||
less-rails
|
less-rails
|
||||||
listen
|
listen
|
||||||
mailcatcher
|
mailcatcher
|
||||||
meta_request
|
|
||||||
midi-smtp-server
|
midi-smtp-server
|
||||||
mime-types
|
mime-types
|
||||||
mysql2
|
mysql2
|
||||||
|
@ -604,28 +658,32 @@ DEPENDENCIES
|
||||||
pry-stack_explorer
|
pry-stack_explorer
|
||||||
puma
|
puma
|
||||||
rack-cors
|
rack-cors
|
||||||
rails (~> 5.2)
|
rails (~> 7.0)
|
||||||
rails-assets-listjs (= 0.2.0.beta.4)
|
rails-assets-listjs (= 0.2.0.beta.4)
|
||||||
rails-i18n
|
rails-i18n
|
||||||
rails-settings-cached (= 0.4.3)
|
rails-settings-cached (= 0.4.3)
|
||||||
rails_tokeninput
|
rails_tokeninput
|
||||||
ransack
|
ransack
|
||||||
recurring_select
|
recurring_select!
|
||||||
resque
|
resque
|
||||||
roo
|
roo
|
||||||
roo-xls
|
roo-xls
|
||||||
rspec-core
|
rspec-core
|
||||||
rspec-rails
|
rspec-rails
|
||||||
rspec-rerun
|
rspec-rerun
|
||||||
|
rswag-api
|
||||||
|
rswag-specs
|
||||||
|
rswag-ui
|
||||||
rubocop
|
rubocop
|
||||||
rubocop-rails
|
rubocop-rails
|
||||||
rubocop-rspec
|
rubocop-rspec
|
||||||
ruby-filemagic
|
ruby-filemagic
|
||||||
ruby-prof
|
ruby-prof
|
||||||
ruby-units
|
ruby-units
|
||||||
sass-rails
|
sassc-rails
|
||||||
sd_notify
|
sd_notify
|
||||||
select2-rails
|
select2-rails
|
||||||
|
sepa_king
|
||||||
simple-navigation (~> 3.14.0)
|
simple-navigation (~> 3.14.0)
|
||||||
simple-navigation-bootstrap
|
simple-navigation-bootstrap
|
||||||
simple_form
|
simple_form
|
||||||
|
@ -635,11 +693,11 @@ DEPENDENCIES
|
||||||
sprockets (< 4)
|
sprockets (< 4)
|
||||||
sqlite3 (~> 1.3.6)
|
sqlite3 (~> 1.3.6)
|
||||||
table_print
|
table_print
|
||||||
|
terser (~> 1.1)
|
||||||
therubyracer
|
therubyracer
|
||||||
twitter-bootstrap-rails (~> 2.2.8)
|
twitter-bootstrap-rails (~> 2.2.8)
|
||||||
uglifier (>= 1.0.3)
|
|
||||||
web-console
|
web-console
|
||||||
whenever
|
whenever
|
||||||
|
|
||||||
BUNDLED WITH
|
BUNDLED WITH
|
||||||
1.17.3
|
2.4.21
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
Foodsoft
|
Foodsoft
|
||||||
=========
|
=========
|
||||||
|
|
||||||
[![Build Status](https://github.com/foodcoops/foodsoft/workflows/Ruby/badge.svg)](https://github.com/foodcoops/foodsoft/actions)
|
[![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)
|
[![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)
|
[![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).
|
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
|
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),
|
Get foodsoft [running locally](doc/SETUP_DEVELOPMENT.md),
|
||||||
then visit our [Developing Guidelines](https://github.com/foodcoops/foodsoft/wiki/Developing-Guidelines)
|
then visit our [Developing Guidelines](https://github.com/foodcoops/foodsoft/wiki/Developing-Guidelines)
|
||||||
page on the wiki.
|
page on the wiki.
|
||||||
|
@ -35,7 +42,6 @@ Deploying
|
||||||
Setup foodsoft to [run in production](doc/SETUP_PRODUCTION.md), or join an existing
|
Setup foodsoft to [run in production](doc/SETUP_PRODUCTION.md), or join an existing
|
||||||
[hosting platform](https://foodcoops.net/foodsoft-hosting/).
|
[hosting platform](https://foodcoops.net/foodsoft-hosting/).
|
||||||
|
|
||||||
|
|
||||||
License
|
License
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
|
2
Rakefile
2
Rakefile
|
@ -1,7 +1,7 @@
|
||||||
#!/usr/bin/env rake
|
#!/usr/bin/env rake
|
||||||
# Add your own tasks in files placed in lib/tasks ending in .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 'rake'
|
||||||
require 'rspec-rerun/tasks' if defined?(RSpec) # http://stackoverflow.com/a/16853615/2866660
|
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.es
|
||||||
//= require bootstrap-datepicker/locales/bootstrap-datepicker.nl
|
//= require bootstrap-datepicker/locales/bootstrap-datepicker.nl
|
||||||
//= require bootstrap-datepicker/locales/bootstrap-datepicker.fr
|
//= require bootstrap-datepicker/locales/bootstrap-datepicker.fr
|
||||||
|
//= require bootstrap-datepicker/locales/bootstrap-datepicker.tr
|
||||||
//= require list
|
//= require list
|
||||||
//= require list.unlist
|
//= require list.unlist
|
||||||
//= require list.delay
|
//= require list.delay
|
||||||
|
@ -20,6 +21,7 @@
|
||||||
//= require touchclick
|
//= require touchclick
|
||||||
//= require delta_input
|
//= require delta_input
|
||||||
//= require recurring_select
|
//= require recurring_select
|
||||||
|
//= require order
|
||||||
|
|
||||||
$.fn.select2.defaults.set('theme', 'bootstrap');
|
$.fn.select2.defaults.set('theme', 'bootstrap');
|
||||||
|
|
0
app/assets/javascripts/autocomplete_sepa.js
Normal file
0
app/assets/javascripts/autocomplete_sepa.js
Normal file
140
app/assets/javascripts/order.js
Normal file
140
app/assets/javascripts/order.js
Normal file
|
@ -0,0 +1,140 @@
|
||||||
|
|
||||||
|
function doTheDownload(selectedGroupOrderIds, orderId, url, supplier, mode = "all") {
|
||||||
|
if (mode == "all") {
|
||||||
|
var data = { order_id: orderId }
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
var data = { group_order_ids: selectedGroupOrderIds }
|
||||||
|
}
|
||||||
|
if (mode == "all" || selectedGroupOrderIds.length > 0) {
|
||||||
|
//suppress generic error warning
|
||||||
|
$.ajaxSetup({
|
||||||
|
global: false,
|
||||||
|
});
|
||||||
|
$.ajax({
|
||||||
|
url: url,
|
||||||
|
method: 'GET', // You may adjust the HTTP method as needed
|
||||||
|
data: data,
|
||||||
|
dataType: 'xml',
|
||||||
|
success: function (response) {
|
||||||
|
// Handle success response
|
||||||
|
// Convert XML response to a Blob
|
||||||
|
var blob = new Blob([new XMLSerializer().serializeToString(response)], { type: 'text/xml' });
|
||||||
|
var order_id = orderId
|
||||||
|
// Create a temporary link element
|
||||||
|
var link = document.createElement('a');
|
||||||
|
link.href = URL.createObjectURL(blob);
|
||||||
|
if (selectedGroupOrderIds.length > 1) {
|
||||||
|
link.download = supplier + "-" + orderId + "-Sammellastschrift.xml";
|
||||||
|
} else {
|
||||||
|
link.download = supplier + "-" + orderId + "-Lastschrift.xml";
|
||||||
|
}
|
||||||
|
// Append the link to the document and trigger the click event
|
||||||
|
document.body.appendChild(link);
|
||||||
|
link.click();
|
||||||
|
|
||||||
|
// Clean up
|
||||||
|
document.body.removeChild(link);
|
||||||
|
$("group-order-invoices-for-order-" + orderId + " .expand-trigger a").click();
|
||||||
|
var modalSelector = "#order_" + orderId + "_modal";
|
||||||
|
|
||||||
|
// Update the value attribute of checkboxes with IDs starting with "sepa_downloaded" to '1'
|
||||||
|
if (selectedGroupOrderIds.length >= 1) {
|
||||||
|
selectedGroupOrderIds.forEach(function (groupOrderId) {
|
||||||
|
var modalSelector = "#group_order_" + groupOrderId;
|
||||||
|
checkbox_element = $(modalSelector + ' input[id^="sepa_downloaded"]');
|
||||||
|
checkbox_element.val('1');
|
||||||
|
checkbox_element.prop('checked', true);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
$(modalSelector + ' input[id^="sepa_downloaded"]').each(function () {
|
||||||
|
$(this).val('1');
|
||||||
|
$(this).prop('checked', true);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
error: function (error) {
|
||||||
|
// Handle error
|
||||||
|
if (error.responseJSON) {
|
||||||
|
alert('AJAX request error:' + "\n" + error.responseJSON.message);
|
||||||
|
} else {
|
||||||
|
var errorText = JSON.parse(error.responseText).error;
|
||||||
|
var alertDiv = '<div class="alert fade in alert-error"><button class="close" data-dismiss="alert">×</button>' + errorText + '</div>';
|
||||||
|
$('.page-header').before(alertDiv);
|
||||||
|
$('modal_')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
var errorText = "Nothing selected";
|
||||||
|
var alertDiv = '<div class="alert fade in alert-error"><button class="close" data-dismiss="alert">×</button>' + errorText + '</div>';
|
||||||
|
$('.page-header').before(alertDiv);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
$(document).off('change', '[class^="ajax-update-all-link-"] select').on('change', '[class^="ajax-update-all-link-"] select', function () {
|
||||||
|
var selectedValue = $(this).val();
|
||||||
|
var url = $(this).closest('a').attr('href');
|
||||||
|
$.ajax({
|
||||||
|
url: url,
|
||||||
|
method: 'PATCH',
|
||||||
|
data: { sepa_sequence_type: selectedValue },
|
||||||
|
success: function (response) {
|
||||||
|
// Handle success response
|
||||||
|
},
|
||||||
|
error: function (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
$(document).off('change', '[class^="ajax-update-link-"] select').on('change', '[class^="ajax-update-link-"] select', function () {
|
||||||
|
var selectedValue = $(this).val();
|
||||||
|
var url = $(this).closest('a').attr('href');
|
||||||
|
$.ajax({
|
||||||
|
url: url,
|
||||||
|
method: 'PATCH',
|
||||||
|
data: { sepa_sequence_type: selectedValue },
|
||||||
|
success: function (response) {
|
||||||
|
// Handle success response
|
||||||
|
},
|
||||||
|
error: function (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
$(document).on('ready turbolinks:load', function () {
|
||||||
|
$('.expand-trigger').click(function () {
|
||||||
|
var orderId = $(this).closest('tr').data('order_id');
|
||||||
|
var expandedRow = $('#expanded-row-' + orderId);
|
||||||
|
// Toggle visibility of the expanded row
|
||||||
|
expandedRow.slideToggle();
|
||||||
|
|
||||||
|
return false; // Prevent the default behavior of the link
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
$(document).off('click', '[id^="collective-direct-debit-link-selected-"]').on('click', '[id^="collective-direct-debit-link-selected-"]', function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
var orderId = $(this).data("order-id");
|
||||||
|
var supplier = $(this).data("supplier");
|
||||||
|
// Extract selected group_order_ids
|
||||||
|
var selectedGroupOrderIds = $('input[name^="group_order_ids_for_order_' + orderId + '"]:checked').map(function () {
|
||||||
|
return $(this).val();
|
||||||
|
}).get();
|
||||||
|
console.log(selectedGroupOrderIds);
|
||||||
|
|
||||||
|
var url = $(this).closest('a').attr('href');
|
||||||
|
doTheDownload(selectedGroupOrderIds, orderId, url, supplier, "selected");
|
||||||
|
});
|
||||||
|
|
||||||
|
$(document).off('click', '[id^="collective-direct-debit-link-all-"]').on('click', '[id^="collective-direct-debit-link-all-"]', function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
var orderId = $(this).data("order-id");
|
||||||
|
var supplier = $(this).data("supplier");
|
||||||
|
var url = $(this).closest('a').attr('href');
|
||||||
|
doTheDownload([], orderId, url, supplier, "all");
|
||||||
|
});
|
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;
|
||||||
|
}
|
|
@ -1,4 +1,5 @@
|
||||||
/*
|
/*
|
||||||
|
*= require group_order_invoices
|
||||||
*= require bootstrap_and_overrides
|
*= require bootstrap_and_overrides
|
||||||
*= require select2
|
*= require select2
|
||||||
*= require select2-bootstrap
|
*= require select2-bootstrap
|
||||||
|
@ -7,4 +8,5 @@
|
||||||
*= require list.unlist
|
*= require list.unlist
|
||||||
*= require list.missing
|
*= require list.missing
|
||||||
*= require recurring_select
|
*= require recurring_select
|
||||||
|
*= require actiontext
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -241,6 +241,9 @@ table {
|
||||||
tr.order-article:hover .article-info {
|
tr.order-article:hover .article-info {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
tr.order-article:focus .article-info {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#order-footer {
|
#order-footer {
|
||||||
|
@ -275,11 +278,13 @@ tr.order-article .article-info {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
tr.order-article:hover .article-info {
|
tr.order-article:focus{
|
||||||
|
background-color: #E4EED6;
|
||||||
|
}
|
||||||
|
tr.order-article:focus .article-info {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// ********* Articles
|
// ********* Articles
|
||||||
|
|
||||||
tr.just-updated {
|
tr.just-updated {
|
||||||
|
|
46
app/assets/stylesheets/group_order_invoices.css
Normal file
46
app/assets/stylesheets/group_order_invoices.css
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
.checkbox-icon {
|
||||||
|
display: inline-block;
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
position: relative;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.checkbox-icon::before {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
border: 1px solid #000;
|
||||||
|
background-color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.checkbox-icon.checked::before {
|
||||||
|
content: "\2713"; /* Unicode checkmark symbol */
|
||||||
|
text-align: center;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 20px; /* Align the checkmark vertically */
|
||||||
|
color: #00ff00; /* Change the color to represent a checked state */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.table.group-order-invoices-table tr{
|
||||||
|
background-color: rgb(255, 255, 233);
|
||||||
|
}
|
||||||
|
.table.group-order-invoices-table thead tr{
|
||||||
|
background-color: lightgoldenrodyellow;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table.group-order-invoices-table tr:nth-child(odd) > td,
|
||||||
|
.table.group-order-invoices-table tr:nth-child(even) > td{
|
||||||
|
background-color: rgb(255, 255, 233);
|
||||||
|
padding-right: 0;
|
||||||
|
.group-order-checkbox {
|
||||||
|
margin-left: 20px;
|
||||||
|
}
|
||||||
|
.form-check-input{
|
||||||
|
margin-left: 20px;
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,39 +3,39 @@ class Admin::BankAccountsController < Admin::BaseController
|
||||||
|
|
||||||
def new
|
def new
|
||||||
@bank_account = BankAccount.new(params[:bank_account])
|
@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
|
end
|
||||||
|
|
||||||
def create
|
def create
|
||||||
@bank_account = BankAccount.new(params[:bank_account])
|
@bank_account = BankAccount.new(params[:bank_account])
|
||||||
if @bank_account.valid? && @bank_account.save
|
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
|
else
|
||||||
render :action => 'new', :layout => false
|
render action: 'new', layout: false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def edit
|
|
||||||
@bank_account = BankAccount.find(params[:id])
|
|
||||||
render :action => 'new', :layout => false
|
|
||||||
end
|
|
||||||
|
|
||||||
def update
|
def update
|
||||||
@bank_account = BankAccount.find(params[:id])
|
@bank_account = BankAccount.find(params[:id])
|
||||||
|
|
||||||
if @bank_account.update(params[:bank_account])
|
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
|
else
|
||||||
render :action => 'new', :layout => false
|
render action: 'new', layout: false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def destroy
|
def destroy
|
||||||
@bank_account = BankAccount.find(params[:id])
|
@bank_account = BankAccount.find(params[:id])
|
||||||
@bank_account.destroy
|
@bank_account.destroy
|
||||||
redirect_to update_bank_accounts_admin_finances_url, :status => 303
|
redirect_to update_bank_accounts_admin_finances_url, status: :see_other
|
||||||
rescue => error
|
rescue StandardError => e
|
||||||
flash.now[:alert] = error.message
|
flash.now[:alert] = e.message
|
||||||
render template: 'shared/alert'
|
render template: 'shared/alert'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -6,6 +6,11 @@ class Admin::BankGatewaysController < Admin::BaseController
|
||||||
render layout: false
|
render layout: false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def edit
|
||||||
|
@bank_gateway = BankGateway.find(params[:id])
|
||||||
|
render action: 'new', layout: false
|
||||||
|
end
|
||||||
|
|
||||||
def create
|
def create
|
||||||
@bank_gateway = BankGateway.new(params[:bank_gateway])
|
@bank_gateway = BankGateway.new(params[:bank_gateway])
|
||||||
if @bank_gateway.valid? && @bank_gateway.save
|
if @bank_gateway.valid? && @bank_gateway.save
|
||||||
|
@ -15,11 +20,6 @@ class Admin::BankGatewaysController < Admin::BaseController
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def edit
|
|
||||||
@bank_gateway = BankGateway.find(params[:id])
|
|
||||||
render action: 'new', layout: false
|
|
||||||
end
|
|
||||||
|
|
||||||
def update
|
def update
|
||||||
@bank_gateway = BankGateway.find(params[:id])
|
@bank_gateway = BankGateway.find(params[:id])
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
class Admin::ConfigsController < Admin::BaseController
|
class Admin::ConfigsController < Admin::BaseController
|
||||||
before_action :get_tabs, only: [:show, :list]
|
before_action :get_tabs, only: %i[show list]
|
||||||
|
|
||||||
def show
|
def show
|
||||||
@current_tab = @tabs.include?(params[:tab]) ? params[:tab] : @tabs.first
|
@current_tab = @tabs.include?(params[:tab]) ? params[:tab] : @tabs.first
|
||||||
|
@ -16,7 +16,7 @@ class Admin::ConfigsController < Admin::BaseController
|
||||||
def update
|
def update
|
||||||
parse_recurring_selects! params[:config][:order_schedule]
|
parse_recurring_selects! params[:config][:order_schedule]
|
||||||
ActiveRecord::Base.transaction do
|
ActiveRecord::Base.transaction do
|
||||||
# TODO support nested configuration keys
|
# TODO: support nested configuration keys
|
||||||
params[:config].each do |key, val|
|
params[:config].each do |key, val|
|
||||||
FoodsoftConfig[key] = convert_config_value val
|
FoodsoftConfig[key] = convert_config_value val
|
||||||
end
|
end
|
||||||
|
@ -29,7 +29,7 @@ class Admin::ConfigsController < Admin::BaseController
|
||||||
|
|
||||||
# Set configuration tab names as `@tabs`
|
# Set configuration tab names as `@tabs`
|
||||||
def get_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
|
# allow engines to modify this list
|
||||||
engines = Rails::Engine.subclasses.map(&:instance).select { |e| e.respond_to?(:configuration) }
|
engines = Rails::Engine.subclasses.map(&:instance).select { |e| e.respond_to?(:configuration) }
|
||||||
engines.each { |e| e.configuration(@tabs, self) }
|
engines.each { |e| e.configuration(@tabs, self) }
|
||||||
|
@ -38,16 +38,16 @@ class Admin::ConfigsController < Admin::BaseController
|
||||||
|
|
||||||
# turn recurring rules into something palatable
|
# turn recurring rules into something palatable
|
||||||
def parse_recurring_selects!(config)
|
def parse_recurring_selects!(config)
|
||||||
if config
|
return unless config
|
||||||
for k in [:pickup, :boxfill, :ends] do
|
|
||||||
if config[k]
|
for k in %i[pickup boxfill ends] do
|
||||||
# allow clearing it using dummy value '{}' ('' would break recurring_select)
|
if config[k]
|
||||||
if config[k][:recurr].present? && config[k][:recurr] != '{}'
|
# allow clearing it using dummy value '{}' ('' would break recurring_select)
|
||||||
config[k][:recurr] = ActiveSupport::JSON.decode(config[k][:recurr])
|
if config[k][:recurr].present? && config[k][:recurr] != '{}'
|
||||||
config[k][:recurr] = FoodsoftDateUtil.rule_from(config[k][:recurr]).to_ical if config[k][:recurr]
|
config[k][:recurr] = ActiveSupport::JSON.decode(config[k][:recurr])
|
||||||
else
|
config[k][:recurr] = FoodsoftDateUtil.rule_from(config[k][:recurr]).to_ical if config[k][:recurr]
|
||||||
config[k] = nil
|
else
|
||||||
end
|
config[k] = nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -10,21 +10,21 @@ class Admin::FinancesController < Admin::BaseController
|
||||||
|
|
||||||
def update_bank_accounts
|
def update_bank_accounts
|
||||||
@bank_accounts = BankAccount.order('name')
|
@bank_accounts = BankAccount.order('name')
|
||||||
render :layout => false
|
render layout: false
|
||||||
end
|
end
|
||||||
|
|
||||||
def update_bank_gateways
|
def update_bank_gateways
|
||||||
@bank_gateways = BankGateway.order('name')
|
@bank_gateways = BankGateway.order('name')
|
||||||
render :layout => false
|
render layout: false
|
||||||
end
|
end
|
||||||
|
|
||||||
def update_transaction_types
|
def update_transaction_types
|
||||||
@financial_transaction_classes = FinancialTransactionClass.includes(:financial_transaction_types).order('name ASC')
|
@financial_transaction_classes = FinancialTransactionClass.includes(:financial_transaction_types).order('name ASC')
|
||||||
render :layout => false
|
render layout: false
|
||||||
end
|
end
|
||||||
|
|
||||||
def update_supplier_categories
|
def update_supplier_categories
|
||||||
@supplier_categories = SupplierCategory.order('name')
|
@supplier_categories = SupplierCategory.order('name')
|
||||||
render :layout => false
|
render layout: false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -6,25 +6,25 @@ class Admin::FinancialTransactionClassesController < Admin::BaseController
|
||||||
render layout: false
|
render layout: false
|
||||||
end
|
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
|
def edit
|
||||||
@financial_transaction_class = FinancialTransactionClass.find(params[:id])
|
@financial_transaction_class = FinancialTransactionClass.find(params[:id])
|
||||||
render action: 'new', layout: false
|
render action: 'new', layout: false
|
||||||
end
|
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
|
def update
|
||||||
@financial_transaction_class = FinancialTransactionClass.find(params[:id])
|
@financial_transaction_class = FinancialTransactionClass.find(params[:id])
|
||||||
|
|
||||||
if @financial_transaction_class.update(params[:financial_transaction_class])
|
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
|
else
|
||||||
render action: 'new', layout: false
|
render action: 'new', layout: false
|
||||||
end
|
end
|
||||||
|
@ -33,9 +33,9 @@ class Admin::FinancialTransactionClassesController < Admin::BaseController
|
||||||
def destroy
|
def destroy
|
||||||
@financial_transaction_class = FinancialTransactionClass.find(params[:id])
|
@financial_transaction_class = FinancialTransactionClass.find(params[:id])
|
||||||
@financial_transaction_class.destroy!
|
@financial_transaction_class.destroy!
|
||||||
redirect_to update_transaction_types_admin_finances_url, status: 303
|
redirect_to update_transaction_types_admin_finances_url, status: :see_other
|
||||||
rescue => error
|
rescue StandardError => e
|
||||||
flash.now[:alert] = error.message
|
flash.now[:alert] = e.message
|
||||||
render template: 'shared/alert'
|
render template: 'shared/alert'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -7,25 +7,25 @@ class Admin::FinancialTransactionTypesController < Admin::BaseController
|
||||||
render layout: false
|
render layout: false
|
||||||
end
|
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
|
def edit
|
||||||
@financial_transaction_type = FinancialTransactionType.find(params[:id])
|
@financial_transaction_type = FinancialTransactionType.find(params[:id])
|
||||||
render action: 'new', layout: false
|
render action: 'new', layout: false
|
||||||
end
|
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
|
def update
|
||||||
@financial_transaction_type = FinancialTransactionType.find(params[:id])
|
@financial_transaction_type = FinancialTransactionType.find(params[:id])
|
||||||
|
|
||||||
if @financial_transaction_type.update(params[:financial_transaction_type])
|
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
|
else
|
||||||
render action: 'new', layout: false
|
render action: 'new', layout: false
|
||||||
end
|
end
|
||||||
|
@ -34,9 +34,9 @@ class Admin::FinancialTransactionTypesController < Admin::BaseController
|
||||||
def destroy
|
def destroy
|
||||||
@financial_transaction_type = FinancialTransactionType.find(params[:id])
|
@financial_transaction_type = FinancialTransactionType.find(params[:id])
|
||||||
@financial_transaction_type.destroy!
|
@financial_transaction_type.destroy!
|
||||||
redirect_to update_transaction_types_admin_finances_url, status: 303
|
redirect_to update_transaction_types_admin_finances_url, status: :see_other
|
||||||
rescue => error
|
rescue StandardError => e
|
||||||
flash.now[:alert] = error.message
|
flash.now[:alert] = e.message
|
||||||
render template: 'shared/alert'
|
render template: 'shared/alert'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,28 +3,28 @@ class Admin::MailDeliveryStatusController < Admin::BaseController
|
||||||
|
|
||||||
def index
|
def index
|
||||||
@maildeliverystatus = MailDeliveryStatus.order(created_at: :desc)
|
@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)
|
@maildeliverystatus = @maildeliverystatus.page(params[:page]).per(@per_page)
|
||||||
end
|
end
|
||||||
|
|
||||||
def show
|
def show
|
||||||
@maildeliverystatus = MailDeliveryStatus.find(params[:id])
|
@maildeliverystatus = MailDeliveryStatus.find(params[:id])
|
||||||
filename = "maildeliverystatus_#{params[:id]}.#{MIME::Types[@maildeliverystatus.attachment_mime].first.preferred_extension}"
|
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
|
end
|
||||||
|
|
||||||
def destroy_all
|
def destroy_all
|
||||||
@maildeliverystatus = MailDeliveryStatus.delete_all
|
@maildeliverystatus = MailDeliveryStatus.delete_all
|
||||||
redirect_to admin_mail_delivery_status_index_path, notice: t('.notice')
|
redirect_to admin_mail_delivery_status_index_path, notice: t('.notice')
|
||||||
rescue => error
|
rescue StandardError => e
|
||||||
redirect_to admin_mail_delivery_status_index_path, alert: I18n.t('errors.general_msg', msg: error.message)
|
redirect_to admin_mail_delivery_status_index_path, alert: I18n.t('errors.general_msg', msg: e.message)
|
||||||
end
|
end
|
||||||
|
|
||||||
def destroy
|
def destroy
|
||||||
@maildeliverystatus = MailDeliveryStatus.find(params[:id])
|
@maildeliverystatus = MailDeliveryStatus.find(params[:id])
|
||||||
@maildeliverystatus.destroy
|
@maildeliverystatus.destroy
|
||||||
redirect_to admin_mail_delivery_status_index_path, notice: t('.notice')
|
redirect_to admin_mail_delivery_status_index_path, notice: t('.notice')
|
||||||
rescue => error
|
rescue StandardError => e
|
||||||
redirect_to admin_mail_delivery_status_index_path, alert: I18n.t('errors.general_msg', msg: error.message)
|
redirect_to admin_mail_delivery_status_index_path, alert: I18n.t('errors.general_msg', msg: e.message)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,25 +2,40 @@ class Admin::OrdergroupsController < Admin::BaseController
|
||||||
inherit_resources
|
inherit_resources
|
||||||
|
|
||||||
def index
|
def index
|
||||||
@ordergroups = Ordergroup.undeleted.sort_by_param(params["sort"])
|
@ordergroups = Ordergroup.undeleted.sort_by_param(params['sort'])
|
||||||
|
|
||||||
if request.format.csv?
|
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
|
end
|
||||||
|
|
||||||
# if somebody uses the search field:
|
# if somebody uses the search field:
|
||||||
unless params[:query].blank?
|
@ordergroups = @ordergroups.where('name LIKE ?', "%#{params[:query]}%") if params[:query].present?
|
||||||
@ordergroups = @ordergroups.where('name LIKE ?', "%#{params[:query]}%")
|
|
||||||
end
|
|
||||||
|
|
||||||
@ordergroups = @ordergroups.page(params[:page]).per(@per_page)
|
@ordergroups = @ordergroups.page(params[:page]).per(@per_page)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def update
|
||||||
|
sepa_account_holder_params = params[:ordergroup][:sepa_account_holder_attributes]
|
||||||
|
if sepa_account_holder_params&.[](:user_id).blank? || sepa_account_holder_params&.[](:group_id).blank?
|
||||||
|
if sepa_account_holder_params&.[](:id).present?
|
||||||
|
SepaAccountHolder.find(sepa_account_holder_params[:id]).destroy
|
||||||
|
end
|
||||||
|
params[:ordergroup].delete(:sepa_account_holder_attributes)
|
||||||
|
end
|
||||||
|
@ordergroup = Ordergroup.find(params[:id])
|
||||||
|
if @ordergroup.update(params[:ordergroup])
|
||||||
|
redirect_to admin_ordergroup_path(@ordergroup), notice: t('.notice')
|
||||||
|
else
|
||||||
|
redirect_to edit_admin_ordergroup_path(@ordergroup), alert: @ordergroup.errors.full_messages.join(', ')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def destroy
|
def destroy
|
||||||
@ordergroup = Ordergroup.find(params[:id])
|
@ordergroup = Ordergroup.find(params[:id])
|
||||||
@ordergroup.mark_as_deleted
|
@ordergroup.mark_as_deleted
|
||||||
redirect_to admin_ordergroups_url, notice: t('admin.ordergroups.destroy.notice')
|
redirect_to admin_ordergroups_url, notice: t('.notice')
|
||||||
rescue => error
|
rescue StandardError => e
|
||||||
redirect_to admin_ordergroups_url, alert: t('admin.ordergroups.destroy.error')
|
redirect_to admin_ordergroups_url, alert: t('.error')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -6,6 +6,11 @@ class Admin::SupplierCategoriesController < Admin::BaseController
|
||||||
render layout: false
|
render layout: false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def edit
|
||||||
|
@supplier_category = SupplierCategory.find(params[:id])
|
||||||
|
render action: 'new', layout: false
|
||||||
|
end
|
||||||
|
|
||||||
def create
|
def create
|
||||||
@supplier_category = SupplierCategory.new(params[:supplier_category])
|
@supplier_category = SupplierCategory.new(params[:supplier_category])
|
||||||
if @supplier_category.valid? && @supplier_category.save
|
if @supplier_category.valid? && @supplier_category.save
|
||||||
|
@ -15,11 +20,6 @@ class Admin::SupplierCategoriesController < Admin::BaseController
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def edit
|
|
||||||
@supplier_category = SupplierCategory.find(params[:id])
|
|
||||||
render action: 'new', layout: false
|
|
||||||
end
|
|
||||||
|
|
||||||
def update
|
def update
|
||||||
@supplier_category = SupplierCategory.find(params[:id])
|
@supplier_category = SupplierCategory.find(params[:id])
|
||||||
|
|
||||||
|
|
|
@ -3,16 +3,14 @@ class Admin::UsersController < Admin::BaseController
|
||||||
|
|
||||||
def index
|
def index
|
||||||
@users = params[:show_deleted] ? User.deleted : User.undeleted
|
@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)
|
@users = @users.includes(:mail_delivery_status)
|
||||||
|
|
||||||
if request.format.csv?
|
send_data UsersCsv.new(@users).to_csv, filename: 'users.csv', type: 'text/csv' if request.format.csv?
|
||||||
send_data UsersCsv.new(@users).to_csv, filename: 'users.csv', type: 'text/csv'
|
|
||||||
end
|
|
||||||
|
|
||||||
# if somebody uses the search field:
|
# 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)
|
@users = @users.page(params[:page]).per(@per_page)
|
||||||
end
|
end
|
||||||
|
@ -20,17 +18,17 @@ class Admin::UsersController < Admin::BaseController
|
||||||
def destroy
|
def destroy
|
||||||
@user = User.find(params[:id])
|
@user = User.find(params[:id])
|
||||||
@user.mark_as_deleted
|
@user.mark_as_deleted
|
||||||
redirect_to admin_users_url, notice: t('admin.users.destroy.notice')
|
redirect_to admin_users_url, notice: t('.notice')
|
||||||
rescue => error
|
rescue StandardError => e
|
||||||
redirect_to admin_users_url, alert: t('admin.users.destroy.error', error: error.message)
|
redirect_to admin_users_url, alert: t('.error', error: e.message)
|
||||||
end
|
end
|
||||||
|
|
||||||
def restore
|
def restore
|
||||||
@user = User.find(params[:id])
|
@user = User.find(params[:id])
|
||||||
@user.restore
|
@user.restore
|
||||||
redirect_to admin_users_url, notice: t('admin.users.restore.notice')
|
redirect_to admin_users_url, notice: t('.notice')
|
||||||
rescue => error
|
rescue StandardError => e
|
||||||
redirect_to admin_users_url, alert: t('admin.users.restore.error', error: error.message)
|
redirect_to admin_users_url, alert: t('.error', error: e.message)
|
||||||
end
|
end
|
||||||
|
|
||||||
def sudo
|
def sudo
|
||||||
|
|
|
@ -4,7 +4,7 @@ class Admin::WorkgroupsController < Admin::BaseController
|
||||||
def index
|
def index
|
||||||
@workgroups = Workgroup.order('name ASC')
|
@workgroups = Workgroup.order('name ASC')
|
||||||
# if somebody uses the search field:
|
# 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)
|
@workgroups = @workgroups.page(params[:page]).per(@per_page)
|
||||||
end
|
end
|
||||||
|
@ -12,8 +12,8 @@ class Admin::WorkgroupsController < Admin::BaseController
|
||||||
def destroy
|
def destroy
|
||||||
@workgroup = Workgroup.find(params[:id])
|
@workgroup = Workgroup.find(params[:id])
|
||||||
@workgroup.destroy
|
@workgroup.destroy
|
||||||
redirect_to admin_workgroups_url, notice: t('admin.workgroups.destroy.notice')
|
redirect_to admin_workgroups_url, notice: t('.notice')
|
||||||
rescue => error
|
rescue StandardError => e
|
||||||
redirect_to admin_workgroups_url, alert: t('admin.workgroups.destroy.error', error: error.message)
|
redirect_to admin_workgroups_url, alert: t('.error', error: e.message)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -20,29 +20,30 @@ class Api::V1::BaseController < ApplicationController
|
||||||
|
|
||||||
def require_ordergroup
|
def require_ordergroup
|
||||||
authenticate
|
authenticate
|
||||||
unless current_ordergroup.present?
|
return if current_ordergroup.present?
|
||||||
raise Api::Errors::PermissionRequired.new('Forbidden, must be in an ordergroup')
|
|
||||||
end
|
raise Api::Errors::PermissionRequired, 'Forbidden, must be in an ordergroup'
|
||||||
end
|
end
|
||||||
|
|
||||||
def require_minimum_balance
|
def require_minimum_balance
|
||||||
minimum_balance = FoodsoftConfig[:minimum_balance] or return
|
minimum_balance = FoodsoftConfig[:minimum_balance] or return
|
||||||
if current_ordergroup.account_balance < minimum_balance
|
return unless current_ordergroup.account_balance < minimum_balance
|
||||||
raise Api::Errors::PermissionRequired.new(t('application.controller.error_minimum_balance', min: minimum_balance))
|
|
||||||
end
|
raise Api::Errors::PermissionRequired, t('application.controller.error_minimum_balance', min: minimum_balance)
|
||||||
end
|
end
|
||||||
|
|
||||||
def require_enough_apples
|
def require_enough_apples
|
||||||
if current_ordergroup.not_enough_apples?
|
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.new(s)
|
s = t('group_orders.messages.not_enough_apples', apples: current_ordergroup.apples,
|
||||||
end
|
stop_ordering_under: FoodsoftConfig[:stop_ordering_under])
|
||||||
|
raise Api::Errors::PermissionRequired, s
|
||||||
end
|
end
|
||||||
|
|
||||||
def require_config_enabled(config)
|
def require_config_enabled(config)
|
||||||
unless FoodsoftConfig[config]
|
return if FoodsoftConfig[config]
|
||||||
raise Api::Errors::PermissionRequired.new(t('application.controller.error_not_enabled', config: config))
|
|
||||||
end
|
raise Api::Errors::PermissionRequired, t('application.controller.error_not_enabled', config: config)
|
||||||
end
|
end
|
||||||
|
|
||||||
def skip_session
|
def skip_session
|
||||||
|
@ -52,12 +53,12 @@ class Api::V1::BaseController < ApplicationController
|
||||||
def not_found_handler(e)
|
def not_found_handler(e)
|
||||||
# remove where-clauses from error message (not suitable for end-users)
|
# remove where-clauses from error message (not suitable for end-users)
|
||||||
msg = e.message.try { |m| m.sub(/\s*\[.*?\]\s*$/, '') } || 'Not found'
|
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
|
end
|
||||||
|
|
||||||
def not_acceptable_handler(e)
|
def not_acceptable_handler(e)
|
||||||
msg = e.message || 'Data not acceptable'
|
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
|
end
|
||||||
|
|
||||||
def doorkeeper_unauthorized_render_options(error:)
|
def doorkeeper_unauthorized_render_options(error:)
|
||||||
|
@ -70,11 +71,11 @@ class Api::V1::BaseController < ApplicationController
|
||||||
|
|
||||||
def permission_required_handler(e)
|
def permission_required_handler(e)
|
||||||
msg = e.message || 'Forbidden, user has no access'
|
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
|
end
|
||||||
|
|
||||||
# @todo something with ApplicationHelper#show_user
|
# @todo something with ApplicationHelper#show_user
|
||||||
def show_user(user = current_user, **options)
|
def show_user(user = current_user, **_options)
|
||||||
user.display
|
user.display
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -16,7 +16,8 @@ class Api::V1::User::FinancialTransactionsController < Api::V1::BaseController
|
||||||
|
|
||||||
def create
|
def create
|
||||||
transaction_type = FinancialTransactionType.find(create_params[:financial_transaction_type_id])
|
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
|
render json: ft
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -4,8 +4,8 @@ class Api::V1::User::GroupOrderArticlesController < Api::V1::BaseController
|
||||||
before_action -> { doorkeeper_authorize! 'group_orders:user' }
|
before_action -> { doorkeeper_authorize! 'group_orders:user' }
|
||||||
|
|
||||||
before_action :require_ordergroup
|
before_action :require_ordergroup
|
||||||
before_action :require_minimum_balance, only: [:create, :update] # destroy is ok
|
before_action :require_minimum_balance, only: %i[create update] # destroy is ok
|
||||||
before_action :require_enough_apples, only: [: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
|
# @todo allow decreasing amounts when minimum balance isn't met
|
||||||
|
|
||||||
def index
|
def index
|
||||||
|
@ -35,7 +35,8 @@ class Api::V1::User::GroupOrderArticlesController < Api::V1::BaseController
|
||||||
goa = nil
|
goa = nil
|
||||||
GroupOrderArticle.transaction do
|
GroupOrderArticle.transaction do
|
||||||
goa = scope_for_update.includes(:group_order_article_quantities).find(params.require(:id))
|
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.order_article.update_results!
|
||||||
goa.group_order.update_price!
|
goa.group_order.update_price!
|
||||||
goa.group_order.update!(updated_by: current_user)
|
goa.group_order.update!(updated_by: current_user)
|
||||||
|
|
|
@ -8,13 +8,13 @@ class Api::V1::User::OrdergroupController < Api::V1::BaseController
|
||||||
financial_overview: {
|
financial_overview: {
|
||||||
account_balance: ordergroup.account_balance.to_f,
|
account_balance: ordergroup.account_balance.to_f,
|
||||||
available_funds: ordergroup.get_available_funds.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,
|
id: c.id,
|
||||||
name: c.display,
|
name: c.display,
|
||||||
amount: ordergroup["sum_of_class_#{c.id}"].to_f
|
amount: ordergroup["sum_of_class_#{c.id}"].to_f
|
||||||
}
|
}
|
||||||
}
|
end
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
|
@ -19,10 +19,10 @@ class ApplicationController < ActionController::Base
|
||||||
private
|
private
|
||||||
|
|
||||||
def set_user_last_activity
|
def set_user_last_activity
|
||||||
if current_user && (session[:last_activity] == nil || session[:last_activity] < 1.minutes.ago)
|
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
|
current_user.update_attribute(:last_activity, Time.now)
|
||||||
end
|
session[:last_activity] = Time.now
|
||||||
end
|
end
|
||||||
|
|
||||||
# Many plugins can be turned on and off on the fly with a `use_` configuration option.
|
# 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
|
end
|
||||||
|
|
||||||
def items_per_page
|
def items_per_page
|
||||||
if params[:per_page] && params[:per_page].to_i > 0 && params[:per_page].to_i <= 500
|
@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
|
params[:per_page].to_i
|
||||||
else
|
else
|
||||||
@per_page = 20
|
20
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Set timezone according to foodcoop preference.
|
# Set timezone according to foodcoop preference.
|
||||||
|
|
|
@ -4,17 +4,17 @@ class ArticleCategoriesController < ApplicationController
|
||||||
before_action :authenticate_article_meta
|
before_action :authenticate_article_meta
|
||||||
|
|
||||||
def create
|
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
|
end
|
||||||
|
|
||||||
def update
|
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
|
end
|
||||||
|
|
||||||
def destroy
|
def destroy
|
||||||
destroy!
|
destroy!
|
||||||
rescue => error
|
rescue StandardError => e
|
||||||
redirect_to article_categories_path, alert: I18n.t('article_categories.destroy.error', message: error.message)
|
redirect_to article_categories_path, alert: I18n.t('article_categories.destroy.error', message: e.message)
|
||||||
end
|
end
|
||||||
|
|
||||||
protected
|
protected
|
||||||
|
|
|
@ -2,24 +2,24 @@ class ArticlesController < ApplicationController
|
||||||
before_action :authenticate_article_meta, :find_supplier
|
before_action :authenticate_article_meta, :find_supplier
|
||||||
|
|
||||||
def index
|
def index
|
||||||
if params['sort']
|
sort = if params['sort']
|
||||||
sort = case params['sort']
|
case params['sort']
|
||||||
when "name" then "articles.name"
|
when 'name' then 'articles.name'
|
||||||
when "unit" then "articles.unit"
|
when 'unit' then 'articles.unit'
|
||||||
when "article_category" then "article_categories.name"
|
when 'article_category' then 'article_categories.name'
|
||||||
when "note" then "articles.note"
|
when 'note' then 'articles.note'
|
||||||
when "availability" then "articles.availability"
|
when 'availability' then 'articles.availability'
|
||||||
when "name_reverse" then "articles.name DESC"
|
when 'name_reverse' then 'articles.name DESC'
|
||||||
when "unit_reverse" then "articles.unit DESC"
|
when 'unit_reverse' then 'articles.unit DESC'
|
||||||
when "article_category_reverse" then "article_categories.name DESC"
|
when 'article_category_reverse' then 'article_categories.name DESC'
|
||||||
when "note_reverse" then "articles.note DESC"
|
when 'note_reverse' then 'articles.note DESC'
|
||||||
when "availability_reverse" then "articles.availability DESC"
|
when 'availability_reverse' then 'articles.availability DESC'
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
sort = "article_categories.name, articles.name"
|
'article_categories.name, articles.name'
|
||||||
end
|
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?
|
if request.format.csv?
|
||||||
send_data ArticlesCsv.new(@articles, encoding: 'utf-8').to_csv, filename: 'articles.csv', type: 'text/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|
|
respond_to do |format|
|
||||||
format.html
|
format.html
|
||||||
format.js { render :layout => false }
|
format.js { render layout: false }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def new
|
def new
|
||||||
@article = @supplier.articles.build(:tax => FoodsoftConfig[:tax_default])
|
@article = @supplier.articles.build(tax: FoodsoftConfig[:tax_default])
|
||||||
render :layout => false
|
render layout: false
|
||||||
end
|
end
|
||||||
|
|
||||||
def copy
|
def copy
|
||||||
@article = @supplier.articles.find(params[:article_id]).dup
|
@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
|
end
|
||||||
|
|
||||||
def create
|
def create
|
||||||
@article = Article.new(params[:article])
|
@article = Article.new(params[:article])
|
||||||
if @article.valid? && @article.save
|
if @article.valid? && @article.save
|
||||||
render :layout => false
|
render layout: false
|
||||||
else
|
else
|
||||||
render :action => 'new', :layout => false
|
render action: 'new', layout: false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def edit
|
|
||||||
@article = Article.find(params[:id])
|
|
||||||
render :action => 'new', :layout => false
|
|
||||||
end
|
|
||||||
|
|
||||||
# Updates one Article and highlights the line if succeded
|
# Updates one Article and highlights the line if succeded
|
||||||
def update
|
def update
|
||||||
@article = Article.find(params[:id])
|
@article = Article.find(params[:id])
|
||||||
|
|
||||||
if @article.update(params[:article])
|
if @article.update(params[:article])
|
||||||
render :layout => false
|
render layout: false
|
||||||
else
|
else
|
||||||
render :action => 'new', :layout => false
|
render action: 'new', layout: false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -75,7 +75,7 @@ class ArticlesController < ApplicationController
|
||||||
def destroy
|
def destroy
|
||||||
@article = Article.find(params[:id])
|
@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
|
@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
|
end
|
||||||
|
|
||||||
# Renders a form for editing all articles from a supplier
|
# Renders a form for editing all articles from a supplier
|
||||||
|
@ -87,19 +87,17 @@ class ArticlesController < ApplicationController
|
||||||
def update_all
|
def update_all
|
||||||
invalid_articles = false
|
invalid_articles = false
|
||||||
|
|
||||||
begin
|
Article.transaction do
|
||||||
Article.transaction do
|
if params[:articles].present?
|
||||||
unless params[:articles].blank?
|
# Update other article attributes...
|
||||||
# Update other article attributes...
|
@articles = Article.find(params[:articles].keys)
|
||||||
@articles = Article.find(params[:articles].keys)
|
@articles.each do |article|
|
||||||
@articles.each do |article|
|
unless article.update(params[:articles][article.id.to_s])
|
||||||
unless article.update(params[:articles][article.id.to_s])
|
invalid_articles ||= true # Remember that there are validation errors
|
||||||
invalid_articles = true unless invalid_articles # Remember that there are validation errors
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
raise ActiveRecord::Rollback if invalid_articles # Rollback all changes
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
raise ActiveRecord::Rollback if invalid_articles # Rollback all changes
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -134,16 +132,15 @@ class ArticlesController < ApplicationController
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
# action succeded
|
# action succeded
|
||||||
redirect_to supplier_articles_url(@supplier, :per_page => params[:per_page])
|
redirect_to supplier_articles_url(@supplier, per_page: params[:per_page])
|
||||||
rescue => error
|
rescue StandardError => e
|
||||||
redirect_to supplier_articles_url(@supplier, :per_page => params[:per_page]),
|
redirect_to supplier_articles_url(@supplier, per_page: params[:per_page]),
|
||||||
:alert => I18n.t('errors.general_msg', :msg => error)
|
alert: I18n.t('errors.general_msg', msg: e)
|
||||||
end
|
end
|
||||||
|
|
||||||
# lets start with parsing articles from uploaded file, yeah
|
# lets start with parsing articles from uploaded file, yeah
|
||||||
# Renders the upload form
|
# Renders the upload form
|
||||||
def upload
|
def upload; end
|
||||||
end
|
|
||||||
|
|
||||||
# Update articles from a spreadsheet
|
# Update articles from a spreadsheet
|
||||||
def parse_upload
|
def parse_upload
|
||||||
|
@ -151,13 +148,15 @@ class ArticlesController < ApplicationController
|
||||||
options = { filename: uploaded_file.original_filename }
|
options = { filename: uploaded_file.original_filename }
|
||||||
options[:outlist_absent] = (params[:articles]['outlist_absent'] == '1')
|
options[:outlist_absent] = (params[:articles]['outlist_absent'] == '1')
|
||||||
options[:convert_units] = (params[:articles]['convert_units'] == '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?
|
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
|
end
|
||||||
@ignored_article_count = 0
|
@ignored_article_count = 0
|
||||||
rescue => error
|
rescue StandardError => e
|
||||||
redirect_to upload_supplier_articles_path(@supplier), :alert => I18n.t('errors.general_msg', :msg => error.message)
|
redirect_to upload_supplier_articles_path(@supplier), alert: I18n.t('errors.general_msg', msg: e.message)
|
||||||
end
|
end
|
||||||
|
|
||||||
# sync all articles with the external database
|
# sync all articles with the external database
|
||||||
|
@ -165,13 +164,14 @@ class ArticlesController < ApplicationController
|
||||||
def sync
|
def sync
|
||||||
# check if there is an shared_supplier
|
# check if there is an shared_supplier
|
||||||
unless @supplier.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
|
end
|
||||||
# sync articles against external database
|
# sync articles against external database
|
||||||
@updated_article_pairs, @outlisted_articles, @new_articles = @supplier.sync_all
|
@updated_article_pairs, @outlisted_articles, @new_articles = @supplier.sync_all
|
||||||
if @updated_article_pairs.empty? && @outlisted_articles.empty? && @new_articles.empty?
|
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
|
redirect_to supplier_articles_path(@supplier), notice: I18n.t('articles.controller.sync.notice')
|
||||||
end
|
end
|
||||||
|
|
||||||
# Updates, deletes articles when upload or sync form is submitted
|
# Updates, deletes articles when upload or sync form is submitted
|
||||||
|
@ -186,7 +186,7 @@ class ArticlesController < ApplicationController
|
||||||
# delete articles
|
# delete articles
|
||||||
begin
|
begin
|
||||||
@outlisted_articles.each(&:mark_as_deleted)
|
@outlisted_articles.each(&:mark_as_deleted)
|
||||||
rescue
|
rescue StandardError
|
||||||
# raises an exception when used in current order
|
# raises an exception when used in current order
|
||||||
has_error = true
|
has_error = true
|
||||||
end
|
end
|
||||||
|
@ -198,15 +198,15 @@ class ArticlesController < ApplicationController
|
||||||
raise ActiveRecord::Rollback if has_error
|
raise ActiveRecord::Rollback if has_error
|
||||||
end
|
end
|
||||||
|
|
||||||
if !has_error
|
if has_error
|
||||||
redirect_to supplier_articles_path(@supplier), notice: I18n.t('articles.controller.update_sync.notice')
|
|
||||||
else
|
|
||||||
@updated_article_pairs = @updated_articles.map do |article|
|
@updated_article_pairs = @updated_articles.map do |article|
|
||||||
orig_article = Article.find(article.id)
|
orig_article = Article.find(article.id)
|
||||||
[article, orig_article.unequal_attributes(article)]
|
[article, orig_article.unequal_attributes(article)]
|
||||||
end
|
end
|
||||||
flash.now.alert = I18n.t('articles.controller.error_invalid')
|
flash.now.alert = I18n.t('articles.controller.error_invalid')
|
||||||
render params[:from_action] == 'sync' ? :sync : :parse_upload
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -218,18 +218,18 @@ class ArticlesController < ApplicationController
|
||||||
q[:name_cont_all] = params.fetch(:name_cont_all_joined, '').split(' ')
|
q[:name_cont_all] = params.fetch(:name_cont_all_joined, '').split(' ')
|
||||||
search = @supplier.shared_supplier.shared_articles.ransack(q)
|
search = @supplier.shared_supplier.shared_articles.ransack(q)
|
||||||
@articles = search.result.page(params[:page]).per(10)
|
@articles = search.result.page(params[:page]).per(10)
|
||||||
render :layout => false
|
render layout: false
|
||||||
end
|
end
|
||||||
|
|
||||||
# fills a form whith values of the selected shared_article
|
# 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
|
# when the direct parameter is set and the article is valid, it is imported directly
|
||||||
def import
|
def import
|
||||||
@article = SharedArticle.find(params[:shared_article_id]).build_new_article(@supplier)
|
@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?
|
@article.article_category_id = params[:article_category_id] if params[:article_category_id].present?
|
||||||
if params[:direct] && !params[:article_category_id].blank? && @article.valid? && @article.save
|
if params[:direct] && params[:article_category_id].present? && @article.valid? && @article.save
|
||||||
render :action => 'create', :layout => false
|
render action: 'create', layout: false
|
||||||
else
|
else
|
||||||
render :action => 'new', :layout => false
|
render action: 'new', layout: false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -9,15 +9,19 @@ module Concerns::Auth
|
||||||
|
|
||||||
def current_user
|
def current_user
|
||||||
# check if there is a valid session and return the logged-in user (its object)
|
# check if there is a valid session and return the logged-in user (its object)
|
||||||
if session[:user_id] && params[:foodcoop]
|
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
|
# for shared-host installations. check if the cookie-subdomain fits to request.
|
||||||
end
|
@current_user ||= User.undeleted.find_by_id(session[:user_id]) if session[:scope] == FoodsoftConfig.scope
|
||||||
end
|
end
|
||||||
|
|
||||||
def deny_access
|
def deny_access
|
||||||
session[:return_to] = request.original_url
|
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
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
@ -47,12 +51,7 @@ module Concerns::Auth
|
||||||
|
|
||||||
def authenticate(role = 'any')
|
def authenticate(role = 'any')
|
||||||
# Attempt to retrieve authenticated user from controller instance or session...
|
# Attempt to retrieve authenticated user from controller instance or session...
|
||||||
if !current_user
|
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
|
|
||||||
# We have an authenticated user, now check role...
|
# We have an authenticated user, now check role...
|
||||||
# Roles gets the user through his memberships.
|
# Roles gets the user through his memberships.
|
||||||
hasRole = case role
|
hasRole = case role
|
||||||
|
@ -73,6 +72,11 @@ module Concerns::Auth
|
||||||
else
|
else
|
||||||
deny_access
|
deny_access
|
||||||
end
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -116,13 +120,13 @@ module Concerns::Auth
|
||||||
# if fails the user will redirected to startpage
|
# if fails the user will redirected to startpage
|
||||||
def authenticate_membership_or_admin(group_id = params[:id])
|
def authenticate_membership_or_admin(group_id = params[:id])
|
||||||
@group = Group.find(group_id)
|
@group = Group.find(group_id)
|
||||||
unless @group.member?(@current_user) || @current_user.role_admin?
|
return if @group.member?(@current_user) || @current_user.role_admin?
|
||||||
redirect_to root_path, alert: I18n.t('application.controller.error_members_only')
|
|
||||||
end
|
redirect_to root_path, alert: I18n.t('application.controller.error_members_only')
|
||||||
end
|
end
|
||||||
|
|
||||||
def authenticate_or_token(prefix, role = 'any')
|
def authenticate_or_token(prefix, role = 'any')
|
||||||
if not params[:token].blank?
|
if params[:token].present?
|
||||||
begin
|
begin
|
||||||
TokenVerifier.new(prefix).verify(params[:token])
|
TokenVerifier.new(prefix).verify(params[:token])
|
||||||
rescue ActiveSupport::MessageVerifier::InvalidSignature
|
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.
|
# Make sure that at least one the given OAuth scopes is valid for the current user's permissions.
|
||||||
# @raise Api::Errors::PermissionsRequired
|
# @raise Api::Errors::PermissionsRequired
|
||||||
def doorkeeper_authorize_roles!(*scopes)
|
def doorkeeper_authorize_roles!(*scopes)
|
||||||
unless scopes.any? { |scope| doorkeeper_scope_permitted?(scope) }
|
return if scopes.any? { |scope| doorkeeper_scope_permitted?(scope) }
|
||||||
raise Api::Errors::PermissionRequired.new('Forbidden, no permission')
|
|
||||||
end
|
raise Api::Errors::PermissionRequired, 'Forbidden, no permission'
|
||||||
end
|
end
|
||||||
|
|
||||||
# Check whether a given OAuth scope is permitted for the current user.
|
# Check whether a given OAuth scope is permitted for the current user.
|
||||||
|
@ -48,9 +48,7 @@ module Concerns::AuthApi
|
||||||
def doorkeeper_scope_permitted?(scope)
|
def doorkeeper_scope_permitted?(scope)
|
||||||
scope_parts = scope.split(':')
|
scope_parts = scope.split(':')
|
||||||
# user sub-scopes like +config:user+ are always permitted
|
# user sub-scopes like +config:user+ are always permitted
|
||||||
if scope_parts.last == 'user'
|
return true if scope_parts.last == 'user'
|
||||||
return true
|
|
||||||
end
|
|
||||||
|
|
||||||
case scope_parts.first
|
case scope_parts.first
|
||||||
when 'user' then return true # access to the current user's own profile
|
when 'user' then return true # access to the current user's own profile
|
||||||
|
@ -64,8 +62,8 @@ module Concerns::AuthApi
|
||||||
end
|
end
|
||||||
|
|
||||||
case scope
|
case scope
|
||||||
when 'orders:read' then return true
|
when 'orders:read' then true
|
||||||
when 'orders:write' then return current_user.role_orders?
|
when 'orders:write' then current_user.role_orders?
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -24,12 +24,12 @@ module Concerns::FoodcoopScope
|
||||||
elsif FoodsoftConfig.allowed_foodcoop? foodcoop
|
elsif FoodsoftConfig.allowed_foodcoop? foodcoop
|
||||||
FoodsoftConfig.select_foodcoop foodcoop
|
FoodsoftConfig.select_foodcoop foodcoop
|
||||||
else
|
else
|
||||||
raise ActionController::RoutingError.new 'Foodcoop Not Found'
|
raise ActionController::RoutingError, 'Foodcoop Not Found'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Always stay in foodcoop url scope
|
# Always stay in foodcoop url scope
|
||||||
def default_url_options(options = {})
|
def default_url_options(_options = {})
|
||||||
super().merge({ foodcoop: FoodsoftConfig.scope })
|
super().merge({ foodcoop: FoodsoftConfig.scope })
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -18,7 +18,7 @@ module Concerns::Locale
|
||||||
end
|
end
|
||||||
|
|
||||||
def browser_language
|
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
|
end
|
||||||
|
|
||||||
def default_language
|
def default_language
|
||||||
|
@ -30,7 +30,7 @@ module Concerns::Locale
|
||||||
def select_language_according_to_priority
|
def select_language_according_to_priority
|
||||||
language = explicitly_requested_language || session_language || user_settings_language
|
language = explicitly_requested_language || session_language || user_settings_language
|
||||||
language ||= browser_language unless FoodsoftConfig[:ignore_browser_locale]
|
language ||= browser_language unless FoodsoftConfig[:ignore_browser_locale]
|
||||||
language.presence&.to_sym unless language.blank?
|
language.presence&.to_sym if language.present?
|
||||||
end
|
end
|
||||||
|
|
||||||
def available_locales
|
def available_locales
|
||||||
|
@ -38,11 +38,11 @@ module Concerns::Locale
|
||||||
end
|
end
|
||||||
|
|
||||||
def set_locale
|
def set_locale
|
||||||
if available_locales.include?(select_language_according_to_priority)
|
::I18n.locale = if available_locales.include?(select_language_according_to_priority)
|
||||||
::I18n.locale = select_language_according_to_priority
|
select_language_according_to_priority
|
||||||
else
|
else
|
||||||
::I18n.locale = default_language
|
default_language
|
||||||
end
|
end
|
||||||
|
|
||||||
locale = session[:locale] = ::I18n.locale
|
locale = session[:locale] = ::I18n.locale
|
||||||
logger.info("Set locale to #{locale}")
|
logger.info("Set locale to #{locale}")
|
||||||
|
|
17
app/controllers/concerns/send_group_order_invoice_pdf.rb
Normal file
17
app/controllers/concerns/send_group_order_invoice_pdf.rb
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
module Concerns::SendGroupOrderInvoicePdf
|
||||||
|
extend ActiveSupport::Concern
|
||||||
|
|
||||||
|
protected
|
||||||
|
|
||||||
|
def create_invoice_pdf(group_order_invoice)
|
||||||
|
invoice_data = group_order_invoice.load_data_for_invoice
|
||||||
|
invoice_data[:title] = t('documents.group_order_invoice_pdf.title', supplier: invoice_data[:supplier])
|
||||||
|
invoice_data[:no_footer] = true
|
||||||
|
GroupOrderInvoicePdf.new invoice_data
|
||||||
|
end
|
||||||
|
|
||||||
|
def send_group_order_invoice_pdf(group_order_invoice)
|
||||||
|
pdf = create_invoice_pdf(group_order_invoice)
|
||||||
|
send_data pdf.to_pdf, filename: pdf.filename, type: 'application/pdf'
|
||||||
|
end
|
||||||
|
end
|
|
@ -3,7 +3,7 @@ module Concerns::SendOrderPdf
|
||||||
|
|
||||||
protected
|
protected
|
||||||
|
|
||||||
def send_order_pdf order, document
|
def send_order_pdf(order, document)
|
||||||
klass = case document
|
klass = case document
|
||||||
when 'groups' then OrderByGroups
|
when 'groups' then OrderByGroups
|
||||||
when 'articles' then OrderByArticles
|
when 'articles' then OrderByArticles
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
class DeliveriesController < ApplicationController
|
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
|
def index
|
||||||
@deliveries = @supplier.deliveries.order('date DESC')
|
@deliveries = @supplier.deliveries.order('date DESC')
|
||||||
|
@ -15,6 +15,10 @@ class DeliveriesController < ApplicationController
|
||||||
@delivery.date = Date.today # TODO: move to model/database
|
@delivery.date = Date.today # TODO: move to model/database
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def edit
|
||||||
|
@delivery = Delivery.find(params[:id])
|
||||||
|
end
|
||||||
|
|
||||||
def create
|
def create
|
||||||
@delivery = Delivery.new(params[:delivery])
|
@delivery = Delivery.new(params[:delivery])
|
||||||
|
|
||||||
|
@ -22,14 +26,10 @@ class DeliveriesController < ApplicationController
|
||||||
flash[:notice] = I18n.t('deliveries.create.notice')
|
flash[:notice] = I18n.t('deliveries.create.notice')
|
||||||
redirect_to [@supplier, @delivery]
|
redirect_to [@supplier, @delivery]
|
||||||
else
|
else
|
||||||
render :action => "new"
|
render action: 'new'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def edit
|
|
||||||
@delivery = Delivery.find(params[:id])
|
|
||||||
end
|
|
||||||
|
|
||||||
def update
|
def update
|
||||||
@delivery = Delivery.find(params[:id])
|
@delivery = Delivery.find(params[:id])
|
||||||
|
|
||||||
|
@ -37,7 +37,7 @@ class DeliveriesController < ApplicationController
|
||||||
flash[:notice] = I18n.t('deliveries.update.notice')
|
flash[:notice] = I18n.t('deliveries.update.notice')
|
||||||
redirect_to [@supplier, @delivery]
|
redirect_to [@supplier, @delivery]
|
||||||
else
|
else
|
||||||
render :action => "edit"
|
render action: 'edit'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -52,18 +52,18 @@ class DeliveriesController < ApplicationController
|
||||||
def add_stock_change
|
def add_stock_change
|
||||||
@stock_change = StockChange.new
|
@stock_change = StockChange.new
|
||||||
@stock_change.stock_article = StockArticle.find(params[:stock_article_id])
|
@stock_change.stock_article = StockArticle.find(params[:stock_article_id])
|
||||||
render :layout => false
|
render layout: false
|
||||||
end
|
end
|
||||||
|
|
||||||
def form_on_stock_article_create # See publish/subscribe design pattern in /doc.
|
def form_on_stock_article_create # See publish/subscribe design pattern in /doc.
|
||||||
@stock_article = StockArticle.find(params[:id])
|
@stock_article = StockArticle.find(params[:id])
|
||||||
|
|
||||||
render :layout => false
|
render layout: false
|
||||||
end
|
end
|
||||||
|
|
||||||
def form_on_stock_article_update # See publish/subscribe design pattern in /doc.
|
def form_on_stock_article_update # See publish/subscribe design pattern in /doc.
|
||||||
@stock_article = StockArticle.find(params[:id])
|
@stock_article = StockArticle.find(params[:id])
|
||||||
|
|
||||||
render :layout => false
|
render layout: false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,13 +1,12 @@
|
||||||
class FeedbackController < ApplicationController
|
class FeedbackController < ApplicationController
|
||||||
def new
|
def new; end
|
||||||
end
|
|
||||||
|
|
||||||
def create
|
def create
|
||||||
if params[:message].present?
|
if params[:message].present?
|
||||||
Mailer.feedback(current_user, params[:message]).deliver_now
|
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
|
else
|
||||||
render :action => 'new'
|
render action: 'new'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -5,7 +5,7 @@ class Finance::BalancingController < Finance::BaseController
|
||||||
|
|
||||||
def new
|
def new
|
||||||
@order = Order.find(params[:order_id])
|
@order = Order.find(params[:order_id])
|
||||||
flash.now.alert = t('finance.balancing.new.alert') if @order.closed?
|
flash.now.alert = t('finance.balancing.new.alert') if @order.closed? && flash[:alert].blank?
|
||||||
@comments = @order.comments
|
@comments = @order.comments
|
||||||
|
|
||||||
@articles = @order.order_articles.ordered_or_member.includes(:article, :article_price,
|
@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'
|
sort_param = params['sort'] || 'name'
|
||||||
@articles = case sort_param
|
@articles = case sort_param
|
||||||
when 'name' then
|
when 'name'
|
||||||
@articles.order('articles.name ASC')
|
@articles.order('articles.name ASC')
|
||||||
when 'name_reverse' then
|
when 'name_reverse'
|
||||||
@articles.order('articles.name DESC')
|
@articles.order('articles.name DESC')
|
||||||
when 'order_number' then
|
when 'order_number'
|
||||||
@articles.order('articles.order_number ASC')
|
@articles.order('articles.order_number ASC')
|
||||||
when 'order_number_reverse' then
|
when 'order_number_reverse'
|
||||||
@articles.order('articles.order_number DESC')
|
@articles.order('articles.order_number DESC')
|
||||||
else
|
else
|
||||||
@articles
|
@articles
|
||||||
|
@ -31,13 +31,13 @@ class Finance::BalancingController < Finance::BaseController
|
||||||
def new_on_order_article_create # See publish/subscribe design pattern in /doc.
|
def new_on_order_article_create # See publish/subscribe design pattern in /doc.
|
||||||
@order_article = OrderArticle.find(params[:order_article_id])
|
@order_article = OrderArticle.find(params[:order_article_id])
|
||||||
|
|
||||||
render :layout => false
|
render layout: false
|
||||||
end
|
end
|
||||||
|
|
||||||
def new_on_order_article_update # See publish/subscribe design pattern in /doc.
|
def new_on_order_article_update # See publish/subscribe design pattern in /doc.
|
||||||
@order_article = OrderArticle.find(params[:order_article_id])
|
@order_article = OrderArticle.find(params[:order_article_id])
|
||||||
|
|
||||||
render :layout => false
|
render layout: false
|
||||||
end
|
end
|
||||||
|
|
||||||
def update_summary
|
def update_summary
|
||||||
|
@ -46,29 +46,29 @@ class Finance::BalancingController < Finance::BaseController
|
||||||
|
|
||||||
def edit_note
|
def edit_note
|
||||||
@order = Order.find(params[:id])
|
@order = Order.find(params[:id])
|
||||||
render :layout => false
|
render layout: false
|
||||||
end
|
end
|
||||||
|
|
||||||
def update_note
|
def update_note
|
||||||
@order = Order.find(params[:id])
|
@order = Order.find(params[:id])
|
||||||
if @order.update(params[:order])
|
if @order.update(params[:order])
|
||||||
render :layout => false
|
render layout: false
|
||||||
else
|
else
|
||||||
render :action => :edit_note, :layout => false
|
render action: :edit_note, layout: false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def edit_transport
|
def edit_transport
|
||||||
@order = Order.find(params[:id])
|
@order = Order.find(params[:id])
|
||||||
render :layout => false
|
render layout: false
|
||||||
end
|
end
|
||||||
|
|
||||||
def update_transport
|
def update_transport
|
||||||
@order = Order.find(params[:id])
|
@order = Order.find(params[:id])
|
||||||
@order.update!(params[:order])
|
@order.update!(params[:order])
|
||||||
redirect_to new_finance_order_path(order_id: @order.id)
|
redirect_to new_finance_order_path(order_id: @order.id)
|
||||||
rescue => error
|
rescue StandardError => e
|
||||||
redirect_to new_finance_order_path(order_id: @order.id), alert: t('errors.general_msg', msg: error.message)
|
redirect_to new_finance_order_path(order_id: @order.id), alert: t('errors.general_msg', msg: e.message)
|
||||||
end
|
end
|
||||||
|
|
||||||
# before the order will booked, a view lists all Ordergroups and its order_prices
|
# before the order will booked, a view lists all Ordergroups and its order_prices
|
||||||
|
@ -81,18 +81,33 @@ class Finance::BalancingController < Finance::BaseController
|
||||||
@order = Order.find(params[:id])
|
@order = Order.find(params[:id])
|
||||||
@type = FinancialTransactionType.find_by_id(params.permit(:type)[:type])
|
@type = FinancialTransactionType.find_by_id(params.permit(:type)[:type])
|
||||||
@order.close!(@current_user, @type)
|
@order.close!(@current_user, @type)
|
||||||
redirect_to finance_order_index_url, notice: t('finance.balancing.close.notice')
|
note = t('finance.balancing.close.notice')
|
||||||
|
if @order.closed?
|
||||||
|
alert = t('finance.balancing.close.alert')
|
||||||
|
if FoodsoftConfig[:group_order_invoices]&.[](:use_automatic_invoices)
|
||||||
|
@order.group_orders.each do |go|
|
||||||
|
alert = t('finance.balancing.close.settings_not_set')
|
||||||
|
goi = GroupOrderInvoice.find_or_create_by!(group_order_id: go.id)
|
||||||
|
if goi.save!
|
||||||
|
NotifyGroupOrderInvoiceJob.perform_later(goi)
|
||||||
|
note = t('finance.balancing.close.notice_mail')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
alert ||= t('finance.balancing.close.alert')
|
||||||
|
redirect_to finance_order_index_url, notice: note
|
||||||
rescue => error
|
rescue => error
|
||||||
redirect_to new_finance_order_url(order_id: @order.id), alert: t('finance.balancing.close.alert', message: error.message)
|
redirect_to new_finance_order_url(order_id: @order.id), notice: note, alert: alert, msg: error.message
|
||||||
end
|
end
|
||||||
|
|
||||||
# Close the order directly, without automaticly updating ordergroups account balances
|
# Close the order directly, without automaticly updating ordergroups account balances
|
||||||
def close_direct
|
def close_direct
|
||||||
@order = Order.find(params[:id])
|
@order = Order.find(params[:id])
|
||||||
@order.close_direct!(@current_user)
|
@order.close_direct!(@current_user)
|
||||||
redirect_to finance_order_index_url, notice: t('finance.balancing.close_direct.notice')
|
redirect_to finance_order_index_url, notice: t('.notice')
|
||||||
rescue => error
|
rescue StandardError => e
|
||||||
redirect_to finance_order_index_url, alert: t('finance.balancing.close_direct.alert', message: error.message)
|
redirect_to finance_order_index_url, alert: t('.alert', message: e.message)
|
||||||
end
|
end
|
||||||
|
|
||||||
def close_all_direct_with_invoice
|
def close_all_direct_with_invoice
|
||||||
|
@ -103,8 +118,8 @@ class Finance::BalancingController < Finance::BaseController
|
||||||
count += 1
|
count += 1
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
redirect_to finance_order_index_url, notice: t('finance.balancing.close_all_direct_with_invoice.notice', count: count)
|
redirect_to finance_order_index_url, notice: t('.notice', count: count)
|
||||||
rescue => error
|
rescue StandardError => e
|
||||||
redirect_to finance_order_index_url, alert: t('errors.general_msg', msg: error.message)
|
redirect_to finance_order_index_url, alert: t('errors.general_msg', msg: e.message)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -8,8 +8,8 @@ class Finance::BankAccountsController < Finance::BaseController
|
||||||
@bank_account = BankAccount.find(params[:id])
|
@bank_account = BankAccount.find(params[:id])
|
||||||
count = @bank_account.assign_unlinked_transactions
|
count = @bank_account.assign_unlinked_transactions
|
||||||
redirect_to finance_bank_account_transactions_url(@bank_account), notice: t('.notice', count: count)
|
redirect_to finance_bank_account_transactions_url(@bank_account), notice: t('.notice', count: count)
|
||||||
rescue => error
|
rescue StandardError => e
|
||||||
redirect_to finance_bank_account_transactions_url(@bank_account), alert: t('errors.general_msg', msg: error.message)
|
redirect_to finance_bank_account_transactions_url(@bank_account), alert: t('errors.general_msg', msg: e.message)
|
||||||
end
|
end
|
||||||
|
|
||||||
def import
|
def import
|
||||||
|
@ -33,8 +33,8 @@ class Finance::BankAccountsController < Finance::BaseController
|
||||||
end
|
end
|
||||||
|
|
||||||
needs_redirect = ok
|
needs_redirect = ok
|
||||||
rescue => error
|
rescue StandardError => e
|
||||||
flash.alert = t('errors.general_msg', msg: error.message)
|
flash.alert = t('errors.general_msg', msg: e.message)
|
||||||
needs_redirect = true
|
needs_redirect = true
|
||||||
ensure
|
ensure
|
||||||
return unless needs_redirect
|
return unless needs_redirect
|
||||||
|
|
|
@ -3,26 +3,30 @@ class Finance::BankTransactionsController < ApplicationController
|
||||||
inherit_resources
|
inherit_resources
|
||||||
|
|
||||||
def index
|
def index
|
||||||
if params["sort"]
|
sort = if params['sort']
|
||||||
sort = case params["sort"]
|
case params['sort']
|
||||||
when "date" then "date"
|
when 'date' then 'date'
|
||||||
when "amount" then "amount"
|
when 'amount' then 'amount'
|
||||||
when "financial_link" then "financial_link_id"
|
when 'financial_link' then 'financial_link_id'
|
||||||
when "date_reverse" then "date DESC"
|
when 'date_reverse' then 'date DESC'
|
||||||
when "amount_reverse" then "amount DESC"
|
when 'amount_reverse' then 'amount DESC'
|
||||||
when "financial_link_reverse" then "financial_link_id DESC"
|
when 'financial_link_reverse' then 'financial_link_id DESC'
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
sort = "date DESC"
|
'date DESC'
|
||||||
end
|
end
|
||||||
|
|
||||||
@bank_account = BankAccount.find(params[:bank_account_id])
|
@bank_account = BankAccount.find(params[:bank_account_id])
|
||||||
@bank_transactions_all = @bank_account.bank_transactions.order(sort).includes(:financial_link)
|
@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)
|
@bank_transactions = @bank_transactions_all.page(params[:page]).per(@per_page)
|
||||||
|
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
format.js; format.html { render }
|
format.js
|
||||||
|
format.html { render }
|
||||||
format.csv do
|
format.csv do
|
||||||
send_data BankTransactionsCsv.new(@bank_transactions_all).to_csv, filename: 'transactions.csv', type: 'text/csv'
|
send_data BankTransactionsCsv.new(@bank_transactions_all).to_csv, filename: 'transactions.csv', type: 'text/csv'
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
class Finance::FinancialLinksController < Finance::BaseController
|
class Finance::FinancialLinksController < Finance::BaseController
|
||||||
before_action :find_financial_link, except: [:create, :incomplete]
|
before_action :find_financial_link, except: %i[create incomplete]
|
||||||
|
|
||||||
def show
|
def show
|
||||||
@items = @financial_link.bank_transactions.map do |bt|
|
@items = @financial_link.bank_transactions.map do |bt|
|
||||||
|
@ -37,7 +37,7 @@ class Finance::FinancialLinksController < Finance::BaseController
|
||||||
|
|
||||||
def create
|
def create
|
||||||
@financial_link = FinancialLink.first_unused_or_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 = BankTransaction.find(params[:bank_transaction])
|
||||||
bank_transaction.update_attribute :financial_link, @financial_link
|
bank_transaction.update_attribute :financial_link, @financial_link
|
||||||
end
|
end
|
||||||
|
@ -72,14 +72,16 @@ class Finance::FinancialLinksController < Finance::BaseController
|
||||||
|
|
||||||
def create_financial_transaction
|
def create_financial_transaction
|
||||||
financial_transaction = FinancialTransaction.new(financial_transaction_params)
|
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')
|
redirect_to finance_link_url(@financial_link), notice: t('.notice')
|
||||||
rescue => error
|
rescue StandardError => e
|
||||||
redirect_to finance_link_url(@financial_link), alert: t('errors.general_msg', msg: error)
|
redirect_to finance_link_url(@financial_link), alert: t('errors.general_msg', msg: e)
|
||||||
end
|
end
|
||||||
|
|
||||||
def index_financial_transaction
|
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
|
end
|
||||||
|
|
||||||
def add_financial_transaction
|
def add_financial_transaction
|
||||||
|
@ -123,7 +125,7 @@ class Finance::FinancialLinksController < Finance::BaseController
|
||||||
end
|
end
|
||||||
|
|
||||||
def find_best_fitting_ordergroup_id_for_financial_link(financial_link_id)
|
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 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}
|
JOIN bank_transactions b ON a.iban = b.iban AND b.financial_link_id = #{financial_link_id.to_i}
|
||||||
SQL
|
SQL
|
||||||
|
|
|
@ -1,24 +1,24 @@
|
||||||
class Finance::FinancialTransactionsController < ApplicationController
|
class Finance::FinancialTransactionsController < ApplicationController
|
||||||
before_action :authenticate_finance
|
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
|
inherit_resources
|
||||||
# belongs_to :ordergroup
|
# belongs_to :ordergroup
|
||||||
|
|
||||||
def index
|
def index
|
||||||
if params['sort']
|
sort = if params['sort']
|
||||||
sort = case params['sort']
|
case params['sort']
|
||||||
when "date" then "created_on"
|
when 'date' then 'created_on'
|
||||||
when "note" then "note"
|
when 'note' then 'note'
|
||||||
when "amount" then "amount"
|
when 'amount' then 'amount'
|
||||||
when "date_reverse" then "created_on DESC"
|
when 'date_reverse' then 'created_on DESC'
|
||||||
when "note_reverse" then "note DESC"
|
when 'note_reverse' then 'note DESC'
|
||||||
when "amount_reverse" then "amount DESC"
|
when 'amount_reverse' then 'amount DESC'
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
sort = "created_on DESC"
|
'created_on DESC'
|
||||||
end
|
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 = @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.visible unless params[:show_hidden]
|
||||||
@financial_transactions_all = @financial_transactions_all.where(ordergroup_id: @ordergroup.id) if @ordergroup
|
@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)
|
@financial_transactions = @financial_transactions_all.page(params[:page]).per(@per_page)
|
||||||
|
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
format.js; format.html { render }
|
format.js
|
||||||
|
format.html { render }
|
||||||
format.csv do
|
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
|
end
|
||||||
end
|
end
|
||||||
|
@ -38,11 +40,11 @@ class Finance::FinancialTransactionsController < ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
def new
|
def new
|
||||||
if @ordergroup
|
@financial_transaction = if @ordergroup
|
||||||
@financial_transaction = @ordergroup.financial_transactions.build
|
@ordergroup.financial_transactions.build
|
||||||
else
|
else
|
||||||
@financial_transaction = FinancialTransaction.new
|
FinancialTransaction.new
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def create
|
def create
|
||||||
|
@ -53,16 +55,18 @@ class Finance::FinancialTransactionsController < ApplicationController
|
||||||
else
|
else
|
||||||
@financial_transaction.save!
|
@financial_transaction.save!
|
||||||
end
|
end
|
||||||
redirect_to finance_group_transactions_path(@ordergroup), notice: I18n.t('finance.financial_transactions.controller.create.notice')
|
redirect_to finance_group_transactions_path(@ordergroup),
|
||||||
rescue ActiveRecord::RecordInvalid => error
|
notice: I18n.t('finance.financial_transactions.controller.create.notice')
|
||||||
flash.now[:alert] = error.message
|
rescue ActiveRecord::RecordInvalid => e
|
||||||
render :action => :new
|
flash.now[:alert] = e.message
|
||||||
|
render action: :new
|
||||||
end
|
end
|
||||||
|
|
||||||
def destroy
|
def destroy
|
||||||
transaction = FinancialTransaction.find(params[:id])
|
transaction = FinancialTransaction.find(params[:id])
|
||||||
transaction.revert!(current_user)
|
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
|
end
|
||||||
|
|
||||||
def new_collection
|
def new_collection
|
||||||
|
@ -88,17 +92,17 @@ class Finance::FinancialTransactionsController < ApplicationController
|
||||||
|
|
||||||
params[:financial_transactions].each do |trans|
|
params[:financial_transactions].each do |trans|
|
||||||
# ignore empty amount fields ...
|
# ignore empty amount fields ...
|
||||||
unless trans[:amount].blank?
|
next if trans[:amount].blank?
|
||||||
amount = LocalizeInput.parse(trans[:amount]).to_f
|
|
||||||
note = params[:note]
|
amount = LocalizeInput.parse(trans[:amount]).to_f
|
||||||
ordergroup = Ordergroup.find(trans[:ordergroup_id])
|
note = params[:note]
|
||||||
if params[:set_balance]
|
ordergroup = Ordergroup.find(trans[:ordergroup_id])
|
||||||
note += " (#{amount})"
|
if params[:set_balance]
|
||||||
amount -= ordergroup.financial_transaction_class_balance(type.financial_transaction_class)
|
note += " (#{amount})"
|
||||||
end
|
amount -= ordergroup.financial_transaction_class_balance(type.financial_transaction_class)
|
||||||
ordergroup.add_financial_transaction!(amount, note, @current_user, type, financial_link)
|
|
||||||
foodcoop_amount -= amount
|
|
||||||
end
|
end
|
||||||
|
ordergroup.add_financial_transaction!(amount, note, @current_user, type, financial_link)
|
||||||
|
foodcoop_amount -= amount
|
||||||
end
|
end
|
||||||
|
|
||||||
if params[:create_foodcoop_transaction]
|
if params[:create_foodcoop_transaction]
|
||||||
|
@ -107,7 +111,7 @@ class Finance::FinancialTransactionsController < ApplicationController
|
||||||
user: @current_user,
|
user: @current_user,
|
||||||
amount: foodcoop_amount,
|
amount: foodcoop_amount,
|
||||||
note: params[:note],
|
note: params[:note],
|
||||||
financial_link: financial_link,
|
financial_link: financial_link
|
||||||
})
|
})
|
||||||
ft.save!
|
ft.save!
|
||||||
end
|
end
|
||||||
|
@ -117,8 +121,8 @@ class Finance::FinancialTransactionsController < ApplicationController
|
||||||
|
|
||||||
url = financial_link ? finance_link_url(financial_link.id) : finance_ordergroups_url
|
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')
|
redirect_to url, notice: I18n.t('finance.financial_transactions.controller.create_collection.notice')
|
||||||
rescue => error
|
rescue StandardError => e
|
||||||
flash.now[:alert] = error.message
|
flash.now[:alert] = e.message
|
||||||
render action: :new_collection
|
render action: :new_collection
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -1,15 +1,16 @@
|
||||||
class Finance::InvoicesController < ApplicationController
|
class Finance::InvoicesController < ApplicationController
|
||||||
before_action :authenticate_finance_or_invoices
|
before_action :authenticate_finance_or_invoices
|
||||||
|
|
||||||
before_action :find_invoice, only: [:show, :edit, :update, :destroy]
|
before_action :find_invoice, only: %i[show edit update destroy]
|
||||||
before_action :ensure_can_edit, only: [:edit, :update, :destroy]
|
before_action :ensure_can_edit, only: %i[edit update destroy]
|
||||||
|
|
||||||
def index
|
def index
|
||||||
@invoices_all = Invoice.includes(:supplier, :deliveries, :orders).order('date DESC')
|
@invoices_all = Invoice.includes(:supplier, :deliveries, :orders).order('date DESC')
|
||||||
@invoices = @invoices_all.page(params[:page]).per(@per_page)
|
@invoices = @invoices_all.page(params[:page]).per(@per_page)
|
||||||
|
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
format.js; format.html { render }
|
format.js
|
||||||
|
format.html { render }
|
||||||
format.csv do
|
format.csv do
|
||||||
send_data InvoicesCsv.new(@invoices_all).to_csv, filename: 'invoices.csv', type: 'text/csv'
|
send_data InvoicesCsv.new(@invoices_all).to_csv, filename: 'invoices.csv', type: 'text/csv'
|
||||||
end
|
end
|
||||||
|
@ -20,11 +21,10 @@ class Finance::InvoicesController < ApplicationController
|
||||||
@suppliers = Supplier.includes(:invoices).where('invoices.paid_on IS NULL').references(:invoices)
|
@suppliers = Supplier.includes(:invoices).where('invoices.paid_on IS NULL').references(:invoices)
|
||||||
end
|
end
|
||||||
|
|
||||||
def show
|
def show; end
|
||||||
end
|
|
||||||
|
|
||||||
def new
|
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.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]
|
@invoice.orders << Order.find_by_id(params[:order_id]) if params[:order_id]
|
||||||
fill_deliveries_and_orders_collection @invoice.id, @invoice.supplier_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
|
def form_on_supplier_id_change
|
||||||
fill_deliveries_and_orders_collection params[:invoice_id], params[:supplier_id]
|
fill_deliveries_and_orders_collection params[:invoice_id], params[:supplier_id]
|
||||||
render :layout => false
|
render layout: false
|
||||||
end
|
end
|
||||||
|
|
||||||
def fill_deliveries_and_orders_collection(invoice_id, supplier_id)
|
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)
|
@deliveries_collection = Delivery.where('invoice_id = ? OR (invoice_id IS NULL AND supplier_id = ?)', invoice_id,
|
||||||
@orders_collection = Order.where('invoice_id = ? OR (invoice_id IS NULL AND supplier_id = ?)', invoice_id, supplier_id).order(ends: :desc).limit(25)
|
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
|
end
|
||||||
|
|
||||||
def create
|
def create
|
||||||
|
@ -58,7 +60,7 @@ class Finance::InvoicesController < ApplicationController
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
fill_deliveries_and_orders_collection @invoice.id, @invoice.supplier_id
|
fill_deliveries_and_orders_collection @invoice.id, @invoice.supplier_id
|
||||||
render :action => "new"
|
render action: 'new'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -81,7 +83,7 @@ class Finance::InvoicesController < ApplicationController
|
||||||
@invoice = Invoice.find(params[:invoice_id])
|
@invoice = Invoice.find(params[:invoice_id])
|
||||||
type = MIME::Types[@invoice.attachment_mime].first
|
type = MIME::Types[@invoice.attachment_mime].first
|
||||||
filename = "invoice_#{@invoice.id}_attachment.#{type.preferred_extension}"
|
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
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
@ -92,8 +94,8 @@ class Finance::InvoicesController < ApplicationController
|
||||||
|
|
||||||
# Returns true if @current_user can edit the invoice..
|
# Returns true if @current_user can edit the invoice..
|
||||||
def ensure_can_edit
|
def ensure_can_edit
|
||||||
unless @invoice.user_can_edit?(current_user)
|
return if @invoice.user_can_edit?(current_user)
|
||||||
deny_access
|
|
||||||
end
|
deny_access
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,17 +1,20 @@
|
||||||
class Finance::OrdergroupsController < Finance::BaseController
|
class Finance::OrdergroupsController < Finance::BaseController
|
||||||
def index
|
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
|
if m
|
||||||
sort = m[:col]
|
sort = m[:col]
|
||||||
sort += ' DESC' if m[:reverse]
|
sort += ' DESC' if m[:reverse]
|
||||||
else
|
else
|
||||||
sort = "name"
|
sort = 'name'
|
||||||
end
|
end
|
||||||
|
|
||||||
@ordergroups = Ordergroup.undeleted.order(sort)
|
@ordergroups = Ordergroup.undeleted.order(sort)
|
||||||
@ordergroups = @ordergroups.include_transaction_class_sum
|
@ordergroups = @ordergroups.include_transaction_class_sum
|
||||||
@ordergroups = @ordergroups.where('groups.name LIKE ?', "%#{params[:query]}%") unless params[:query].nil?
|
@ordergroups = @ordergroups.where('groups.name LIKE ?', "%#{params[:query]}%") unless params[:query].nil?
|
||||||
|
|
||||||
@ordergroups = @ordergroups.page(params[:page]).per(@per_page)
|
@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 }
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,20 +1,16 @@
|
||||||
class Foodcoop::OrdergroupsController < ApplicationController
|
class Foodcoop::OrdergroupsController < ApplicationController
|
||||||
def index
|
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]}%") if params[:name].present? # Search by name
|
||||||
@ordergroups = @ordergroups.where('name LIKE ?', "%#{params[:name]}%")
|
|
||||||
end
|
|
||||||
|
|
||||||
if params[:only_active] # Select only active groups
|
@ordergroups = @ordergroups.active if params[:only_active] # Select only active groups
|
||||||
@ordergroups = @ordergroups.active
|
|
||||||
end
|
|
||||||
|
|
||||||
@ordergroups = @ordergroups.page(params[:page]).per(@per_page)
|
@ordergroups = @ordergroups.page(params[:page]).per(@per_page)
|
||||||
|
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
format.html # index.html.erb
|
format.html # index.html.erb
|
||||||
format.js { render :layout => false }
|
format.js { render layout: false }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,19 +1,22 @@
|
||||||
class Foodcoop::UsersController < ApplicationController
|
class Foodcoop::UsersController < ApplicationController
|
||||||
|
before_action -> { require_config_disabled :disable_members_overview }
|
||||||
|
|
||||||
def index
|
def index
|
||||||
@users = User.undeleted.sort_by_param(params["sort"])
|
@users = User.undeleted.sort_by_param(params['sort'])
|
||||||
|
|
||||||
# if somebody uses the search field:
|
# 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]
|
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
|
end
|
||||||
|
|
||||||
@users = @users.page(params[:page]).per(@per_page)
|
@users = @users.page(params[:page]).per(@per_page)
|
||||||
|
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
format.html # index.html.haml
|
format.html # index.html.haml
|
||||||
format.js { render :layout => false } # index.js.erb
|
format.js { render layout: false } # index.js.erb
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
class Foodcoop::WorkgroupsController < ApplicationController
|
class Foodcoop::WorkgroupsController < ApplicationController
|
||||||
before_action :authenticate_membership_or_admin,
|
before_action :authenticate_membership_or_admin,
|
||||||
:except => [:index]
|
except: [:index]
|
||||||
|
|
||||||
def index
|
def index
|
||||||
@workgroups = Workgroup.order("name")
|
@workgroups = Workgroup.order('name')
|
||||||
end
|
end
|
||||||
|
|
||||||
def edit
|
def edit
|
||||||
|
@ -13,9 +13,9 @@ class Foodcoop::WorkgroupsController < ApplicationController
|
||||||
def update
|
def update
|
||||||
@workgroup = Workgroup.find(params[:id])
|
@workgroup = Workgroup.find(params[:id])
|
||||||
if @workgroup.update(params[:workgroup])
|
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
|
else
|
||||||
render :action => 'edit'
|
render action: 'edit'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
class GroupOrderArticlesController < ApplicationController
|
class GroupOrderArticlesController < ApplicationController
|
||||||
before_action :authenticate_finance
|
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
|
layout false # We only use this controller to server js snippets, no need for layout rendering
|
||||||
|
|
||||||
|
|
167
app/controllers/group_order_invoices_controller.rb
Normal file
167
app/controllers/group_order_invoices_controller.rb
Normal file
|
@ -0,0 +1,167 @@
|
||||||
|
class GroupOrderInvoicesController < ApplicationController
|
||||||
|
include Concerns::SendGroupOrderInvoicePdf
|
||||||
|
before_action :authenticate_finance
|
||||||
|
|
||||||
|
def show
|
||||||
|
@group_order_invoice = GroupOrderInvoice.find(params[:id])
|
||||||
|
raise RecordInvalid unless FoodsoftConfig[:contact][:tax_number]
|
||||||
|
|
||||||
|
respond_to do |format|
|
||||||
|
format.html do
|
||||||
|
send_group_order_invoice_pdf @group_order_invoice if FoodsoftConfig[:contact][:tax_number]
|
||||||
|
end
|
||||||
|
format.pdf do
|
||||||
|
send_group_order_invoice_pdf @group_order_invoice if FoodsoftConfig[:contact][:tax_number]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
rescue ActiveRecord::RecordInvalid => e
|
||||||
|
redirect_back fallback_location: root_path, notice: 'Something went wrong', alert: I18n.t('errors.general_msg', msg: "#{e} " + I18n.t('errors.check_tax_number'))
|
||||||
|
end
|
||||||
|
|
||||||
|
def create
|
||||||
|
go = GroupOrder.find(params[:group_order])
|
||||||
|
@order = go.order
|
||||||
|
begin
|
||||||
|
GroupOrderInvoice.find_or_create_by!(group_order_id: go.id)
|
||||||
|
respond_to do |format|
|
||||||
|
format.js
|
||||||
|
end
|
||||||
|
rescue StandardError => e
|
||||||
|
redirect_back fallback_location: root_path, notice: 'Something went wrong', :alert => I18n.t('errors.general_msg', :msg => e)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def destroy
|
||||||
|
goi = GroupOrderInvoice.find(params[:id])
|
||||||
|
@order = goi.group_order.order
|
||||||
|
goi.destroy
|
||||||
|
respond_to do |format|
|
||||||
|
format.js
|
||||||
|
format.json { head :no_content }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def create_multiple
|
||||||
|
invoice_date = params[:group_order_invoice][:invoice_date]
|
||||||
|
order_id = params[:group_order_invoice][:order_id]
|
||||||
|
@order = Order.find(order_id)
|
||||||
|
gos = GroupOrder.where("order_id = ?", order_id)
|
||||||
|
gos.each do |go|
|
||||||
|
goi = GroupOrderInvoice.find_or_create_by!(group_order_id: go.id)
|
||||||
|
goi.invoice_date = invoice_date
|
||||||
|
goi.invoice_number = goi.generate_invoice_number(1)
|
||||||
|
goi.save!
|
||||||
|
end
|
||||||
|
respond_to do |format|
|
||||||
|
format.js
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def select_sepa_sequence_type
|
||||||
|
@group_order_invoice = GroupOrderInvoice.find(params[:id])
|
||||||
|
@group_order = @group_order_invoice.group_order
|
||||||
|
return unless params[:sepa_sequence_type]
|
||||||
|
|
||||||
|
respond_to do |format|
|
||||||
|
@group_order_invoice.sepa_sequence_type = params[:sepa_sequence_type]
|
||||||
|
if @group_order_invoice.save!
|
||||||
|
format.js
|
||||||
|
else
|
||||||
|
format.json { render json: @group_order_invoice.errors, status: :unprocessable_entity }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def select_all_sepa_sequence_type
|
||||||
|
@order = Order.find(params[:order_id])
|
||||||
|
@group_order_invoices = @order.group_orders.map(&:group_order_invoice).compact
|
||||||
|
return unless params[:sepa_sequence_type]
|
||||||
|
@sepa_sequence_type = params[:sepa_sequence_type]
|
||||||
|
@group_order_invoices.each do |goi|
|
||||||
|
goi.sepa_sequence_type = params[:sepa_sequence_type]
|
||||||
|
goi.save!
|
||||||
|
end
|
||||||
|
respond_to do |format|
|
||||||
|
format.js
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def toggle_paid
|
||||||
|
@group_order_invoice = GroupOrderInvoice.find(params[:id])
|
||||||
|
respond_to do |format|
|
||||||
|
@group_order_invoice.paid = !@group_order_invoice.paid
|
||||||
|
if @group_order_invoice.save!
|
||||||
|
format.js
|
||||||
|
else
|
||||||
|
format.json { render json: @group_order_invoice.errors, status: :unprocessable_entity }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def toggle_sepa_downloaded
|
||||||
|
@group_order_invoice = GroupOrderInvoice.find(params[:id])
|
||||||
|
@order = @group_order_invoice.group_order.order
|
||||||
|
respond_to do |format|
|
||||||
|
@group_order_invoice.sepa_downloaded = !@group_order_invoice.sepa_downloaded
|
||||||
|
if @group_order_invoice.save!
|
||||||
|
format.js
|
||||||
|
else
|
||||||
|
format.json { render json: @group_order_invoice.errors, status: :unprocessable_entity }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def toggle_all_paid
|
||||||
|
@order = Order.find(params[:order_id])
|
||||||
|
@group_order_invoices = @order.group_orders.map(&:group_order_invoice).compact
|
||||||
|
@group_order_invoices.each do |goi|
|
||||||
|
goi.paid = !ActiveRecord::Type::Boolean.new.deserialize(params[:paid])
|
||||||
|
goi.save!
|
||||||
|
end
|
||||||
|
respond_to do |format|
|
||||||
|
format.js
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def toggle_all_sepa_downloaded
|
||||||
|
@order = Order.find(params[:order_id])
|
||||||
|
@group_order_invoices = @order.group_orders.map(&:group_order_invoice).compact
|
||||||
|
@group_order_invoices.each do |goi|
|
||||||
|
goi.sepa_downloaded = !ActiveRecord::Type::Boolean.new.deserialize(params[:sepa_downloaded])
|
||||||
|
goi.save!
|
||||||
|
end
|
||||||
|
respond_to do |format|
|
||||||
|
format.js
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def download_all
|
||||||
|
order = Order.find(params[:order_id])
|
||||||
|
|
||||||
|
invoices = order.group_orders.map(&:group_order_invoice)
|
||||||
|
pdf = {}
|
||||||
|
file_paths = []
|
||||||
|
temp_file = Tempfile.new("all_invoices_for_order_#{order.id}.zip")
|
||||||
|
Zip::File.open(temp_file.path, Zip::File::CREATE) do |zipfile|
|
||||||
|
invoices.each do |invoice|
|
||||||
|
pdf = create_invoice_pdf(invoice)
|
||||||
|
file_path = File.join("tmp", pdf.filename)
|
||||||
|
File.open(file_path, 'w:ASCII-8BIT') do |file|
|
||||||
|
file.write(pdf.to_pdf)
|
||||||
|
end
|
||||||
|
file_paths << file_path
|
||||||
|
zipfile.add(pdf.filename, file_path) unless zipfile.find_entry(pdf.filename)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
zip_data = File.read(temp_file.path)
|
||||||
|
file_paths.each do |file_path|
|
||||||
|
File.delete(file_path)
|
||||||
|
end
|
||||||
|
respond_to do |format|
|
||||||
|
format.html do
|
||||||
|
send_data(zip_data, type: 'application/zip', filename: "#{l order.ends, format: :file}-#{order.supplier.name}-#{order.id}.zip", disposition: 'attachment')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -3,9 +3,9 @@
|
||||||
class GroupOrdersController < ApplicationController
|
class GroupOrdersController < ApplicationController
|
||||||
# Security
|
# Security
|
||||||
before_action :ensure_ordergroup_member
|
before_action :ensure_ordergroup_member
|
||||||
before_action :ensure_open_order, :only => [:new, :create, :edit, :update, :order, :stock_order, :saveOrder]
|
before_action :ensure_open_order, only: %i[new create edit update order stock_order saveOrder]
|
||||||
before_action :ensure_my_group_order, only: [:show, :edit, :update]
|
before_action :ensure_my_group_order, only: %i[show edit update]
|
||||||
before_action :enough_apples?, only: [:new, :create]
|
before_action :enough_apples?, only: %i[new create]
|
||||||
|
|
||||||
# Index page.
|
# Index page.
|
||||||
def index
|
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)
|
@finished_not_closed_orders_including_group_order = Order.finished_not_closed.ordergroup_group_orders_map(@ordergroup)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def show
|
||||||
|
@order = @group_order.order
|
||||||
|
end
|
||||||
|
|
||||||
def new
|
def new
|
||||||
ordergroup = params[:stock_order] ? nil : @ordergroup
|
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
|
@ordering_data = @group_order.load_data
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -23,34 +31,26 @@ class GroupOrdersController < ApplicationController
|
||||||
@group_order = GroupOrder.new(params[:group_order])
|
@group_order = GroupOrder.new(params[:group_order])
|
||||||
begin
|
begin
|
||||||
@group_order.save_ordering!
|
@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
|
rescue ActiveRecord::StaleObjectError
|
||||||
redirect_to group_orders_url, :alert => I18n.t('group_orders.create.error_stale')
|
redirect_to group_orders_url, alert: I18n.t('group_orders.create.error_stale')
|
||||||
rescue => exception
|
rescue StandardError => e
|
||||||
logger.error('Failed to update order: ' + exception.message)
|
logger.error('Failed to update order: ' + e.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_general')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def show
|
|
||||||
@order = @group_order.order
|
|
||||||
end
|
|
||||||
|
|
||||||
def edit
|
|
||||||
@ordering_data = @group_order.load_data
|
|
||||||
end
|
|
||||||
|
|
||||||
def update
|
def update
|
||||||
@group_order.attributes = params[:group_order]
|
@group_order.attributes = params[:group_order]
|
||||||
@group_order.updated_by = current_user
|
@group_order.updated_by = current_user
|
||||||
begin
|
begin
|
||||||
@group_order.save_ordering!
|
@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
|
rescue ActiveRecord::StaleObjectError
|
||||||
redirect_to group_orders_url, :alert => I18n.t('group_orders.update.error_stale')
|
redirect_to group_orders_url, alert: I18n.t('group_orders.update.error_stale')
|
||||||
rescue => exception
|
rescue StandardError => e
|
||||||
logger.error('Failed to update order: ' + exception.message)
|
logger.error('Failed to update order: ' + e.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_general')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -74,16 +74,16 @@ class GroupOrdersController < ApplicationController
|
||||||
# Used as a :before_action by OrdersController.
|
# Used as a :before_action by OrdersController.
|
||||||
def ensure_ordergroup_member
|
def ensure_ordergroup_member
|
||||||
@ordergroup = @current_user.ordergroup
|
@ordergroup = @current_user.ordergroup
|
||||||
if @ordergroup.nil?
|
return unless @ordergroup.nil?
|
||||||
redirect_to root_url, :alert => I18n.t('group_orders.errors.no_member')
|
|
||||||
end
|
redirect_to root_url, alert: I18n.t('group_orders.errors.no_member')
|
||||||
end
|
end
|
||||||
|
|
||||||
def ensure_open_order
|
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?
|
unless @order.open?
|
||||||
flash[:notice] = I18n.t('group_orders.errors.closed')
|
flash[:notice] = I18n.t('group_orders.errors.closed')
|
||||||
redirect_to :action => 'index'
|
redirect_to action: 'index'
|
||||||
end
|
end
|
||||||
rescue ActiveRecord::RecordNotFound
|
rescue ActiveRecord::RecordNotFound
|
||||||
redirect_to group_orders_url, alert: I18n.t('group_orders.errors.notfound')
|
redirect_to group_orders_url, alert: I18n.t('group_orders.errors.notfound')
|
||||||
|
@ -91,17 +91,17 @@ class GroupOrdersController < ApplicationController
|
||||||
|
|
||||||
def ensure_my_group_order
|
def ensure_my_group_order
|
||||||
@group_order = GroupOrder.find(params[:id])
|
@group_order = GroupOrder.find(params[:id])
|
||||||
if @group_order.ordergroup != @ordergroup && (@group_order.ordergroup || !current_user.role_orders?)
|
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
|
redirect_to group_orders_url, alert: I18n.t('group_orders.errors.notfound')
|
||||||
end
|
end
|
||||||
|
|
||||||
def enough_apples?
|
def enough_apples?
|
||||||
if @ordergroup.not_enough_apples?
|
return unless @ordergroup.not_enough_apples?
|
||||||
redirect_to group_orders_url,
|
|
||||||
alert: t('not_enough_apples', scope: 'group_orders.messages', apples: @ordergroup.apples,
|
redirect_to group_orders_url,
|
||||||
stop_ordering_under: FoodsoftConfig[:stop_ordering_under])
|
alert: t('not_enough_apples', scope: 'group_orders.messages', apples: @ordergroup.apples,
|
||||||
end
|
stop_ordering_under: FoodsoftConfig[:stop_ordering_under])
|
||||||
end
|
end
|
||||||
|
|
||||||
def order_id_param
|
def order_id_param
|
||||||
|
|
|
@ -9,8 +9,7 @@ class HomeController < ApplicationController
|
||||||
@unassigned_tasks = Task.order(:due_date).next_unassigned_tasks_for(current_user)
|
@unassigned_tasks = Task.order(:due_date).next_unassigned_tasks_for(current_user)
|
||||||
end
|
end
|
||||||
|
|
||||||
def profile
|
def profile; end
|
||||||
end
|
|
||||||
|
|
||||||
def reference_calculator
|
def reference_calculator
|
||||||
if current_user.ordergroup
|
if current_user.ordergroup
|
||||||
|
@ -36,40 +35,43 @@ class HomeController < ApplicationController
|
||||||
@user = @current_user
|
@user = @current_user
|
||||||
@ordergroup = @user.ordergroup
|
@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)
|
@ordergroup = Ordergroup.include_transaction_class_sum.find(@ordergroup.id)
|
||||||
|
|
||||||
if params['sort']
|
sort = if params['sort']
|
||||||
sort = case params['sort']
|
case params['sort']
|
||||||
when "date" then "created_on"
|
when 'date' then 'created_on'
|
||||||
when "note" then "note"
|
when 'note' then 'note'
|
||||||
when "amount" then "amount"
|
when 'amount' then 'amount'
|
||||||
when "date_reverse" then "created_on DESC"
|
when 'date_reverse' then 'created_on DESC'
|
||||||
when "note_reverse" then "note DESC"
|
when 'note_reverse' then 'note DESC'
|
||||||
when "amount_reverse" then "amount DESC"
|
when 'amount_reverse' then 'amount DESC'
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
sort = "created_on DESC"
|
'created_on DESC'
|
||||||
end
|
end
|
||||||
|
|
||||||
@financial_transactions = @ordergroup.financial_transactions.visible.page(params[:page]).per(@per_page).order(sort)
|
@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
|
||||||
end
|
end
|
||||||
|
|
||||||
# cancel personal memberships direct from the myProfile-page
|
# cancel personal memberships direct from the myProfile-page
|
||||||
def cancel_membership
|
def cancel_membership
|
||||||
if params[:membership_id]
|
membership = if params[:membership_id]
|
||||||
membership = @current_user.memberships.find!(params[:membership_id])
|
@current_user.memberships.find(params[:membership_id])
|
||||||
else
|
else
|
||||||
membership = @current_user.memberships.find_by_group_id!(params[:group_id])
|
@current_user.memberships.find_by_group_id!(params[:group_id])
|
||||||
end
|
end
|
||||||
membership.destroy
|
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
|
end
|
||||||
|
|
||||||
protected
|
protected
|
||||||
|
@ -82,8 +84,8 @@ class HomeController < ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
def ordergroup_params
|
def ordergroup_params
|
||||||
if params[:user][:ordergroup]
|
return unless params[:user][:ordergroup]
|
||||||
params.require(:user).require(:ordergroup).permit(:contact_address)
|
|
||||||
end
|
params.require(:user).require(:ordergroup).permit(:contact_address)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,7 +3,7 @@ class InvitesController < ApplicationController
|
||||||
before_action -> { require_config_disabled :disable_invite }
|
before_action -> { require_config_disabled :disable_invite }
|
||||||
|
|
||||||
def new
|
def new
|
||||||
@invite = Invite.new(:user => @current_user, :group => @group)
|
@invite = Invite.new(user: @current_user, group: @group)
|
||||||
end
|
end
|
||||||
|
|
||||||
def create
|
def create
|
||||||
|
@ -27,6 +27,10 @@ class InvitesController < ApplicationController
|
||||||
protected
|
protected
|
||||||
|
|
||||||
def authenticate_membership_or_admin_for_invites
|
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
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
class LoginController < ApplicationController
|
class LoginController < ApplicationController
|
||||||
skip_before_action :authenticate # no authentication since this is the login page
|
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.
|
# Display the form to enter an email address requesting a token to set a new password.
|
||||||
def forgot_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".
|
# Sends an email to a user with the token that allows setting a new password through action "password".
|
||||||
def reset_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 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
|
|
||||||
|
|
||||||
if (user = User.undeleted.find_by_email(params[:user][:email]))
|
if (user = User.undeleted.find_by_email(params[:user][:email]))
|
||||||
user.request_password_reset!
|
user.request_password_reset!
|
||||||
end
|
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
|
end
|
||||||
|
|
||||||
# Set a new password with a token from the password reminder email.
|
# 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.
|
# Called with params :id => User.id and :token => User.reset_password_token to specify a new password.
|
||||||
def new_password
|
def new_password; end
|
||||||
end
|
|
||||||
|
|
||||||
# Sets a new password.
|
# Sets a new password.
|
||||||
# Called with params :id => User.id and :token => User.reset_password_token to specify 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_token = nil
|
||||||
@user.reset_password_expires = nil
|
@user.reset_password_expires = nil
|
||||||
@user.save
|
@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
|
else
|
||||||
render :new_password
|
render :new_password
|
||||||
end
|
end
|
||||||
|
@ -50,14 +47,14 @@ class LoginController < ApplicationController
|
||||||
@user = User.new(params[:user])
|
@user = User.new(params[:user])
|
||||||
@user.email = @invite.email
|
@user.email = @invite.email
|
||||||
if @user.save
|
if @user.save
|
||||||
Membership.new(:user => @user, :group => @invite.group).save!
|
Membership.new(user: @user, group: @invite.group).save!
|
||||||
@invite.destroy
|
@invite.destroy
|
||||||
session[:locale] = @user.locale
|
session[:locale] = @user.locale
|
||||||
redirect_to login_url, notice: I18n.t('login.controller.accept_invitation.notice')
|
redirect_to login_url, notice: I18n.t('login.controller.accept_invitation.notice')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
@user = User.new(:email => @invite.email)
|
@user = User.new(email: @invite.email)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -65,8 +62,8 @@ class LoginController < ApplicationController
|
||||||
|
|
||||||
def validate_token
|
def validate_token
|
||||||
@user = User.find_by_id_and_reset_password_token(params[:id], params[:token])
|
@user = User.find_by_id_and_reset_password_token(params[:id], params[:token])
|
||||||
if (@user.nil? || @user.reset_password_expires < Time.now)
|
return unless @user.nil? || @user.reset_password_expires < Time.now
|
||||||
redirect_to forgot_password_url, alert: I18n.t('login.controller.error_token_invalid')
|
|
||||||
end
|
redirect_to forgot_password_url, alert: I18n.t('login.controller.error_token_invalid')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
class OrderArticlesController < ApplicationController
|
class OrderArticlesController < ApplicationController
|
||||||
before_action :fetch_order, except: :destroy
|
before_action :fetch_order, except: :destroy
|
||||||
before_action :authenticate_finance_or_invoices, except: [:new, :create]
|
before_action :authenticate_finance_or_invoices, except: %i[new create]
|
||||||
before_action :authenticate_finance_orders_or_pickup, except: [:edit, :update, :destroy]
|
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
|
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])
|
@order_article = @order.order_articles.build(params[:order_article])
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def edit
|
||||||
|
@order_article = OrderArticle.find(params[:id])
|
||||||
|
end
|
||||||
|
|
||||||
def create
|
def create
|
||||||
# The article may be ordered with zero units - in that case do not complain.
|
# 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
|
# 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.
|
# given mentioning that the article already exists, which is desired.
|
||||||
@order_article = @order.order_articles.where(:article_id => params[:order_article][:article_id]).first
|
@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]) unless @order_article && @order_article.units_to_order == 0
|
||||||
@order_article = @order.order_articles.build(params[:order_article])
|
|
||||||
end
|
|
||||||
@order_article.save!
|
@order_article.save!
|
||||||
rescue
|
rescue StandardError
|
||||||
render action: :new
|
render action: :new
|
||||||
end
|
end
|
||||||
|
|
||||||
def edit
|
|
||||||
@order_article = OrderArticle.find(params[:id])
|
|
||||||
end
|
|
||||||
|
|
||||||
def update
|
def update
|
||||||
@order_article = OrderArticle.find(params[:id])
|
@order_article = OrderArticle.find(params[:id])
|
||||||
begin
|
begin
|
||||||
@order_article.update_article_and_price!(params[:order_article], params[:article], params[:article_price])
|
@order_article.update_article_and_price!(params[:order_article], params[:article], params[:article_price])
|
||||||
rescue
|
rescue StandardError
|
||||||
render action: :edit
|
render action: :edit
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
class OrderCommentsController < ApplicationController
|
class OrderCommentsController < ApplicationController
|
||||||
def new
|
def new
|
||||||
@order = Order.find(params[:order_id])
|
@order = Order.find(params[:order_id])
|
||||||
@order_comment = @order.comments.build(:user => current_user)
|
@order_comment = @order.comments.build(user: current_user)
|
||||||
end
|
end
|
||||||
|
|
||||||
def create
|
def create
|
||||||
@order_comment = OrderComment.new(params[:order_comment])
|
@order_comment = OrderComment.new(params[:order_comment])
|
||||||
if @order_comment.save
|
if @order_comment.save
|
||||||
render :layout => false
|
render layout: false
|
||||||
else
|
else
|
||||||
render :action => :new, :layout => false
|
render action: :new, layout: false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,27 +3,29 @@
|
||||||
# Normal ordering actions of members of order groups is handled by the OrderingController.
|
# Normal ordering actions of members of order groups is handled by the OrderingController.
|
||||||
class OrdersController < ApplicationController
|
class OrdersController < ApplicationController
|
||||||
include Concerns::SendOrderPdf
|
include Concerns::SendOrderPdf
|
||||||
|
include SepaHelper
|
||||||
|
|
||||||
before_action :authenticate_pickups_or_orders
|
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 :authenticate_orders,
|
||||||
before_action :remove_empty_article, only: [:create, :update]
|
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
|
# List orders
|
||||||
def index
|
def index
|
||||||
@open_orders = Order.open.includes(:supplier)
|
@open_orders = Order.open.includes(:supplier)
|
||||||
@finished_orders = Order.finished_not_closed.includes(:supplier)
|
@finished_orders = Order.finished_not_closed.includes(:supplier)
|
||||||
@per_page = 15
|
@per_page = 15
|
||||||
if params['sort']
|
sort = if params['sort']
|
||||||
sort = case params['sort']
|
case params['sort']
|
||||||
when "supplier" then "suppliers.name, ends DESC"
|
when 'supplier' then 'suppliers.name, ends DESC'
|
||||||
when "pickup" then "pickup DESC"
|
when 'pickup' then 'pickup DESC'
|
||||||
when "ends" then "ends DESC"
|
when 'ends' then 'ends DESC'
|
||||||
when "supplier_reverse" then "suppliers.name DESC"
|
when 'supplier_reverse' then 'suppliers.name DESC'
|
||||||
when "ends_reverse" then "ends"
|
when 'ends_reverse' then 'ends'
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
sort = "ends DESC"
|
'ends DESC'
|
||||||
end
|
end
|
||||||
@suppliers = Supplier.having_articles.order('suppliers.name')
|
@suppliers = Supplier.having_articles.order('suppliers.name')
|
||||||
@orders = Order.closed.includes(:supplier).reorder(sort).page(params[:page]).per(@per_page)
|
@orders = Order.closed.includes(:supplier).reorder(sort).page(params[:page]).per(@per_page)
|
||||||
end
|
end
|
||||||
|
@ -43,7 +45,7 @@ class OrdersController < ApplicationController
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
format.html
|
format.html
|
||||||
format.js do
|
format.js do
|
||||||
render :layout => false
|
render layout: false
|
||||||
end
|
end
|
||||||
format.pdf do
|
format.pdf do
|
||||||
send_order_pdf @order, params[:document]
|
send_order_pdf @order, params[:document]
|
||||||
|
@ -66,8 +68,14 @@ class OrdersController < ApplicationController
|
||||||
else
|
else
|
||||||
@order = Order.new(supplier_id: params[:supplier_id]).init_dates
|
@order = Order.new(supplier_id: params[:supplier_id]).init_dates
|
||||||
end
|
end
|
||||||
rescue => error
|
rescue StandardError => e
|
||||||
redirect_to orders_url, alert: t('errors.general_msg', msg: error.message)
|
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
|
end
|
||||||
|
|
||||||
# Save a new order.
|
# Save a new order.
|
||||||
|
@ -81,31 +89,25 @@ class OrdersController < ApplicationController
|
||||||
redirect_to @order
|
redirect_to @order
|
||||||
else
|
else
|
||||||
logger.debug "[debug] order errors: #{@order.errors.messages}"
|
logger.debug "[debug] order errors: #{@order.errors.messages}"
|
||||||
render :action => 'new'
|
render action: 'new'
|
||||||
end
|
end
|
||||||
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.
|
# Update an existing order.
|
||||||
def update
|
def update
|
||||||
@order = Order.find params[:id]
|
@order = Order.find params[:id]
|
||||||
if @order.update(params[:order].merge(updated_by: current_user))
|
if @order.update(params[:order].merge(updated_by: current_user))
|
||||||
flash[:notice] = I18n.t('orders.update.notice')
|
flash[:notice] = I18n.t('orders.update.notice')
|
||||||
redirect_to :action => 'show', :id => @order
|
redirect_to action: 'show', id: @order
|
||||||
else
|
else
|
||||||
render :action => 'edit'
|
render action: 'edit'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Delete an order.
|
# Delete an order.
|
||||||
def destroy
|
def destroy
|
||||||
Order.find(params[:id]).destroy
|
Order.find(params[:id]).destroy
|
||||||
redirect_to :action => 'index'
|
redirect_to action: 'index'
|
||||||
end
|
end
|
||||||
|
|
||||||
# Finish a current order.
|
# Finish a current order.
|
||||||
|
@ -113,8 +115,8 @@ class OrdersController < ApplicationController
|
||||||
order = Order.find(params[:id])
|
order = Order.find(params[:id])
|
||||||
order.finish!(@current_user)
|
order.finish!(@current_user)
|
||||||
redirect_to order, notice: I18n.t('orders.finish.notice')
|
redirect_to order, notice: I18n.t('orders.finish.notice')
|
||||||
rescue => error
|
rescue StandardError => e
|
||||||
redirect_to orders_url, alert: I18n.t('errors.general_msg', :msg => error.message)
|
redirect_to orders_url, alert: I18n.t('errors.general_msg', msg: e.message)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Send a order to the supplier.
|
# Send a order to the supplier.
|
||||||
|
@ -122,20 +124,18 @@ class OrdersController < ApplicationController
|
||||||
order = Order.find(params[:id])
|
order = Order.find(params[:id])
|
||||||
order.send_to_supplier!(@current_user)
|
order.send_to_supplier!(@current_user)
|
||||||
redirect_to order, notice: I18n.t('orders.send_to_supplier.notice')
|
redirect_to order, notice: I18n.t('orders.send_to_supplier.notice')
|
||||||
rescue => error
|
rescue StandardError => e
|
||||||
redirect_to order, alert: I18n.t('errors.general_msg', :msg => error.message)
|
redirect_to order, alert: I18n.t('errors.general_msg', msg: e.message)
|
||||||
end
|
end
|
||||||
|
|
||||||
def receive
|
def receive
|
||||||
@order = Order.find(params[:id])
|
@order = Order.find(params[:id])
|
||||||
unless request.post?
|
if request.post?
|
||||||
@order_articles = @order.order_articles.ordered_or_member.includes(:article).order('articles.order_number, articles.name')
|
|
||||||
else
|
|
||||||
Order.transaction do
|
Order.transaction do
|
||||||
s = update_order_amounts
|
s = update_order_amounts
|
||||||
@order.update_attribute(:state, 'received') if @order.state != 'received'
|
@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
|
end
|
||||||
NotifyReceivedOrderJob.perform_later(@order)
|
NotifyReceivedOrderJob.perform_later(@order)
|
||||||
if current_user.role_orders? || current_user.role_finance?
|
if current_user.role_orders? || current_user.role_finance?
|
||||||
|
@ -145,23 +145,95 @@ class OrdersController < ApplicationController
|
||||||
else
|
else
|
||||||
redirect_to receive_order_path(@order)
|
redirect_to receive_order_path(@order)
|
||||||
end
|
end
|
||||||
|
else
|
||||||
|
@order_articles = @order.order_articles.ordered_or_member.includes(:article).order('articles.order_number, articles.name')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def receive_on_order_article_create # See publish/subscribe design pattern in /doc.
|
def receive_on_order_article_create # See publish/subscribe design pattern in /doc.
|
||||||
@order_article = OrderArticle.find(params[:order_article_id])
|
@order_article = OrderArticle.find(params[:order_article_id])
|
||||||
render :layout => false
|
render layout: false
|
||||||
end
|
end
|
||||||
|
|
||||||
def receive_on_order_article_update # See publish/subscribe design pattern in /doc.
|
def receive_on_order_article_update # See publish/subscribe design pattern in /doc.
|
||||||
@order_article = OrderArticle.find(params[:order_article_id])
|
@order_article = OrderArticle.find(params[:order_article_id])
|
||||||
render :layout => false
|
render layout: false
|
||||||
|
end
|
||||||
|
|
||||||
|
def collective_direct_debit
|
||||||
|
if foodsoft_sepa_ready?
|
||||||
|
case params[:mode]
|
||||||
|
when 'all'
|
||||||
|
group_orders = GroupOrder.where(order_id: params[:id])
|
||||||
|
when 'selected'
|
||||||
|
group_orders = GroupOrder.where(id: params[:group_order_ids])
|
||||||
|
else
|
||||||
|
redirect_to finance_order_index_path, alert: I18n.t('orders.collective_direct_debit.alert', ordergroup_names: '')
|
||||||
|
end
|
||||||
|
|
||||||
|
@order = Order.find(params[:id])
|
||||||
|
ordergroups = group_orders.map(&:ordergroup)
|
||||||
|
|
||||||
|
export_allowed = !ordergroups.map(&:sepa_possible?).include?(false) && !group_orders.map { |go| go.group_order_invoice.present? }.include?(false)
|
||||||
|
group_order_ids = group_orders.map { |go| go.id if go.group_order_invoice.present? }
|
||||||
|
|
||||||
|
sepa_possible_ordergroup_names = ordergroups.map { |ordergroup| ordergroup.name if ordergroup.sepa_possible? }.compact_blank
|
||||||
|
sepa_not_possible_ordergroup_names = ordergroups.map(&:name) - sepa_possible_ordergroup_names
|
||||||
|
|
||||||
|
if export_allowed && group_orders.present?
|
||||||
|
respond_to do |format|
|
||||||
|
format.html do
|
||||||
|
collective_debit = OrderCollectiveDirectDebitXml.new(group_orders)
|
||||||
|
send_data collective_debit.xml_string, filename: @order.name + '_Sammellastschrift' + '.xml', type: 'text/xml'
|
||||||
|
group_orders.map(&:group_order_invoice).each(&:mark_sepa_downloaded)
|
||||||
|
rescue SEPA::Error => e
|
||||||
|
group_orders.map(&:group_order_invoice).each(&:unmark_sepa_downloaded)
|
||||||
|
redirect_to finance_order_index_path, alert: e.message
|
||||||
|
rescue StandardError => e
|
||||||
|
group_orders.map(&:group_order_invoice).each(&:unmark_sepa_downloaded)
|
||||||
|
redirect_to finance_order_index_path, alert: I18n.t('orders.collective_direct_debit.alert', ordergroup_names: sepa_not_possible_ordergroup_names.join(', '), error: e.message)
|
||||||
|
end
|
||||||
|
format.xml do
|
||||||
|
group_orders.map(&:group_order_invoice).each(&:mark_sepa_downloaded)
|
||||||
|
collective_debit = OrderCollectiveDirectDebitXml.new(group_orders)
|
||||||
|
send_data collective_debit.xml_string, filename: @order.name + '_Sammellastschrift' + '.xml', type: 'text/xml'
|
||||||
|
rescue SEPA::Error => e
|
||||||
|
group_orders.map(&:group_order_invoice).each(&:unmark_sepa_downloaded)
|
||||||
|
render json: { error: e.message }
|
||||||
|
rescue StandardError => e
|
||||||
|
group_orders.map(&:group_order_invoice).each(&:unmark_sepa_downloaded)
|
||||||
|
render json: { error: I18n.t('orders.collective_direct_debit.alert', ordergroup_names: sepa_not_possible_ordergroup_names.join(', '), error: e.message) }
|
||||||
|
end
|
||||||
|
format.js
|
||||||
|
end
|
||||||
|
else
|
||||||
|
respond_to do |format|
|
||||||
|
format.html do
|
||||||
|
redirect_to finance_order_index_path, alert: I18n.t('orders.collective_direct_debit.alert', ordergroup_names: sepa_not_possible_ordergroup_names.join(', '), error: '')
|
||||||
|
end
|
||||||
|
format.xml do
|
||||||
|
render json: { error: I18n.t('orders.collective_direct_debit.alert', ordergroup_names: sepa_not_possible_ordergroup_names.join(', '), error: '') }
|
||||||
|
end
|
||||||
|
format.js
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
respond_to do |format|
|
||||||
|
format.html do
|
||||||
|
redirect_to finance_order_index_path, alert: "Wichtige SEPA Konfiguration in Administration >> Einstellungen >> Finanzen nicht gesetzt!"
|
||||||
|
end
|
||||||
|
format.xml do
|
||||||
|
redirect_to finance_order_index_path, alert: "Wichtige SEPA Konfiguration in Administration >> Einstellungen >> Finanzen nicht gesetzt!"
|
||||||
|
end
|
||||||
|
format.js
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
protected
|
protected
|
||||||
|
|
||||||
def update_order_amounts
|
def update_order_amounts
|
||||||
return if not params[:order_articles]
|
return unless params[:order_articles]
|
||||||
|
|
||||||
# where to leave remainder during redistribution
|
# where to leave remainder during redistribution
|
||||||
rest_to = []
|
rest_to = []
|
||||||
|
@ -176,35 +248,42 @@ class OrdersController < ApplicationController
|
||||||
# "MySQL lock timeout exceeded" errors. It's ok to do
|
# "MySQL lock timeout exceeded" errors. It's ok to do
|
||||||
# this article-by-article anway.
|
# this article-by-article anway.
|
||||||
params[:order_articles].each do |oa_id, oa_params|
|
params[:order_articles].each do |oa_id, oa_params|
|
||||||
unless oa_params.blank?
|
next if oa_params.blank?
|
||||||
oa = OrderArticle.find(oa_id)
|
|
||||||
# update attributes; don't use update_attribute because it calls save
|
oa = OrderArticle.find(oa_id)
|
||||||
# which makes received_changed? not work anymore
|
# update attributes; don't use update_attribute because it calls save
|
||||||
oa.attributes = oa_params
|
# which makes received_changed? not work anymore
|
||||||
if oa.units_received_changed?
|
oa.attributes = oa_params
|
||||||
counts[0] += 1
|
if oa.units_received_changed?
|
||||||
unless oa.units_received.blank?
|
counts[0] += 1
|
||||||
cunits[0] += oa.units_received * oa.article.unit_quantity
|
if oa.units_received.present?
|
||||||
oacounts = oa.redistribute oa.units_received * oa.price.unit_quantity, rest_to
|
cunits[0] += oa.units_received * oa.article.unit_quantity
|
||||||
oacounts.each_with_index { |c, i| cunits[i + 1] += c; counts[i + 1] += 1 if c > 0 }
|
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
|
||||||
end
|
end
|
||||||
oa.save!
|
|
||||||
end
|
end
|
||||||
|
oa.save!
|
||||||
end
|
end
|
||||||
return nil if counts[0] == 0
|
return nil if counts[0] == 0
|
||||||
|
|
||||||
notice = []
|
notice = []
|
||||||
notice << I18n.t('orders.update_order_amounts.msg1', count: counts[0], units: cunits[0])
|
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]
|
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
|
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
|
end
|
||||||
notice.join(', ')
|
notice.join(', ')
|
||||||
end
|
end
|
||||||
|
|
||||||
def remove_empty_article
|
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
|
||||||
end
|
end
|
||||||
|
|
|
@ -12,16 +12,20 @@ class SessionsController < ApplicationController
|
||||||
user = User.authenticate(params[:nick], params[:password])
|
user = User.authenticate(params[:nick], params[:password])
|
||||||
if user
|
if user
|
||||||
user.update_attribute(:last_login, Time.now)
|
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
|
else
|
||||||
flash.now.alert = I18n.t(FoodsoftConfig[:use_nick] ? 'sessions.login_invalid_nick' : 'sessions.login_invalid_email')
|
flash.now.alert = I18n.t(FoodsoftConfig[:use_nick] ? 'sessions.login_invalid_nick' : 'sessions.login_invalid_email')
|
||||||
render "new"
|
render 'new'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def destroy
|
def destroy
|
||||||
logout
|
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
|
end
|
||||||
|
|
||||||
# redirect to root, going to default foodcoop when none given
|
# redirect to root, going to default foodcoop when none given
|
||||||
|
|
|
@ -7,21 +7,21 @@ class StockTakingsController < ApplicationController
|
||||||
|
|
||||||
def new
|
def new
|
||||||
@stock_taking = StockTaking.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
|
end
|
||||||
|
|
||||||
def new_on_stock_article_create # See publish/subscribe design pattern in /doc.
|
def new_on_stock_article_create # See publish/subscribe design pattern in /doc.
|
||||||
stock_article = StockArticle.find(params[:stock_article_id])
|
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
|
end
|
||||||
|
|
||||||
def create
|
def create
|
||||||
create!(:notice => I18n.t('stock_takings.create.notice'))
|
create!(notice: I18n.t('stock_takings.create.notice'))
|
||||||
end
|
end
|
||||||
|
|
||||||
def update
|
def update
|
||||||
update!(:notice => I18n.t('stock_takings.update.notice'))
|
update!(notice: I18n.t('stock_takings.update.notice'))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -7,57 +7,13 @@ class StockitController < ApplicationController
|
||||||
def index_on_stock_article_create # See publish/subscribe design pattern in /doc.
|
def index_on_stock_article_create # See publish/subscribe design pattern in /doc.
|
||||||
@stock_article = StockArticle.find(params[:id])
|
@stock_article = StockArticle.find(params[:id])
|
||||||
|
|
||||||
render :layout => false
|
render layout: false
|
||||||
end
|
end
|
||||||
|
|
||||||
def index_on_stock_article_update # See publish/subscribe design pattern in /doc.
|
def index_on_stock_article_update # See publish/subscribe design pattern in /doc.
|
||||||
@stock_article = StockArticle.find(params[:id])
|
@stock_article = StockArticle.find(params[:id])
|
||||||
|
|
||||||
render :layout => false
|
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
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def show
|
def show
|
||||||
|
@ -65,24 +21,68 @@ class StockitController < ApplicationController
|
||||||
@stock_changes = @stock_article.stock_changes.order('stock_changes.created_at DESC')
|
@stock_changes = @stock_article.stock_changes.order('stock_changes.created_at DESC')
|
||||||
end
|
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.
|
def show_on_stock_article_update # See publish/subscribe design pattern in /doc.
|
||||||
@stock_article = StockArticle.find(params[:id])
|
@stock_article = StockArticle.find(params[:id])
|
||||||
|
|
||||||
render :layout => false
|
render layout: false
|
||||||
end
|
end
|
||||||
|
|
||||||
def destroy
|
def destroy
|
||||||
@stock_article = StockArticle.find(params[:id])
|
@stock_article = StockArticle.find(params[:id])
|
||||||
@stock_article.mark_as_deleted
|
@stock_article.mark_as_deleted
|
||||||
render :layout => false
|
render layout: false
|
||||||
rescue => error
|
rescue StandardError => e
|
||||||
render :partial => "destroy_fail", :layout => false,
|
render partial: 'destroy_fail', layout: false,
|
||||||
:locals => { :fail_msg => I18n.t('errors.general_msg', :msg => error.message) }
|
locals: { fail_msg: I18n.t('errors.general_msg', msg: e.message) }
|
||||||
end
|
end
|
||||||
|
|
||||||
# TODO: Fix this!!
|
# TODO: Fix this!!
|
||||||
def articles_search
|
def articles_search
|
||||||
@articles = Article.not_in_stock.limit(8).where('name LIKE ?', "%#{params[:term]}%")
|
@articles = Article.not_in_stock.limit(8).where('name LIKE ?', "%#{params[:term]}%")
|
||||||
render :json => @articles.map(&:name)
|
render json: @articles.map(&:name)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -9,7 +9,7 @@ class StylesController < ApplicationController
|
||||||
def foodcoop
|
def foodcoop
|
||||||
css = FoodsoftConfig[:custom_css]
|
css = FoodsoftConfig[:custom_css]
|
||||||
if css.blank?
|
if css.blank?
|
||||||
render body: nil, content_type: 'text/css', status: 404
|
render body: nil, content_type: 'text/css', status: :not_found
|
||||||
else
|
else
|
||||||
expires_in 1.week, public: true if params[:md5].present?
|
expires_in 1.week, public: true if params[:md5].present?
|
||||||
render body: css, content_type: 'text/css'
|
render body: css, content_type: 'text/css'
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
class SuppliersController < ApplicationController
|
class SuppliersController < ApplicationController
|
||||||
before_action :authenticate_suppliers, :except => [:index, :list]
|
before_action :authenticate_suppliers, except: %i[index list]
|
||||||
helper :deliveries
|
helper :deliveries
|
||||||
|
|
||||||
def index
|
def index
|
||||||
|
@ -24,6 +24,10 @@ class SuppliersController < ApplicationController
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def edit
|
||||||
|
@supplier = Supplier.find(params[:id])
|
||||||
|
end
|
||||||
|
|
||||||
def create
|
def create
|
||||||
@supplier = Supplier.new(supplier_params)
|
@supplier = Supplier.new(supplier_params)
|
||||||
@supplier.supplier_category ||= SupplierCategory.first
|
@supplier.supplier_category ||= SupplierCategory.first
|
||||||
|
@ -31,21 +35,17 @@ class SuppliersController < ApplicationController
|
||||||
flash[:notice] = I18n.t('suppliers.create.notice')
|
flash[:notice] = I18n.t('suppliers.create.notice')
|
||||||
redirect_to suppliers_path
|
redirect_to suppliers_path
|
||||||
else
|
else
|
||||||
render :action => 'new'
|
render action: 'new'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def edit
|
|
||||||
@supplier = Supplier.find(params[:id])
|
|
||||||
end
|
|
||||||
|
|
||||||
def update
|
def update
|
||||||
@supplier = Supplier.find(params[:id])
|
@supplier = Supplier.find(params[:id])
|
||||||
if @supplier.update(supplier_params)
|
if @supplier.update(supplier_params)
|
||||||
flash[:notice] = I18n.t('suppliers.update.notice')
|
flash[:notice] = I18n.t('suppliers.update.notice')
|
||||||
redirect_to @supplier
|
redirect_to @supplier
|
||||||
else
|
else
|
||||||
render :action => 'edit'
|
render action: 'edit'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -54,8 +54,8 @@ class SuppliersController < ApplicationController
|
||||||
@supplier.mark_as_deleted
|
@supplier.mark_as_deleted
|
||||||
flash[:notice] = I18n.t('suppliers.destroy.notice')
|
flash[:notice] = I18n.t('suppliers.destroy.notice')
|
||||||
redirect_to suppliers_path
|
redirect_to suppliers_path
|
||||||
rescue => e
|
rescue StandardError => e
|
||||||
flash[:error] = I18n.t('errors.general_msg', :msg => e.message)
|
flash[:error] = I18n.t('errors.general_msg', msg: e.message)
|
||||||
redirect_to @supplier
|
redirect_to @supplier
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -11,35 +11,33 @@ class TasksController < ApplicationController
|
||||||
@accepted_tasks = Task.accepted_tasks_for(current_user)
|
@accepted_tasks = Task.accepted_tasks_for(current_user)
|
||||||
end
|
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
|
def show
|
||||||
@task = Task.find(params[:id])
|
@task = Task.find(params[:id])
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def new
|
||||||
|
@task = Task.new(current_user_id: current_user.id)
|
||||||
|
end
|
||||||
|
|
||||||
def edit
|
def edit
|
||||||
@task = Task.find(params[:id])
|
@task = Task.find(params[:id])
|
||||||
@periodic = !!params[:periodic]
|
@periodic = !!params[:periodic]
|
||||||
@task.current_user_id = current_user.id
|
@task.current_user_id = current_user.id
|
||||||
end
|
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
|
def update
|
||||||
@task = Task.find(params[:id])
|
@task = Task.find(params[:id])
|
||||||
task_group = @task.periodic_task_group
|
task_group = @task.periodic_task_group
|
||||||
|
@ -50,16 +48,14 @@ class TasksController < ApplicationController
|
||||||
if @task.errors.empty? && @task.save
|
if @task.errors.empty? && @task.save
|
||||||
task_group.update_tasks_including(@task, prev_due_date) if params[:periodic]
|
task_group.update_tasks_including(@task, prev_due_date) if params[:periodic]
|
||||||
flash[:notice] = I18n.t('tasks.update.notice')
|
flash[:notice] = I18n.t('tasks.update.notice')
|
||||||
if was_periodic && !@task.periodic?
|
flash[:notice] = I18n.t('tasks.update.notice_converted') if was_periodic && !@task.periodic?
|
||||||
flash[:notice] = I18n.t('tasks.update.notice_converted')
|
|
||||||
end
|
|
||||||
if @task.workgroup
|
if @task.workgroup
|
||||||
redirect_to workgroup_tasks_url(workgroup_id: @task.workgroup_id)
|
redirect_to workgroup_tasks_url(workgroup_id: @task.workgroup_id)
|
||||||
else
|
else
|
||||||
redirect_to tasks_url
|
redirect_to tasks_url
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
render :template => "tasks/edit"
|
render template: 'tasks/edit'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -75,7 +71,7 @@ class TasksController < ApplicationController
|
||||||
end
|
end
|
||||||
task.update_ordergroup_stats(user_ids)
|
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
|
end
|
||||||
|
|
||||||
# assign current_user to the task and set the assignment to "accepted"
|
# 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)
|
if ass = task.is_assigned?(current_user)
|
||||||
ass.update_attribute(:accepted, true)
|
ass.update_attribute(:accepted, true)
|
||||||
else
|
else
|
||||||
task.assignments.create(:user => current_user, :accepted => true)
|
task.assignments.create(user: current_user, accepted: true)
|
||||||
end
|
end
|
||||||
redirect_to user_tasks_path, :notice => I18n.t('tasks.accept.notice')
|
redirect_to user_tasks_path, notice: I18n.t('tasks.accept.notice')
|
||||||
end
|
end
|
||||||
|
|
||||||
# deletes assignment between current_user and given taskcurrent_user_id: current_user.id
|
# deletes assignment between current_user and given taskcurrent_user_id: current_user.id
|
||||||
def reject
|
def reject
|
||||||
Task.find(params[:id]).users.delete(current_user)
|
Task.find(params[:id]).users.delete(current_user)
|
||||||
redirect_to :action => "index"
|
redirect_to action: 'index'
|
||||||
end
|
end
|
||||||
|
|
||||||
def set_done
|
def set_done
|
||||||
Task.find(params[:id]).update_attribute :done, true
|
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
|
end
|
||||||
|
|
||||||
# Shows all tasks, which are already done
|
# Shows all tasks, which are already done
|
||||||
|
@ -109,9 +105,9 @@ class TasksController < ApplicationController
|
||||||
# shows workgroup (normal group) to edit weekly_tasks_template
|
# shows workgroup (normal group) to edit weekly_tasks_template
|
||||||
def workgroup
|
def workgroup
|
||||||
@group = Group.find(params[:workgroup_id])
|
@group = Group.find(params[:workgroup_id])
|
||||||
if @group.is_a? Ordergroup
|
return unless @group.is_a? Ordergroup
|
||||||
redirect_to tasks_url, :alert => I18n.t('tasks.error_not_found')
|
|
||||||
end
|
redirect_to tasks_url, alert: I18n.t('tasks.error_not_found')
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
|
@ -3,7 +3,7 @@ class UsersController < ApplicationController
|
||||||
def index
|
def index
|
||||||
@users = User.undeleted.natural_search(params[:q])
|
@users = User.undeleted.natural_search(params[:q])
|
||||||
respond_to do |format|
|
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
|
end
|
||||||
end
|
end
|
||||||
|
|
309
app/documents/group_order_invoice_pdf.rb
Normal file
309
app/documents/group_order_invoice_pdf.rb
Normal file
|
@ -0,0 +1,309 @@
|
||||||
|
class GroupOrderInvoicePdf < RenderPdf
|
||||||
|
def filename
|
||||||
|
ordergroup_name = @options[:ordergroup].name || "OrderGroup"
|
||||||
|
"#{ordergroup_name}_" + I18n.t('documents.group_order_invoice_pdf.filename', :number => @options[:invoice_number]) + '.pdf'
|
||||||
|
end
|
||||||
|
|
||||||
|
def title
|
||||||
|
I18n.t('documents.group_order_invoice_pdf.title', :supplier => @options[:supplier])
|
||||||
|
end
|
||||||
|
|
||||||
|
def body
|
||||||
|
contact = FoodsoftConfig[:contact].symbolize_keys
|
||||||
|
ordergroup = @options[:ordergroup]
|
||||||
|
|
||||||
|
# From paragraph
|
||||||
|
bounding_box [margin_box.right - 200, margin_box.top - 20], width: 200 do
|
||||||
|
text I18n.t('documents.group_order_invoice_pdf.invoicer')
|
||||||
|
move_down 7
|
||||||
|
text FoodsoftConfig[:name], size: fontsize(9), align: :left
|
||||||
|
move_down 5
|
||||||
|
text contact[:street], size: fontsize(9), align: :left
|
||||||
|
move_down 5
|
||||||
|
text "#{contact[:zip_code]} #{contact[:city]}", size: fontsize(9), align: :left
|
||||||
|
move_down 5
|
||||||
|
if contact[:phone].present?
|
||||||
|
text "#{Supplier.human_attribute_name :phone}: #{contact[:phone]}", size: fontsize(9), align: :left
|
||||||
|
move_down 5
|
||||||
|
end
|
||||||
|
text "#{Supplier.human_attribute_name :email}: #{contact[:email]}", size: fontsize(9), align: :left if contact[:email].present?
|
||||||
|
move_down 5
|
||||||
|
text I18n.t('documents.group_order_invoice_pdf.tax_number', :number => @options[:tax_number]), size: fontsize(9), align: :left
|
||||||
|
end
|
||||||
|
|
||||||
|
# Receiving Ordergroup
|
||||||
|
bounding_box [margin_box.left, margin_box.top - 20], width: 200 do
|
||||||
|
text I18n.t('documents.group_order_invoice_pdf.invoicee')
|
||||||
|
move_down 7
|
||||||
|
text I18n.t('documents.group_order_invoice_pdf.ordergroup.name', ordergroup: ordergroup.name.to_s), size: fontsize(9)
|
||||||
|
move_down 5
|
||||||
|
if ordergroup.contact_address.present?
|
||||||
|
text I18n.t('documents.group_order_invoice_pdf.ordergroup.contact_address', contact_address: ordergroup.contact_address.to_s), size: fontsize(9)
|
||||||
|
move_down 5
|
||||||
|
end
|
||||||
|
if ordergroup.contact_phone.present?
|
||||||
|
text I18n.t('documents.group_order_invoice_pdf.ordergroup.contact_phone', contact_phone: ordergroup.contact_phone.to_s), size: fontsize(9)
|
||||||
|
move_down 5
|
||||||
|
end
|
||||||
|
if ordergroup.customer_number.present?
|
||||||
|
text I18n.t('documents.group_order_invoice_pdf.ordergroup.customer_number', customer_number: ordergroup.customer_number.to_s), size: fontsize(9)
|
||||||
|
move_down 5
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# invoice Date and nnvoice number
|
||||||
|
bounding_box [margin_box.right - 200, margin_box.top - 150], width: 200 do
|
||||||
|
text I18n.t('documents.group_order_invoice_pdf.invoice_number', invoice_number: @options[:invoice_number]), align: :left
|
||||||
|
move_down 5
|
||||||
|
text I18n.t('documents.group_order_invoice_pdf.invoice_date', invoice_date: @options[:invoice_date].strftime(I18n.t('date.formats.default'))), align: :left
|
||||||
|
if @options[:pickup]
|
||||||
|
move_down 5
|
||||||
|
text I18n.t('documents.group_order_invoice_pdf.pickup_date', invoice_date: @options[:pickup].strftime(I18n.t('date.formats.default')))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
move_down 20
|
||||||
|
text I18n.t('documents.group_order_invoice_pdf.payment_method', payment_method: @options[:payment_method])
|
||||||
|
text I18n.t('documents.group_order_invoice_pdf.table_headline')
|
||||||
|
move_down 5
|
||||||
|
|
||||||
|
#------------- Table Data -----------------------
|
||||||
|
|
||||||
|
@group_order = GroupOrder.find(@options[:group_order].id)
|
||||||
|
|
||||||
|
if FoodsoftConfig[:group_order_invoices][:vat_exempt]
|
||||||
|
body_for_vat_exempt
|
||||||
|
else
|
||||||
|
body_with_vat
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def body_for_vat_exempt
|
||||||
|
total_gross = 0
|
||||||
|
data = [I18n.t('documents.group_order_invoice_pdf.vat_exempt_rows')]
|
||||||
|
move_down 10
|
||||||
|
group_order_articles = GroupOrderArticle.where(group_order_id: @group_order.id)
|
||||||
|
separate_deposits = FoodsoftConfig[:group_order_invoices]&.[](:separate_deposits)
|
||||||
|
group_order_articles.each do |goa|
|
||||||
|
# if no unit is received, nothing is to be charged
|
||||||
|
next if goa.result.to_i == 0
|
||||||
|
|
||||||
|
goa_total_price = separate_deposits ? goa.total_price_without_deposit : goa.total_price
|
||||||
|
data << [goa.order_article.article.name,
|
||||||
|
goa.result.to_i,
|
||||||
|
number_to_currency(goa.order_article.price.fc_price_without_deposit),
|
||||||
|
number_to_currency(goa_total_price)]
|
||||||
|
total_gross += goa_total_price
|
||||||
|
next unless separate_deposits && goa.order_article.price.deposit > 0.0
|
||||||
|
|
||||||
|
goa_total_deposit = goa.result * goa.order_article.price.fc_deposit_price
|
||||||
|
data << ["zzgl. Pfand",
|
||||||
|
goa.result.to_i,
|
||||||
|
number_to_currency(goa.order_article.article.fc_deposit_price),
|
||||||
|
number_to_currency(goa_total_deposit)]
|
||||||
|
total_gross += goa_total_deposit
|
||||||
|
end
|
||||||
|
|
||||||
|
table data, cell_style: { size: fontsize(8), overflow: :shrink_to_fit } do |table|
|
||||||
|
table.header = true
|
||||||
|
table.position = :center
|
||||||
|
table.cells.border_width = 1
|
||||||
|
table.cells.border_color = '666666'
|
||||||
|
|
||||||
|
table.row(0).column(0..4).width = 80
|
||||||
|
table.row(0).column(0).width = 180
|
||||||
|
table.row(0).border_bottom_width = 2
|
||||||
|
table.columns(1).align = :right
|
||||||
|
table.columns(1..6).align = :right
|
||||||
|
end
|
||||||
|
|
||||||
|
move_down 5
|
||||||
|
sum = []
|
||||||
|
sum << [nil, nil, I18n.t('documents.group_order_invoice_pdf.sum_to_pay_gross'), number_to_currency(total_gross)]
|
||||||
|
# table for sum
|
||||||
|
table sum, cell_style: { size: fontsize(8), overflow: :shrink_to_fit } do |table|
|
||||||
|
table.header = true
|
||||||
|
table.position = :center
|
||||||
|
table.cells.border_width = 1
|
||||||
|
table.cells.border_color = '666666'
|
||||||
|
table.row(0).columns(2..4).style(align: :bottom)
|
||||||
|
table.row(0).border_bottom_width = 2
|
||||||
|
table.row(0..-1).columns(0..1).border_width = 0
|
||||||
|
|
||||||
|
table.rows(0..-1).columns(0..4).width = 80
|
||||||
|
table.row(0).column(0).width = 180
|
||||||
|
table.row(0).column(-1).style(font_style: :bold)
|
||||||
|
table.row(0).column(-2).style(font_style: :bold)
|
||||||
|
table.row(0).column(-1).size = fontsize(10)
|
||||||
|
table.row(0).column(-2).size = fontsize(10)
|
||||||
|
|
||||||
|
table.columns(1).align = :right
|
||||||
|
table.columns(1..6).align = :right
|
||||||
|
end
|
||||||
|
|
||||||
|
move_down 25
|
||||||
|
text I18n.t('documents.group_order_invoice_pdf.small_business_regulation')
|
||||||
|
move_down 10
|
||||||
|
end
|
||||||
|
|
||||||
|
def body_with_vat
|
||||||
|
separate_deposits = FoodsoftConfig[:group_order_invoices]&.[](:separate_deposits)
|
||||||
|
total_gross = 0
|
||||||
|
total_net = 0
|
||||||
|
# Articles
|
||||||
|
|
||||||
|
tax_hash_net = Hash.new(0) # for summing up article net prices grouped into vat percentage
|
||||||
|
tax_hash_gross = Hash.new(0) # same here with gross prices
|
||||||
|
tax_hash_fc = Hash.new(0) # same here with fc prices
|
||||||
|
|
||||||
|
if separate_deposits
|
||||||
|
total_deposit = 0
|
||||||
|
total_deposit_gross = 0
|
||||||
|
|
||||||
|
tax_hash_deposit_gross = Hash.new(0) # for summing up deposit gross prices grouped into vat percentage
|
||||||
|
tax_hash_deposit_net = Hash.new(0) # same here with gross prices
|
||||||
|
tax_hash_deposit_fc = Hash.new(0) # same here with fc prices
|
||||||
|
end
|
||||||
|
|
||||||
|
marge = FoodsoftConfig[:price_markup]
|
||||||
|
|
||||||
|
# data table looks different when price_markup > 0
|
||||||
|
data = if marge == 0
|
||||||
|
[I18n.t('documents.group_order_invoice_pdf.no_price_markup_rows')]
|
||||||
|
else
|
||||||
|
[I18n.t('documents.group_order_invoice_pdf.price_markup_rows', marge: marge)]
|
||||||
|
end
|
||||||
|
goa_tax_hash = GroupOrderArticle.where(group_order_id: @group_order.id).find_each.group_by { |oat| oat.order_article.price.tax }
|
||||||
|
goa_tax_hash.each do |tax, group_order_articles|
|
||||||
|
group_order_articles.each do |goa|
|
||||||
|
# if no unit is received, nothing is to be charged
|
||||||
|
next if goa.result.to_i == 0
|
||||||
|
|
||||||
|
order_article = goa.order_article
|
||||||
|
goa_total_net = goa.result * order_article.price.price
|
||||||
|
|
||||||
|
goa_total_fc = separate_deposits ? goa.total_price_without_deposit : goa.total_price
|
||||||
|
goa_total_gross = separate_deposits ? goa.result * order_article.price.gross_price_without_deposit : goa.result * order_article.price.gross_price
|
||||||
|
|
||||||
|
data << [order_article.article.name,
|
||||||
|
goa.result.to_i,
|
||||||
|
number_to_currency(order_article.price.price),
|
||||||
|
number_to_currency(goa_total_net),
|
||||||
|
tax.to_s + '%',
|
||||||
|
number_to_currency(goa_total_fc)]
|
||||||
|
|
||||||
|
if separate_deposits && order_article.price.deposit > 0.0
|
||||||
|
goa_net_deposit = goa.result * order_article.price.net_deposit_price
|
||||||
|
goa_deposit = goa.result * order_article.price.deposit
|
||||||
|
goa_total_deposit = goa.result * order_article.price.fc_deposit_price
|
||||||
|
|
||||||
|
data << ["zzgl. Pfand",
|
||||||
|
goa.result.to_i,
|
||||||
|
number_to_currency(order_article.price.net_deposit_price),
|
||||||
|
number_to_currency(goa_net_deposit),
|
||||||
|
tax.to_s + '%',
|
||||||
|
number_to_currency(goa_total_deposit)]
|
||||||
|
|
||||||
|
total_deposit += goa_deposit
|
||||||
|
total_deposit_gross += goa_total_deposit
|
||||||
|
|
||||||
|
tax_hash_deposit_net[tax.to_i] += goa_net_deposit
|
||||||
|
tax_hash_deposit_gross[tax.to_i] += goa_deposit
|
||||||
|
tax_hash_deposit_fc[tax.to_i] += goa_total_deposit
|
||||||
|
end
|
||||||
|
|
||||||
|
tax_hash_net[tax.to_i] += goa_total_net
|
||||||
|
tax_hash_gross[tax.to_i] += goa_total_gross
|
||||||
|
tax_hash_fc[tax.to_i] += goa_total_fc
|
||||||
|
|
||||||
|
total_net += goa_total_net
|
||||||
|
total_gross += goa_total_fc
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Two separate tables for sum and individual data
|
||||||
|
# article information + data
|
||||||
|
table data, cell_style: { size: fontsize(8), overflow: :shrink_to_fit } do |table|
|
||||||
|
table.header = true
|
||||||
|
table.position = :center
|
||||||
|
table.cells.border_width = 1
|
||||||
|
table.cells.border_color = '666666'
|
||||||
|
table.row(0).columns(0..6).style(background_color: 'cccccc', font_style: :bold)
|
||||||
|
table.rows(0..-1).columns(2..6).width = 80
|
||||||
|
table.rows(0..-1).column(0).width = 170
|
||||||
|
table.rows(0..-1).column(1).width = 40
|
||||||
|
table.rows(0..-1).column(4).width = 60
|
||||||
|
table.rows(0..-1).column(5).width = 90
|
||||||
|
table.row(0).border_bottom_width = 2
|
||||||
|
table.columns(1).align = :right
|
||||||
|
table.columns(1..6).align = :right
|
||||||
|
end
|
||||||
|
|
||||||
|
if marge > 0
|
||||||
|
sum = [[nil, nil, "Netto", "MwSt", "FC-Marge", "Brutto"]]
|
||||||
|
else
|
||||||
|
sum = [[nil, nil, nil, "Netto", "MwSt", "Brutto"]]
|
||||||
|
end
|
||||||
|
|
||||||
|
tax_hash_gross.keys.each do |key|
|
||||||
|
tmp_sum = [nil, "Produkte mit #{key}%", number_to_currency(tax_hash_net[key])]
|
||||||
|
if marge <= 0
|
||||||
|
tmp_sum.unshift(nil)
|
||||||
|
end
|
||||||
|
tmp_sum << number_to_currency(tax_hash_gross[key] - tax_hash_net[key])
|
||||||
|
if marge > 0
|
||||||
|
tmp_sum << number_to_currency(tax_hash_fc[key] - tax_hash_gross[key])
|
||||||
|
end
|
||||||
|
tmp_sum << number_to_currency(tax_hash_fc[key])
|
||||||
|
sum << tmp_sum
|
||||||
|
|
||||||
|
|
||||||
|
if separate_deposits
|
||||||
|
tmp_sum = [nil, "Pfand mit #{key}%", number_to_currency(tax_hash_deposit_net[key])]
|
||||||
|
if marge <= 0
|
||||||
|
tmp_sum.unshift(nil)
|
||||||
|
end
|
||||||
|
tmp_sum << number_to_currency(tax_hash_deposit_gross[key] - tax_hash_deposit_net[key])
|
||||||
|
if marge > 0
|
||||||
|
tmp_sum << number_to_currency(tax_hash_deposit_fc[key] - tax_hash_deposit_gross[key])
|
||||||
|
end
|
||||||
|
tmp_sum << number_to_currency(tax_hash_deposit_fc[key])
|
||||||
|
sum << tmp_sum
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
total_deposit_gross ||= 0
|
||||||
|
sum << [nil, nil, nil, nil, I18n.t('documents.group_order_invoice_pdf.sum_to_pay_gross'), number_to_currency(total_gross + total_deposit_gross)]
|
||||||
|
|
||||||
|
move_down 10
|
||||||
|
table sum, cell_style: { size: fontsize(8), overflow: :shrink_to_fit } do |table|
|
||||||
|
table.header = true
|
||||||
|
table.position = :center
|
||||||
|
table.cells.border_width = 1
|
||||||
|
table.cells.border_color = '666666'
|
||||||
|
table.row(0).columns(2..6).style(align: :bottom)
|
||||||
|
table.row(0).border_bottom_width = 2
|
||||||
|
table.row(0..-1).columns(0).border_width = 0
|
||||||
|
table.row(0..-1).columns(1).border_width = 0 if marge <= 0
|
||||||
|
table.rows(0..-1).columns(2..6).width = 80
|
||||||
|
table.rows(0..-1).column(0).width = 110
|
||||||
|
table.rows(0..-1).column(1).width = 100
|
||||||
|
table.rows(0..-1).column(4).width = 60
|
||||||
|
table.rows(0..-1).column(5).width = 90
|
||||||
|
|
||||||
|
table.row(-1).column(-1).style(font_style: :bold)
|
||||||
|
table.row(-1).column(-2).style(font_style: :bold)
|
||||||
|
table.row(-1).column(-1).size = fontsize(10)
|
||||||
|
table.row(-1).column(-2).size = fontsize(10)
|
||||||
|
|
||||||
|
table.columns(1).align = :right
|
||||||
|
table.columns(1..6).align = :right
|
||||||
|
end
|
||||||
|
|
||||||
|
if FoodsoftConfig[:group_order_invoices][:vat_exempt]
|
||||||
|
move_down 15
|
||||||
|
text I18n.t('documents.group_order_invoice_pdf.small_business_regulation')
|
||||||
|
end
|
||||||
|
move_down 10
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,11 +1,11 @@
|
||||||
class OrderByArticles < OrderPdf
|
class OrderByArticles < OrderPdf
|
||||||
def filename
|
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
|
end
|
||||||
|
|
||||||
def title
|
def title
|
||||||
I18n.t('documents.order_by_articles.title', :name => order.name,
|
I18n.t('documents.order_by_articles.title', name: order.name,
|
||||||
:date => order.ends.strftime(I18n.t('date.formats.default')))
|
date: order.ends.strftime(I18n.t('date.formats.default')))
|
||||||
end
|
end
|
||||||
|
|
||||||
def body
|
def body
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
class OrderByGroups < OrderPdf
|
class OrderByGroups < OrderPdf
|
||||||
def filename
|
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
|
end
|
||||||
|
|
||||||
def title
|
def title
|
||||||
I18n.t('documents.order_by_groups.title', :name => order.name,
|
I18n.t('documents.order_by_groups.title', name: order.name,
|
||||||
:date => order.ends.strftime(I18n.t('date.formats.default')))
|
date: order.ends.strftime(I18n.t('date.formats.default')))
|
||||||
end
|
end
|
||||||
|
|
||||||
def body
|
def body
|
||||||
|
|
|
@ -2,7 +2,7 @@ class OrderFax < OrderPdf
|
||||||
BATCH_SIZE = 250
|
BATCH_SIZE = 250
|
||||||
|
|
||||||
def filename
|
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
|
end
|
||||||
|
|
||||||
def title
|
def title
|
||||||
|
@ -20,16 +20,18 @@ class OrderFax < OrderPdf
|
||||||
move_down 5
|
move_down 5
|
||||||
text "#{contact[:zip_code]} #{contact[:city]}", size: fontsize(9), align: :right
|
text "#{contact[:zip_code]} #{contact[:city]}", size: fontsize(9), align: :right
|
||||||
move_down 5
|
move_down 5
|
||||||
unless order.supplier.try(:customer_number).blank?
|
if order.supplier.try(:customer_number).present?
|
||||||
text "#{Supplier.human_attribute_name :customer_number}: #{order.supplier[:customer_number]}", size: fontsize(9), align: :right
|
text "#{Supplier.human_attribute_name :customer_number}: #{order.supplier[:customer_number]}",
|
||||||
|
size: fontsize(9), align: :right
|
||||||
move_down 5
|
move_down 5
|
||||||
end
|
end
|
||||||
unless contact[:phone].blank?
|
if contact[:phone].present?
|
||||||
text "#{Supplier.human_attribute_name :phone}: #{contact[:phone]}", size: fontsize(9), align: :right
|
text "#{Supplier.human_attribute_name :phone}: #{contact[:phone]}", size: fontsize(9), align: :right
|
||||||
move_down 5
|
move_down 5
|
||||||
end
|
end
|
||||||
unless contact[:email].blank?
|
if contact[:email].present?
|
||||||
text "#{Supplier.human_attribute_name :email}: #{contact[:email]}", size: fontsize(9), align: :right
|
text "#{Supplier.human_attribute_name :email}: #{contact[:email]}", size: fontsize(9),
|
||||||
|
align: :right
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -38,7 +40,7 @@ class OrderFax < OrderPdf
|
||||||
text order.name
|
text order.name
|
||||||
move_down 5
|
move_down 5
|
||||||
text order.supplier.try(:address).to_s
|
text order.supplier.try(:address).to_s
|
||||||
unless order.supplier.try(:fax).blank?
|
if order.supplier.try(:fax).present?
|
||||||
move_down 5
|
move_down 5
|
||||||
text "#{Supplier.human_attribute_name :fax}: #{order.supplier[:fax]}"
|
text "#{Supplier.human_attribute_name :fax}: #{order.supplier[:fax]}"
|
||||||
end
|
end
|
||||||
|
@ -50,7 +52,7 @@ class OrderFax < OrderPdf
|
||||||
move_down 10
|
move_down 10
|
||||||
text "#{Delivery.human_attribute_name :date}:"
|
text "#{Delivery.human_attribute_name :date}:"
|
||||||
move_down 10
|
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]}"
|
text "#{Supplier.human_attribute_name :contact_person}: #{order.supplier[:contact_person]}"
|
||||||
move_down 10
|
move_down 10
|
||||||
end
|
end
|
||||||
|
@ -78,8 +80,8 @@ class OrderFax < OrderPdf
|
||||||
table.row(0).border_bottom_width = 2
|
table.row(0).border_bottom_width = 2
|
||||||
table.columns(1).align = :right
|
table.columns(1).align = :right
|
||||||
table.columns(3..6).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..5).borders = %i[top bottom]
|
||||||
table.row(data.length - 1).columns(0).borders = [:top, :bottom, :left]
|
table.row(data.length - 1).columns(0).borders = %i[top bottom left]
|
||||||
table.row(data.length - 1).border_top_width = 2
|
table.row(data.length - 1).border_top_width = 2
|
||||||
end
|
end
|
||||||
# font_size: fontsize(8),
|
# font_size: fontsize(8),
|
||||||
|
@ -98,7 +100,7 @@ class OrderFax < OrderPdf
|
||||||
.preload(:article, :article_price)
|
.preload(:article, :article_price)
|
||||||
end
|
end
|
||||||
|
|
||||||
def each_order_article
|
def each_order_article(&block)
|
||||||
order_articles.find_each_with_order(batch_size: BATCH_SIZE) { |oa| yield oa }
|
order_articles.find_each_with_order(batch_size: BATCH_SIZE, &block)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,12 +3,12 @@ class OrderMatrix < OrderPdf
|
||||||
PLACEHOLDER_CHAR = 'X'
|
PLACEHOLDER_CHAR = 'X'
|
||||||
|
|
||||||
def filename
|
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
|
end
|
||||||
|
|
||||||
def title
|
def title
|
||||||
I18n.t('documents.order_matrix.title', :name => @order.name,
|
I18n.t('documents.order_matrix.title', name: @order.name,
|
||||||
:date => @order.ends.strftime(I18n.t('date.formats.default')))
|
date: @order.ends.strftime(I18n.t('date.formats.default')))
|
||||||
end
|
end
|
||||||
|
|
||||||
def body
|
def body
|
||||||
|
@ -87,7 +87,7 @@ class OrderMatrix < OrderPdf
|
||||||
table.cells.border_width = 0.5
|
table.cells.border_width = 0.5
|
||||||
table.cells.border_color = '666666'
|
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(0).padding = [2, 0, 2, 0]
|
||||||
table.row(1..-1).height = row_height_1
|
table.row(1..-1).height = row_height_1
|
||||||
table.column(0..1).borders = []
|
table.column(0..1).borders = []
|
||||||
|
@ -106,7 +106,7 @@ class OrderMatrix < OrderPdf
|
||||||
table.column(2 + idx).border_width = 2
|
table.column(2 + idx).border_width = 2
|
||||||
end
|
end
|
||||||
|
|
||||||
table.row_colors = ['dddddd', 'ffffff']
|
table.row_colors = %w[dddddd ffffff]
|
||||||
end
|
end
|
||||||
|
|
||||||
first_page = false
|
first_page = false
|
||||||
|
|
|
@ -28,7 +28,11 @@ module Admin::ConfigsHelper
|
||||||
options[:default] = options[:input_html].delete(:value)
|
options[:default] = options[:input_html].delete(:value)
|
||||||
return form.input key, options, &block
|
return form.input key, options, &block
|
||||||
end
|
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
|
form.input key, options, &block
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -57,11 +61,12 @@ module Admin::ConfigsHelper
|
||||||
unchecked_value = options.delete(:unchecked_value) || 'false'
|
unchecked_value = options.delete(:unchecked_value) || 'false'
|
||||||
options[:checked] = 'checked' if v = options.delete(:value) && v != '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
|
# 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
|
elsif options[:as] == :select_recurring
|
||||||
options[:value] = FoodsoftDateUtil.rule_from(options[:value])
|
options[:value] = FoodsoftDateUtil.rule_from(options[:value])
|
||||||
options[:rules] ||= []
|
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
|
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
|
form.select_recurring key, options.delete(:rules).uniq, options
|
||||||
else
|
else
|
||||||
|
@ -73,7 +78,7 @@ module Admin::ConfigsHelper
|
||||||
# @param form [ActionView::Helpers::FormBuilder] Form object.
|
# @param form [ActionView::Helpers::FormBuilder] Form object.
|
||||||
# @param key [Symbol, String] Configuration key of a boolean (e.g. +use_messages+).
|
# @param key [Symbol, String] Configuration key of a boolean (e.g. +use_messages+).
|
||||||
# @option options [String] :label Label to show
|
# @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
|
head = content_tag :label do
|
||||||
lbl = options[:label] || config_input_label(form, key)
|
lbl = options[:label] || config_input_label(form, key)
|
||||||
field = config_input_field(form, key, as: :boolean, boolean_style: :inline,
|
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, {})
|
content_tag :span, (lbl + field).html_safe, config_input_tooltip_options(form, key, {})
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
fields = content_tag(:fieldset, id: "#{key}-fields", class: "collapse#{' in' if @cfg[key]}") do
|
fields = content_tag(:fieldset, id: "#{key}-fields", class: "collapse#{' in' if @cfg[key]}", &block)
|
||||||
yield
|
|
||||||
end
|
|
||||||
head + fields
|
head + fields
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -127,7 +130,7 @@ module Admin::ConfigsHelper
|
||||||
# tooltip with help info to the right
|
# tooltip with help info to the right
|
||||||
cfg_path = form.lookup_model_names[1..-1] + [key]
|
cfg_path = form.lookup_model_names[1..-1] + [key]
|
||||||
tooltip = I18n.t("config.hints.#{cfg_path.map(&:to_s).join('.')}", default: '')
|
tooltip = I18n.t("config.hints.#{cfg_path.map(&:to_s).join('.')}", default: '')
|
||||||
unless tooltip.blank?
|
if tooltip.present?
|
||||||
options[:data] ||= {}
|
options[:data] ||= {}
|
||||||
options[:data][:toggle] ||= 'tooltip'
|
options[:data][:toggle] ||= 'tooltip'
|
||||||
options[:data][:placement] ||= 'right'
|
options[:data][:placement] ||= 'right'
|
||||||
|
|
|
@ -2,9 +2,7 @@ module Admin::OrdergroupsHelper
|
||||||
def ordergroup_members_title(ordergroup)
|
def ordergroup_members_title(ordergroup)
|
||||||
s = ''
|
s = ''
|
||||||
s += ordergroup.users.map(&:name).join(', ') if ordergroup.users.any?
|
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 if ordergroup.contact_person.present?
|
||||||
s += "\n" + Ordergroup.human_attribute_name(:contact) + ": " + ordergroup.contact_person
|
|
||||||
end
|
|
||||||
s
|
s
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -4,7 +4,7 @@ module ApplicationHelper
|
||||||
include PathHelper
|
include PathHelper
|
||||||
|
|
||||||
def format_time(time = Time.now)
|
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
|
end
|
||||||
|
|
||||||
def format_date(time = Time.now)
|
def format_date(time = Time.now)
|
||||||
|
@ -16,7 +16,7 @@ module ApplicationHelper
|
||||||
end
|
end
|
||||||
|
|
||||||
def format_datetime_timespec(time, format)
|
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
|
end
|
||||||
|
|
||||||
def format_currency(amount)
|
def format_currency(amount)
|
||||||
|
@ -26,28 +26,28 @@ module ApplicationHelper
|
||||||
|
|
||||||
# Splits an IBAN into groups of 4 digits displayed with margins in between
|
# Splits an IBAN into groups of 4 digits displayed with margins in between
|
||||||
def format_iban(iban)
|
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
|
end
|
||||||
|
|
||||||
# Creates ajax-controlled-links for pagination
|
# Creates ajax-controlled-links for pagination
|
||||||
def pagination_links_remote(collection, options = {})
|
def pagination_links_remote(collection, options = {})
|
||||||
per_page = options[:per_page] || @per_page
|
per_page = options[:per_page] || @per_page
|
||||||
params = options[:params] || {}
|
params = options[:params] || {}
|
||||||
params = params.merge({ :per_page => per_page })
|
params = params.merge({ per_page: per_page })
|
||||||
paginate collection, :params => params, :remote => true
|
paginate collection, params: params, remote: true
|
||||||
end
|
end
|
||||||
|
|
||||||
# Link-collection for per_page-options when using the pagination-plugin
|
# Link-collection for per_page-options when using the pagination-plugin
|
||||||
def items_per_page(options = {})
|
def items_per_page(options = {})
|
||||||
per_page_options = options[:per_page_options] || [20, 50, 100, 500]
|
per_page_options = options[:per_page_options] || [20, 50, 100, 500]
|
||||||
current = options[:current] || @per_page
|
current = options[:current] || @per_page
|
||||||
params = params || {}
|
params ||= {}
|
||||||
|
|
||||||
links = per_page_options.map do |per_page|
|
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 = 'btn'
|
||||||
link_class << ' disabled' if per_page == current
|
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
|
end
|
||||||
|
|
||||||
if options[:wrap] == false
|
if options[:wrap] == false
|
||||||
|
@ -63,21 +63,19 @@ module ApplicationHelper
|
||||||
# Hmtl options
|
# Hmtl options
|
||||||
remote = options[:remote].nil? ? true : options[:remote]
|
remote = options[:remote].nil? ? true : options[:remote]
|
||||||
class_name = case params[:sort]
|
class_name = case params[:sort]
|
||||||
when key then
|
when key
|
||||||
'sortup'
|
'sortup'
|
||||||
when key + '_reverse' then
|
when key + '_reverse'
|
||||||
'sortdown'
|
'sortdown'
|
||||||
else
|
|
||||||
nil
|
|
||||||
end
|
end
|
||||||
html_options = {
|
html_options = {
|
||||||
:title => I18n.t('helpers.application.sort_by', text: text),
|
title: I18n.t('helpers.application.sort_by', text: text),
|
||||||
:remote => remote,
|
remote: remote,
|
||||||
:class => class_name
|
class: class_name
|
||||||
}
|
}
|
||||||
|
|
||||||
# Url options
|
# Url options
|
||||||
key += "_reverse" if params[:sort] == key
|
key += '_reverse' if params[:sort] == key
|
||||||
per_page = options[:per_page] || @per_page
|
per_page = options[:per_page] || @per_page
|
||||||
url_options = params.merge(per_page: per_page, sort: key)
|
url_options = params.merge(per_page: per_page, sort: key)
|
||||||
url_options.merge!({ page: params[:page] }) if params[:page]
|
url_options.merge!({ page: params[:page] }) if params[:page]
|
||||||
|
@ -95,14 +93,16 @@ module ApplicationHelper
|
||||||
# be overridden by the option 'desc'.
|
# be overridden by the option 'desc'.
|
||||||
# Other options are passed through to I18n.
|
# Other options are passed through to I18n.
|
||||||
def heading_helper(model, attribute, options = {})
|
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)
|
s = model.human_attribute_name(attribute, i18nopts)
|
||||||
if options[:short]
|
if options[:short]
|
||||||
desc = options[:desc]
|
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
|
desc.blank? && desc = s
|
||||||
sshort = model.human_attribute_name("#{attribute}_short".to_sym, options.merge({ fallback: true, default: '', count: 2 }))
|
sshort = model.human_attribute_name("#{attribute}_short".to_sym,
|
||||||
s = raw "<abbr title='#{desc}'>#{sshort}</abbr>" unless sshort.blank?
|
options.merge({ fallback: true, default: '', count: 2 }))
|
||||||
|
s = raw "<abbr title='#{desc}'>#{sshort}</abbr>" if sshort.present?
|
||||||
end
|
end
|
||||||
s
|
s
|
||||||
end
|
end
|
||||||
|
@ -117,7 +117,7 @@ module ApplicationHelper
|
||||||
# Returns the weekday. 0 is sunday, 1 is monday and so on
|
# Returns the weekday. 0 is sunday, 1 is monday and so on
|
||||||
def weekday(dayNumber)
|
def weekday(dayNumber)
|
||||||
weekdays = I18n.t('date.day_names')
|
weekdays = I18n.t('date.day_names')
|
||||||
return weekdays[dayNumber]
|
weekdays[dayNumber]
|
||||||
end
|
end
|
||||||
|
|
||||||
# to set a title for both the h1-tag and the title in the header
|
# 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 = {})
|
def icon(name, options = {})
|
||||||
icons = {
|
icons = {
|
||||||
:delete => { :file => 'b_drop.png', :alt => I18n.t('ui.delete') },
|
delete: { file: 'b_drop.png', alt: I18n.t('ui.delete') },
|
||||||
:edit => { :file => 'b_edit.png', :alt => I18n.t('ui.edit') },
|
edit: { file: 'b_edit.png', alt: I18n.t('ui.edit') },
|
||||||
:members => { :file => 'b_users.png', :alt => I18n.t('helpers.application.edit_user') }
|
members: { file: 'b_users.png', alt: I18n.t('helpers.application.edit_user') }
|
||||||
}
|
}
|
||||||
options[:alt] ||= icons[name][:alt]
|
options[:alt] ||= icons[name][:alt]
|
||||||
options[:title] ||= icons[name][:title]
|
options[:title] ||= icons[name][:title]
|
||||||
options.merge!({ :size => '16x16', :border => "0" })
|
options.merge!({ size: '16x16', border: '0' })
|
||||||
|
|
||||||
image_tag icons[name][:file], options
|
image_tag icons[name][:file], options
|
||||||
end
|
end
|
||||||
|
@ -150,27 +150,29 @@ module ApplicationHelper
|
||||||
# Remote links with default 'loader'.gif during request
|
# Remote links with default 'loader'.gif during request
|
||||||
def remote_link_to(text, options = {})
|
def remote_link_to(text, options = {})
|
||||||
remote_options = {
|
remote_options = {
|
||||||
:before => "Element.show('loader')",
|
before: "Element.show('loader')",
|
||||||
:success => "Element.hide('loader')",
|
success: "Element.hide('loader')",
|
||||||
:method => :get
|
method: :get
|
||||||
}
|
}
|
||||||
link_to(text, options[:url], remote_options.merge(options))
|
link_to(text, options[:url], remote_options.merge(options))
|
||||||
end
|
end
|
||||||
|
|
||||||
def format_roles(record, icon = false)
|
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}?" }
|
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
|
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
|
else
|
||||||
roles.map { |r| names[r] }.join(', ')
|
roles.map { |r| names[r] }.join(', ')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def link_to_gmaps(address)
|
def link_to_gmaps(address)
|
||||||
link_to h(address), "http://maps.google.com/?q=#{h(address)}", :title => I18n.t('helpers.application.show_google_maps'),
|
link_to h(address), "http://maps.google.com/?q=#{h(address)}", title: I18n.t('helpers.application.show_google_maps'),
|
||||||
:target => "_blank"
|
target: '_blank', rel: 'noopener'
|
||||||
end
|
end
|
||||||
|
|
||||||
# Returns flash messages html.
|
# Returns flash messages html.
|
||||||
|
@ -186,8 +188,8 @@ module ApplicationHelper
|
||||||
type = :success if type == 'notice'
|
type = :success if type == 'notice'
|
||||||
type = :error if type == 'alert'
|
type = :error if type == 'alert'
|
||||||
text = content_tag(:div,
|
text = content_tag(:div,
|
||||||
content_tag(:button, I18n.t('ui.marks.close').html_safe, :class => "close", "data-dismiss" => "alert") +
|
content_tag(:button, I18n.t('ui.marks.close').html_safe, :class => 'close', 'data-dismiss' => 'alert') +
|
||||||
message, :class => "alert fade in alert-#{type}")
|
message, class: "alert fade in alert-#{type}")
|
||||||
flash_messages << text if message
|
flash_messages << text if message
|
||||||
end
|
end
|
||||||
flash_messages.join("\n").html_safe
|
flash_messages.join("\n").html_safe
|
||||||
|
@ -195,17 +197,17 @@ module ApplicationHelper
|
||||||
|
|
||||||
# render base errors in a form after failed validation
|
# render base errors in a form after failed validation
|
||||||
# http://railsapps.github.io/twitter-bootstrap-rails.html
|
# 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?
|
return '' if resource.errors.empty? || resource.errors[:base].empty?
|
||||||
|
|
||||||
messages = resource.errors[:base].map { |msg| content_tag(:li, msg) }.join
|
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
|
end
|
||||||
|
|
||||||
# show a user, depending on settings
|
# show a user, depending on settings
|
||||||
def show_user(user = @current_user, options = {})
|
def show_user(user = @current_user, options = {})
|
||||||
if user.nil?
|
if user.nil?
|
||||||
"?"
|
'?'
|
||||||
elsif FoodsoftConfig[:use_nick]
|
elsif FoodsoftConfig[:use_nick]
|
||||||
if options[:full] && options[:markup]
|
if options[:full] && options[:markup]
|
||||||
raw "<b>#{h user.nick}</b> (#{h user.first_name} #{h user.last_name})"
|
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
|
user.nick.nil? ? I18n.t('helpers.application.nick_fallback') : user.nick
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
"#{user.first_name} #{user.last_name}" + (options[:unique] ? " (\##{user.id})" : '')
|
"#{user.first_name} #{user.last_name}" + (options[:unique] ? " (##{user.id})" : '')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -258,9 +260,9 @@ module ApplicationHelper
|
||||||
|
|
||||||
# @return [String] stylesheet tag for foodcoop CSS style (+custom_css+ foodcoop config)
|
# @return [String] stylesheet tag for foodcoop CSS style (+custom_css+ foodcoop config)
|
||||||
# @see #foodcoop_css_path
|
# @see #foodcoop_css_path
|
||||||
def foodcoop_css_tag(options = {})
|
def foodcoop_css_tag(_options = {})
|
||||||
unless FoodsoftConfig[:custom_css].blank?
|
return if FoodsoftConfig[:custom_css].blank?
|
||||||
stylesheet_link_tag foodcoop_css_path, media: 'all'
|
|
||||||
end
|
stylesheet_link_tag foodcoop_css_path, media: 'all'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,13 +3,13 @@ module ArticlesHelper
|
||||||
def highlight_new(unequal_attributes, attribute)
|
def highlight_new(unequal_attributes, attribute)
|
||||||
return unless unequal_attributes
|
return unless unequal_attributes
|
||||||
|
|
||||||
unequal_attributes.has_key?(attribute) ? "background-color: yellow" : ""
|
unequal_attributes.has_key?(attribute) ? 'background-color: yellow' : ''
|
||||||
end
|
end
|
||||||
|
|
||||||
def row_classes(article)
|
def row_classes(article)
|
||||||
classes = []
|
classes = []
|
||||||
classes << "unavailable" if !article.availability
|
classes << 'unavailable' unless article.availability
|
||||||
classes << "just-updated" if article.recently_updated && article.availability
|
classes << 'just-updated' if article.recently_updated && article.availability
|
||||||
classes.join(" ")
|
classes.join(' ')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -11,11 +11,11 @@ module DeliveriesHelper
|
||||||
|
|
||||||
def articles_for_select2(articles, except = [], &block)
|
def articles_for_select2(articles, except = [], &block)
|
||||||
articles = articles.reorder('articles.name ASC')
|
articles = articles.reorder('articles.name ASC')
|
||||||
articles = articles.reject { |a| not except.index(a.id).nil? } if except
|
articles = articles.reject { |a| !except.index(a.id).nil? } if except
|
||||||
block_given? or block = Proc.new { |a| "#{a.name} (#{number_to_currency a.price}/#{a.unit})" }
|
block_given? or block = proc { |a| "#{a.name} (#{number_to_currency a.price}/#{a.unit})" }
|
||||||
articles.map do |a|
|
articles.map do |a|
|
||||||
{ :id => a.id, :text => block.call(a) }
|
{ id: a.id, text: block.call(a) }
|
||||||
end.unshift({ :id => '', :text => '' })
|
end.unshift({ id: '', text: '' })
|
||||||
end
|
end
|
||||||
|
|
||||||
def articles_for_table(articles)
|
def articles_for_table(articles)
|
||||||
|
@ -23,10 +23,14 @@ module DeliveriesHelper
|
||||||
end
|
end
|
||||||
|
|
||||||
def stock_change_remove_link(stock_change_form)
|
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 = stock_change_form.hidden_field :_destroy
|
||||||
output += link_to t('deliveries.stock_change_fields.remove_article'), "#", :class => 'destroy_stock_change btn btn-small'
|
output += link_to t('deliveries.stock_change_fields.remove_article'), '#',
|
||||||
return output.html_safe
|
class: 'destroy_stock_change btn btn-small'
|
||||||
|
output.html_safe
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,11 +2,11 @@ module Finance::BalancingHelper
|
||||||
def balancing_view_partial
|
def balancing_view_partial
|
||||||
view = params[:view] || 'edit_results'
|
view = params[:view] || 'edit_results'
|
||||||
case view
|
case view
|
||||||
when 'edit_results' then
|
when 'edit_results'
|
||||||
'edit_results_by_articles'
|
'edit_results_by_articles'
|
||||||
when 'groups_overview' then
|
when 'groups_overview'
|
||||||
'shared/articles_by/groups'
|
'shared/articles_by/groups'
|
||||||
when 'articles_overview' then
|
when 'articles_overview'
|
||||||
'shared/articles_by/articles'
|
'shared/articles_by/articles'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
module Finance::InvoicesHelper
|
module Finance::InvoicesHelper
|
||||||
def format_delivery_item delivery
|
def format_delivery_item(delivery)
|
||||||
format_date(delivery.date)
|
format_date(delivery.date)
|
||||||
end
|
end
|
||||||
|
|
||||||
def format_order_item order
|
def format_order_item(order)
|
||||||
"#{format_date(order.ends)} (#{number_to_currency(order.sum)})"
|
"#{format_date(order.ends)} (#{number_to_currency(order.sum)})"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,12 +2,12 @@ module GroupOrderArticlesHelper
|
||||||
# return an edit field for a GroupOrderArticle result
|
# return an edit field for a GroupOrderArticle result
|
||||||
def group_order_article_edit_result(goa)
|
def group_order_article_edit_result(goa)
|
||||||
result = number_with_precision goa.result, strip_insignificant_zeros: true
|
result = number_with_precision goa.result, strip_insignificant_zeros: true
|
||||||
unless goa.group_order.order.finished? && current_user.role_finance?
|
if goa.group_order.order.finished? && current_user.role_finance?
|
||||||
result
|
|
||||||
else
|
|
||||||
simple_form_for goa, remote: true, html: { 'data-submit-onchange' => 'changed', class: 'delta-input' } do |f|
|
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
|
f.input_field :result, as: :delta, class: 'input-nano', data: { min: 0 }, id: "r_#{goa.id}", value: result
|
||||||
end
|
end
|
||||||
|
else
|
||||||
|
result
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
module GroupOrdersHelper
|
module GroupOrdersHelper
|
||||||
def data_to_js(ordering_data)
|
def data_to_js(ordering_data)
|
||||||
ordering_data[:order_articles].map { |id, data|
|
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]]
|
[id, data[:price], data[:unit], data[:total_price], data[:others_quantity], data[:others_tolerance],
|
||||||
}.map { |row|
|
data[:used_quantity], data[:quantity_available]]
|
||||||
|
end.map do |row|
|
||||||
"addData(#{row.join(', ')});"
|
"addData(#{row.join(', ')});"
|
||||||
}.join("\n")
|
end.join("\n")
|
||||||
end
|
end
|
||||||
|
|
||||||
# Returns a link to the page where a group_order can be edited.
|
# 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
|
path = if options[:show] && group_order
|
||||||
group_order_path(group_order)
|
group_order_path(group_order)
|
||||||
elsif 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
|
else
|
||||||
new_group_order_path(:order_id => order.id)
|
new_group_order_path(order_id: order.id)
|
||||||
end
|
end
|
||||||
options.delete(:show)
|
options.delete(:show)
|
||||||
name = block_given? ? capture(&block) : order.name
|
name = block_given? ? capture(&block) : order.name
|
||||||
|
@ -26,7 +27,7 @@ module GroupOrdersHelper
|
||||||
# Return css class names for order result table
|
# Return css class names for order result table
|
||||||
|
|
||||||
def order_article_class_name(quantity, tolerance, result)
|
def order_article_class_name(quantity, tolerance, result)
|
||||||
if (quantity + tolerance > 0)
|
if quantity + tolerance > 0
|
||||||
result > 0 ? 'success' : 'failed'
|
result > 0 ? 'success' : 'failed'
|
||||||
else
|
else
|
||||||
'ignored'
|
'ignored'
|
||||||
|
@ -45,12 +46,12 @@ module GroupOrdersHelper
|
||||||
end
|
end
|
||||||
|
|
||||||
def get_missing_units_css_class(quantity_missing)
|
def get_missing_units_css_class(quantity_missing)
|
||||||
if (quantity_missing == 1)
|
if quantity_missing == 1
|
||||||
return 'missing-few';
|
'missing-few'
|
||||||
elsif (quantity_missing == 0)
|
elsif quantity_missing == 0
|
||||||
return ''
|
''
|
||||||
else
|
else
|
||||||
return 'missing-many'
|
'missing-many'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
module OrderArticlesHelper
|
module OrderArticlesHelper
|
||||||
def article_label_with_unit(article)
|
def article_label_with_unit(article)
|
||||||
pkg_info = pkg_helper(article, plain: true)
|
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
|
||||||
end
|
end
|
||||||
|
|
|
@ -18,7 +18,7 @@ module OrdersHelper
|
||||||
|
|
||||||
def options_for_suppliers_to_select
|
def options_for_suppliers_to_select
|
||||||
options = [[I18n.t('helpers.orders.option_choose')]]
|
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 += [[I18n.t('helpers.orders.option_stock'), url_for(action: 'new', supplier_id: nil)]]
|
||||||
options_for_select(options)
|
options_for_select(options)
|
||||||
end
|
end
|
||||||
|
@ -29,13 +29,13 @@ module OrdersHelper
|
||||||
nil
|
nil
|
||||||
else
|
else
|
||||||
units_info = []
|
units_info = []
|
||||||
[:units_to_order, :units_billed, :units_received].map do |unit|
|
%i[units_to_order units_billed units_received].map do |unit|
|
||||||
if n = order_article.send(unit)
|
next unless n = order_article.send(unit)
|
||||||
line = n.to_s + ' '
|
|
||||||
line += pkg_helper(order_article.price, options) + ' ' unless n == 0
|
line = n.to_s + ' '
|
||||||
line += OrderArticle.human_attribute_name("#{unit}_short", count: n)
|
line += pkg_helper(order_article.price, options) + ' ' unless n == 0
|
||||||
units_info << line
|
line += OrderArticle.human_attribute_name("#{unit}_short", count: n)
|
||||||
end
|
units_info << line
|
||||||
end
|
end
|
||||||
units_info.join(', ').html_safe
|
units_info.join(', ').html_safe
|
||||||
end
|
end
|
||||||
|
@ -67,8 +67,8 @@ module OrdersHelper
|
||||||
def pkg_helper_icon(c = nil, options = {})
|
def pkg_helper_icon(c = nil, options = {})
|
||||||
options = { tag: 'i', class: '' }.merge(options)
|
options = { tag: 'i', class: '' }.merge(options)
|
||||||
if c.nil?
|
if c.nil?
|
||||||
c = " ".html_safe
|
c = ' '.html_safe
|
||||||
options[:class] += " icon-only"
|
options[:class] += ' icon-only'
|
||||||
end
|
end
|
||||||
content_tag(options[:tag], c, class: "package #{options[:class]}").html_safe
|
content_tag(options[:tag], c, class: "package #{options[:class]}").html_safe
|
||||||
end
|
end
|
||||||
|
@ -94,11 +94,12 @@ module OrdersHelper
|
||||||
autocomplete: 'off'
|
autocomplete: 'off'
|
||||||
|
|
||||||
if order_article.result_manually_changed?
|
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') {
|
button_tag(nil, type: :button, class: 'btn unlocker') {
|
||||||
content_tag(:i, nil, class: 'icon icon-unlock')
|
content_tag(:i, nil, class: 'icon icon-unlock')
|
||||||
} + input_html
|
} + input_html
|
||||||
}
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
input_html.html_safe
|
input_html.html_safe
|
||||||
|
@ -109,18 +110,16 @@ module OrdersHelper
|
||||||
def ordergroup_count(order)
|
def ordergroup_count(order)
|
||||||
group_orders = order.group_orders.includes(:ordergroup)
|
group_orders = order.group_orders.includes(:ordergroup)
|
||||||
txt = "#{group_orders.count} #{Ordergroup.model_name.human count: group_orders.count}"
|
txt = "#{group_orders.count} #{Ordergroup.model_name.human count: group_orders.count}"
|
||||||
if group_orders.count == 0
|
return txt if group_orders.count == 0
|
||||||
return txt
|
|
||||||
else
|
desc = group_orders.includes(:ordergroup).map { |g| g.ordergroup_name }.join(', ')
|
||||||
desc = group_orders.includes(:ordergroup).map { |g| g.ordergroup_name }.join(', ')
|
content_tag(:abbr, txt, title: desc).html_safe
|
||||||
content_tag(:abbr, txt, title: desc).html_safe
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# @param order_or_supplier [Order, Supplier] Order or supplier to link to
|
# @param order_or_supplier [Order, Supplier] Order or supplier to link to
|
||||||
# @return [String] Link to order or supplier, showing its name.
|
# @return [String] Link to order or supplier, showing its name.
|
||||||
def supplier_link(order_or_supplier)
|
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
|
link_to(order_or_supplier.name, stock_articles_path).html_safe
|
||||||
else
|
else
|
||||||
link_to(@order.supplier.name, supplier_path(@order.supplier)).html_safe
|
link_to(@order.supplier.name, supplier_path(@order.supplier)).html_safe
|
||||||
|
@ -152,7 +151,8 @@ module OrdersHelper
|
||||||
if order.stockit?
|
if order.stockit?
|
||||||
content_tag :div, t('orders.index.action_receive'), class: "btn disabled #{options[:class]}"
|
content_tag :div, t('orders.index.action_receive'), class: "btn disabled #{options[:class]}"
|
||||||
else
|
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
|
end
|
||||||
end
|
end
|
||||||
|
|
5
app/helpers/sepa_helper.rb
Normal file
5
app/helpers/sepa_helper.rb
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
module SepaHelper
|
||||||
|
def foodsoft_sepa_ready?
|
||||||
|
FoodsoftConfig[:group_order_invoices]&.[](:iban) && FoodsoftConfig[:group_order_invoices]&.[](:bic) && FoodsoftConfig[:name].present? && FoodsoftConfig[:group_order_invoices]&.[](:creditor_identifier).present?
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,8 +1,8 @@
|
||||||
module StockitHelper
|
module StockitHelper
|
||||||
def stock_article_classes(article)
|
def stock_article_classes(article)
|
||||||
class_names = []
|
class_names = []
|
||||||
class_names << "unavailable" if article.quantity_available <= 0
|
class_names << 'unavailable' if article.quantity_available <= 0
|
||||||
class_names.join(" ")
|
class_names.join(' ')
|
||||||
end
|
end
|
||||||
|
|
||||||
def link_to_stock_change_reason(stock_change)
|
def link_to_stock_change_reason(stock_change)
|
||||||
|
@ -17,8 +17,8 @@ module StockitHelper
|
||||||
|
|
||||||
def stock_article_price_hint(stock_article)
|
def stock_article_price_hint(stock_article)
|
||||||
t('simple_form.hints.stock_article.edit_stock_article.price',
|
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_link: link_to(t('stockit.form.copy_stock_article'),
|
||||||
stock_article_copy_path(stock_article),
|
stock_article_copy_path(stock_article),
|
||||||
:remote => true))
|
remote: true))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
module TasksHelper
|
module TasksHelper
|
||||||
def task_assignments(task)
|
def task_assignments(task)
|
||||||
task.assignments.map do |ass|
|
task.assignments.map do |ass|
|
||||||
content_tag :span, show_user(ass.user), :class => (ass.accepted? ? 'accepted' : 'unaccepted')
|
content_tag :span, show_user(ass.user), class: (ass.accepted? ? 'accepted' : 'unaccepted')
|
||||||
end.join(", ").html_safe
|
end.join(', ').html_safe
|
||||||
end
|
end
|
||||||
|
|
||||||
# generate colored number of still required users
|
# generate colored number of still required users
|
||||||
def highlighted_required_users(task)
|
def highlighted_required_users(task)
|
||||||
unless task.enough_users_assigned?
|
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)
|
content_tag :span, task.still_required_users, class: 'badge badge-important',
|
||||||
end
|
title: I18n.t('helpers.tasks.required_users', count: task.still_required_users)
|
||||||
end
|
end
|
||||||
|
|
||||||
def task_title(task)
|
def task_title(task)
|
||||||
|
|
|
@ -6,7 +6,7 @@ class DeltaInput < SimpleForm::Inputs::StringInput
|
||||||
options[:data] ||= {}
|
options[:data] ||= {}
|
||||||
options[:data][:delta] ||= 1
|
options[:data][:delta] ||= 1
|
||||||
options[:autocomplete] ||= 'off'
|
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
|
template.content_tag :div, class: 'delta-input input-prepend input-append' do
|
||||||
delta_button(content_tag(:i, nil, class: 'icon icon-minus'), -1, options) +
|
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'))
|
||||||
|
}
|
||||||
|
})
|
10
app/jobs/notify_group_order_invoice_job.rb
Normal file
10
app/jobs/notify_group_order_invoice_job.rb
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
class NotifyGroupOrderInvoiceJob < ApplicationJob
|
||||||
|
def perform(group_order_invoice)
|
||||||
|
ordergroup = group_order_invoice.group_order.ordergroup
|
||||||
|
ordergroup.users.each do |user|
|
||||||
|
Mailer.deliver_now_with_user_locale user do
|
||||||
|
Mailer.group_order_invoice(group_order_invoice, user)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -14,23 +14,23 @@ class AppleBar
|
||||||
def group_bar_state
|
def group_bar_state
|
||||||
if apples >= 100
|
if apples >= 100
|
||||||
'success'
|
'success'
|
||||||
|
elsif FoodsoftConfig[:stop_ordering_under].present? &&
|
||||||
|
(apples >= FoodsoftConfig[:stop_ordering_under])
|
||||||
|
'warning'
|
||||||
else
|
else
|
||||||
if FoodsoftConfig[:stop_ordering_under].present? and
|
'danger'
|
||||||
apples >= FoodsoftConfig[:stop_ordering_under]
|
|
||||||
'warning'
|
|
||||||
else
|
|
||||||
'danger'
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Use apples as percentage, but show at least 10 percent
|
# Use apples as percentage, but show at least 10 percent
|
||||||
def group_bar_width
|
def group_bar_width
|
||||||
@ordergroup.apples < 2 ? 2 : @ordergroup.apples
|
[@ordergroup.apples, 2].max
|
||||||
end
|
end
|
||||||
|
|
||||||
def mean_order_amount_per_job
|
def mean_order_amount_per_job
|
||||||
(1 / @global_avg).round rescue 0
|
(1 / @global_avg).round
|
||||||
|
rescue StandardError
|
||||||
|
0
|
||||||
end
|
end
|
||||||
|
|
||||||
def apples
|
def apples
|
|
@ -1,4 +1,4 @@
|
||||||
class ArticlesCsv < RenderCSV
|
class ArticlesCsv < RenderCsv
|
||||||
include ApplicationHelper
|
include ApplicationHelper
|
||||||
|
|
||||||
def header
|
def header
|
||||||
|
@ -16,14 +16,14 @@ class ArticlesCsv < RenderCSV
|
||||||
Article.human_attribute_name(:unit_quantity),
|
Article.human_attribute_name(:unit_quantity),
|
||||||
'',
|
'',
|
||||||
'',
|
'',
|
||||||
Article.human_attribute_name(:article_category),
|
Article.human_attribute_name(:article_category)
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
def data
|
def data
|
||||||
@object.each do |o|
|
@object.each do |o|
|
||||||
yield [
|
yield [
|
||||||
'',
|
o.availability ? I18n.t('simple_form.yes') : I18n.t('simple_form.no'),
|
||||||
o.order_number,
|
o.order_number,
|
||||||
o.name,
|
o.name,
|
||||||
o.note,
|
o.note,
|
||||||
|
@ -36,7 +36,7 @@ class ArticlesCsv < RenderCSV
|
||||||
o.unit_quantity,
|
o.unit_quantity,
|
||||||
'',
|
'',
|
||||||
'',
|
'',
|
||||||
o.article_category.try(:name),
|
o.article_category.try(:name)
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
end
|
end
|
|
@ -8,9 +8,7 @@ class BankAccountConnector
|
||||||
nil
|
nil
|
||||||
end
|
end
|
||||||
|
|
||||||
def text
|
attr_reader :text
|
||||||
@text
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
class TextField
|
class TextField
|
||||||
|
@ -24,13 +22,7 @@ class BankAccountConnector
|
||||||
nil
|
nil
|
||||||
end
|
end
|
||||||
|
|
||||||
def name
|
attr_reader :name, :value
|
||||||
@name
|
|
||||||
end
|
|
||||||
|
|
||||||
def value
|
|
||||||
@value
|
|
||||||
end
|
|
||||||
|
|
||||||
def label
|
def label
|
||||||
@label || @name.to_s
|
@label || @name.to_s
|
||||||
|
@ -49,14 +41,14 @@ class BankAccountConnector
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@registered_classes = Set.new
|
@registered_classes = Set.new
|
||||||
|
|
||||||
def self.register(klass)
|
def self.register(klass)
|
||||||
@@registered_classes.add klass
|
@registered_classes.add klass
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.find(iban)
|
def self.find(iban)
|
||||||
@@registered_classes.each do |klass|
|
@registered_classes.each do |klass|
|
||||||
return klass if klass.handles(iban)
|
return klass if klass.handles(iban)
|
||||||
end
|
end
|
||||||
nil
|
nil
|
||||||
|
@ -73,17 +65,7 @@ class BankAccountConnector
|
||||||
@bank_account.iban
|
@bank_account.iban
|
||||||
end
|
end
|
||||||
|
|
||||||
def auto_submit
|
attr_reader :auto_submit, :controls, :count
|
||||||
@auto_submit
|
|
||||||
end
|
|
||||||
|
|
||||||
def controls
|
|
||||||
@controls
|
|
||||||
end
|
|
||||||
|
|
||||||
def count
|
|
||||||
@count
|
|
||||||
end
|
|
||||||
|
|
||||||
def text(data)
|
def text(data)
|
||||||
@controls += [TextItem.new(data)]
|
@controls += [TextItem.new(data)]
|
||||||
|
@ -142,11 +124,9 @@ class BankAccountConnector
|
||||||
@bank_account.save!
|
@bank_account.save!
|
||||||
end
|
end
|
||||||
|
|
||||||
def load(data)
|
def load(data); end
|
||||||
end
|
|
||||||
|
|
||||||
def dump
|
def dump; end
|
||||||
end
|
|
||||||
|
|
||||||
def t(key, args = {})
|
def t(key, args = {})
|
||||||
return t(".fields.#{key}") unless key.is_a? String
|
return t(".fields.#{key}") unless key.is_a? String
|
|
@ -17,16 +17,16 @@ class BankAccountInformationImporter
|
||||||
ret = 0
|
ret = 0
|
||||||
booked.each do |t|
|
booked.each do |t|
|
||||||
amount = parse_account_information_amount t[:transactionAmount]
|
amount = parse_account_information_amount t[:transactionAmount]
|
||||||
entityName = amount < 0 ? t[:creditorName] : t[:debtorName]
|
entity_name = amount < 0 ? t[:creditorName] : t[:debtorName]
|
||||||
entityAccount = amount < 0 ? t[:creditorAccount] : t[:debtorAccount]
|
entity_account = amount < 0 ? t[:creditorAccount] : t[:debtorAccount]
|
||||||
reference = [t[:endToEndId], t[:remittanceInformationUnstructured]].join("\n").strip
|
reference = [t[:endToEndId], t[:remittanceInformationUnstructured]].join("\n").strip
|
||||||
|
|
||||||
@bank_account.bank_transactions.where(external_id: t[:transactionId]).first_or_create.update({
|
@bank_account.bank_transactions.where(external_id: t[:transactionId]).first_or_create.update({
|
||||||
date: t[:bookingDate],
|
date: t[:bookingDate],
|
||||||
amount: amount,
|
amount: amount,
|
||||||
iban: entityAccount && entityAccount[:iban],
|
iban: entity_account && entity_account[:iban],
|
||||||
reference: reference,
|
reference: reference,
|
||||||
text: entityName,
|
text: entity_name,
|
||||||
receipt: t[:additionalInformation]
|
receipt: t[:additionalInformation]
|
||||||
})
|
})
|
||||||
ret += 1
|
ret += 1
|
||||||
|
@ -34,7 +34,7 @@ class BankAccountInformationImporter
|
||||||
|
|
||||||
balances = (data[:balances] ? data[:balances].map { |b| [b[:balanceType], b[:balanceAmount]] } : []).to_h
|
balances = (data[:balances] ? data[:balances].map { |b| [b[:balanceType], b[:balanceAmount]] } : []).to_h
|
||||||
balance = balances.values.first
|
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]
|
value = balances[type]
|
||||||
if value
|
if value
|
||||||
balance = value
|
balance = value
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue