mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-01-12 18:36:49 +00:00
Compare commits
1 Commits
v5.1.6
...
RachL-patc
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b5020cc740 |
@@ -6,9 +6,9 @@
|
||||
# cp .env.development .env.local
|
||||
|
||||
# Locale for translation. Using a locale other than `en` tests the
|
||||
# successful fallback to `en`. To see up-to-date text used in production,
|
||||
# set another locale in a local env file.
|
||||
LOCALE="en_TST"
|
||||
# successful fallback to `en`. You will also see up-to-date text used
|
||||
# in production
|
||||
LOCALE="en_AU"
|
||||
|
||||
VERBOSE_QUERY_LOGS=true
|
||||
|
||||
@@ -16,9 +16,8 @@ SECRET_TOKEN="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
||||
|
||||
OFN_REDIS_URL="redis://localhost:6379/1"
|
||||
OFN_REDIS_JOBS_URL="redis://localhost:6379/2"
|
||||
OFN_REDIS_CABLE_URL="redis://localhost:6379/0"
|
||||
|
||||
SITE_URL="localhost:3000"
|
||||
SITE_URL="0.0.0.0:3000"
|
||||
|
||||
# Deactivate rack-timeout in development.
|
||||
# https://github.com/zombocom/rack-timeout#configuring
|
||||
|
||||
17
.env.test
17
.env.test
@@ -1,17 +1,8 @@
|
||||
# ENV vars for the test environment
|
||||
# Override locally with `.env.test.local`
|
||||
|
||||
# Test env specific variables
|
||||
#
|
||||
# Adjust this to your computer. When you start test-driven development, you may
|
||||
# want to reduce this value to avoid waiting for a test that you expect to fail.
|
||||
CAPYBARA_MAX_WAIT_TIME="10"
|
||||
|
||||
# General app specific variables
|
||||
|
||||
# Locale for translation. Using a locale other than `en` tests the
|
||||
# successful fallback to `en`.
|
||||
LOCALE="en_TST"
|
||||
# Locale for translation.
|
||||
LOCALE="en_TEST"
|
||||
|
||||
OFN_REDIS_JOBS_URL="redis://localhost:6379/2"
|
||||
|
||||
@@ -24,10 +15,6 @@ STRIPE_PUBLIC_TEST_API_KEY="bogus_stripe_publishable_key"
|
||||
|
||||
SITE_URL="test.host"
|
||||
|
||||
# OIDC Settings for DFC authentication
|
||||
# Find secrets in BitWarden.
|
||||
# To get a refresh token: log into the OIDC provider, connect your OFN user to it at /admin/oidc_settings, then copy the token from the database:
|
||||
# ./bin/rails runner 'puts "OPENID_REFRESH_TOKEN=\"#{OidcAccount.last.refresh_token}\""'
|
||||
OPENID_APP_ID="test-provider"
|
||||
OPENID_APP_SECRET="dummy-openid-app-secret-token"
|
||||
OPENID_REFRESH_TOKEN="dummy-refresh-token"
|
||||
|
||||
2
.github/ISSUE_TEMPLATE/release.md
vendored
2
.github/ISSUE_TEMPLATE/release.md
vendored
@@ -13,7 +13,6 @@ assignees: ''
|
||||
- [ ] Include translations: `script/release/update_locales`
|
||||
- You need the [Transifex Client] installed on your local dev environement to run the script.
|
||||
- [ ] Increment version number: `git push upstream HEAD:refs/tags/vX.Y.Z`
|
||||
Check for [minor or major breaking changes]
|
||||
- Major: if server changes are required (eg. provision with ofn-install)
|
||||
- Minor: larger change that is irreversible (eg. migration deleting data)
|
||||
- Patch: all others. Shortcut: `script/release/tag`
|
||||
@@ -57,4 +56,3 @@ The full process is described at https://github.com/openfoodfoundation/openfoodn
|
||||
[Create issue]: https://github.com/openfoodfoundation/openfoodnetwork/issues/new?assignees=&labels=&projects=&template=release.md&title=Release
|
||||
[#delivery-circle]: https://openfoodnetwork.slack.com/archives/C01T75H6G0Z
|
||||
[Transifex Client]: https://developers.transifex.com/docs/cli
|
||||
[minor or major breaking changes]: https://github.com/openfoodfoundation/openfoodnetwork/pulls?q=label%3A%22breaking+change%22%2C%22major+breaking+change%22
|
||||
6
.github/release.yml
vendored
6
.github/release.yml
vendored
@@ -14,12 +14,6 @@ changelog:
|
||||
- technical changes only
|
||||
- user facing changes
|
||||
|
||||
# These will require a minor or major version increment
|
||||
- title: "Significant changes 🚀"
|
||||
labels:
|
||||
- breaking change
|
||||
- major breaking change
|
||||
|
||||
# Posted in advance for #instance-managers
|
||||
- title: "User-facing changes 👀"
|
||||
labels:
|
||||
|
||||
51
.github/workflows/brakeman-analysis.yml
vendored
Normal file
51
.github/workflows/brakeman-analysis.yml
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
# This workflow integrates Brakeman with GitHub's Code Scanning feature
|
||||
# Brakeman is a static analysis security vulnerability scanner for Ruby on Rails applications
|
||||
|
||||
name: Brakeman Scan
|
||||
|
||||
# This section configures the trigger for the workflow. Feel free to customize depending on your convention
|
||||
on:
|
||||
push:
|
||||
branches: [ "master" ]
|
||||
pull_request:
|
||||
branches: [ "master" ]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
brakeman-scan:
|
||||
permissions:
|
||||
contents: read # for actions/checkout to fetch code
|
||||
security-events: write # for github/codeql-action/upload-sarif to upload SARIF results
|
||||
name: Brakeman Scan
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
# Checkout the repository to the GitHub Actions runner
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
# Customize the ruby version depending on your needs
|
||||
- name: Setup Ruby
|
||||
uses: ruby/setup-ruby@v1
|
||||
with:
|
||||
ruby-version: '2.7'
|
||||
|
||||
- name: Setup Brakeman
|
||||
env:
|
||||
BRAKEMAN_VERSION: '5.4.0'
|
||||
run: |
|
||||
gem install brakeman --version $BRAKEMAN_VERSION
|
||||
|
||||
# Execute Brakeman CLI and generate a SARIF output with the security issues identified during the analysis
|
||||
- name: Scan
|
||||
continue-on-error: true
|
||||
run: |
|
||||
git show --no-patch # the commit being tested (which is often a merge due to actions/checkout@v3)
|
||||
brakeman -f sarif -o output.sarif.json .
|
||||
|
||||
# Upload the SARIF file generated in the previous step
|
||||
- name: Upload SARIF
|
||||
uses: github/codeql-action/upload-sarif@v2
|
||||
with:
|
||||
sarif_file: output.sarif.json
|
||||
227
.github/workflows/build.yml
vendored
227
.github/workflows/build.yml
vendored
@@ -17,7 +17,85 @@ permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
controllers_and_models:
|
||||
controllers:
|
||||
runs-on: ubuntu-22.04
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:10
|
||||
ports: ["5432:5432"]
|
||||
options: >-
|
||||
--health-cmd pg_isready
|
||||
--health-interval 10s
|
||||
--health-timeout 5s
|
||||
--health-retries 5
|
||||
env:
|
||||
POSTGRES_DB: open_food_network_test
|
||||
POSTGRES_USER: ofn
|
||||
POSTGRES_PASSWORD: f00d
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
# [n] - where the n is a number of parallel jobs you want to run your tests on.
|
||||
# Use a higher number if you have slow tests to split them between more parallel jobs.
|
||||
# Remember to update the value of the `ci_node_index` below to (0..n-1).
|
||||
ci_node_total: [8]
|
||||
# Indexes for parallel jobs (starting from zero).
|
||||
# E.g. use [0, 1] for 2 parallel jobs, [0, 1, 2] for 3 parallel jobs, etc.
|
||||
ci_node_index: [0, 1, 2, 3, 4, 5, 6, 7]
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Setup redis
|
||||
uses: supercharge/redis-github-action@1.4.0
|
||||
with:
|
||||
redis-version: 6
|
||||
|
||||
- name: Set up Ruby
|
||||
uses: ruby/setup-ruby@v1
|
||||
with:
|
||||
bundler-cache: true # runs 'bundle install' and caches installed gems automatically
|
||||
|
||||
# JS is required in order for webpacker to compile, in order to render templates containing image urls
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version-file: .node-version
|
||||
cache: yarn
|
||||
|
||||
- name: Install JS dependencies
|
||||
run: yarn install --frozen-lockfile
|
||||
|
||||
- name: Set up database
|
||||
run: |
|
||||
bin/rake db:create db:schema:load
|
||||
|
||||
- name: Run tests
|
||||
env:
|
||||
KNAPSACK_PRO_TEST_SUITE_TOKEN_RSPEC: 864ef557d85ea8e603e086c0387d5154
|
||||
KNAPSACK_PRO_CI_NODE_TOTAL: ${{ matrix.ci_node_total }}
|
||||
KNAPSACK_PRO_CI_NODE_INDEX: ${{ matrix.ci_node_index }}
|
||||
KNAPSACK_PRO_LOG_LEVEL: info
|
||||
# if you use Knapsack Pro Queue Mode you must set below env variable
|
||||
# to be able to retry CI build and run previously recorded tests
|
||||
# https://github.com/KnapsackPro/knapsack_pro-ruby#knapsack_pro_fixed_queue_split-remember-queue-split-on-retry-ci-node
|
||||
# KNAPSACK_PRO_FIXED_QUEUE_SPLIT: false
|
||||
# RSpec split test files by test examples feature - it's optional
|
||||
# https://knapsackpro.com/faq/question/how-to-split-slow-rspec-test-files-by-test-examples-by-individual-it
|
||||
#KNAPSACK_PRO_RSPEC_SPLIT_BY_TEST_EXAMPLES: true
|
||||
KNAPSACK_PRO_TEST_FILE_PATTERN: "{spec/controllers/**/*_spec.rb}"
|
||||
run: |
|
||||
git show --no-patch # the commit being tested (which is often a merge due to actions/checkout@v3)
|
||||
bin/rake knapsack_pro:rspec
|
||||
|
||||
- name: Save SimpleCov file
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: simplecov-chunk-controllers-${{ matrix.ci_node_index }}
|
||||
path: coverage/*.*
|
||||
retention-days: 2 # doesn't need to be long, because it's the combined results that matter
|
||||
if-no-files-found: ignore
|
||||
include-hidden-files: true
|
||||
|
||||
models:
|
||||
runs-on: ubuntu-22.04
|
||||
services:
|
||||
postgres:
|
||||
@@ -55,22 +133,13 @@ jobs:
|
||||
with:
|
||||
bundler-cache: true # runs 'bundle install' and caches installed gems automatically
|
||||
|
||||
# JS is required in order for webpacker to compile, in order to render templates containing image urls
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version-file: .node-version
|
||||
cache: yarn
|
||||
|
||||
- name: Install JS dependencies
|
||||
run: yarn install --frozen-lockfile
|
||||
|
||||
- name: Set up database
|
||||
run: |
|
||||
bin/rails db:create db:schema:load
|
||||
bin/rake db:create db:schema:load
|
||||
|
||||
- name: Run tests
|
||||
env:
|
||||
KNAPSACK_PRO_TEST_SUITE_TOKEN_RSPEC: 864ef557d85ea8e603e086c0387d5154
|
||||
KNAPSACK_PRO_TEST_SUITE_TOKEN_RSPEC: 09476e2ce491c12083df62768667c674
|
||||
KNAPSACK_PRO_CI_NODE_TOTAL: ${{ matrix.ci_node_total }}
|
||||
KNAPSACK_PRO_CI_NODE_INDEX: ${{ matrix.ci_node_index }}
|
||||
KNAPSACK_PRO_LOG_LEVEL: info
|
||||
@@ -81,21 +150,20 @@ jobs:
|
||||
# RSpec split test files by test examples feature - it's optional
|
||||
# https://knapsackpro.com/faq/question/how-to-split-slow-rspec-test-files-by-test-examples-by-individual-it
|
||||
#KNAPSACK_PRO_RSPEC_SPLIT_BY_TEST_EXAMPLES: true
|
||||
KNAPSACK_PRO_TEST_FILE_PATTERN: "{spec/controllers/**/*_spec.rb,spec/models/**/*_spec.rb}"
|
||||
KNAPSACK_PRO_TEST_FILE_PATTERN: "{spec/models/**/*_spec.rb}"
|
||||
run: |
|
||||
git show --no-patch # the commit being tested (which is often a merge due to actions/checkout@v3)
|
||||
bin/rails assets:precompile knapsack_pro:rspec
|
||||
bin/rake knapsack_pro:rspec
|
||||
|
||||
- name: Save SimpleCov file
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: simplecov-chunk-controllers-${{ matrix.ci_node_index }}
|
||||
name: simplecov-chunk-models-${{ matrix.ci_node_index }}
|
||||
path: coverage/*.*
|
||||
retention-days: 2 # doesn't need to be long, because it's the combined results that matter
|
||||
if-no-files-found: ignore
|
||||
include-hidden-files: true
|
||||
|
||||
system:
|
||||
system_admin:
|
||||
runs-on: ubuntu-22.04
|
||||
services:
|
||||
postgres:
|
||||
@@ -116,10 +184,10 @@ jobs:
|
||||
# [n] - where the n is a number of parallel jobs you want to run your tests on.
|
||||
# Use a higher number if you have slow tests to split them between more parallel jobs.
|
||||
# Remember to update the value of the `ci_node_index` below to (0..n-1).
|
||||
ci_node_total: [19]
|
||||
ci_node_total: [14]
|
||||
# Indexes for parallel jobs (starting from zero).
|
||||
# E.g. use [0, 1] for 2 parallel jobs, [0, 1, 2] for 3 parallel jobs, etc.
|
||||
ci_node_index: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18]
|
||||
ci_node_index: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
@@ -143,7 +211,7 @@ jobs:
|
||||
|
||||
- name: Set up database
|
||||
run: |
|
||||
bin/rails db:create db:schema:load
|
||||
bin/rake db:create db:schema:load
|
||||
|
||||
- name: Run tests
|
||||
|
||||
@@ -159,15 +227,15 @@ jobs:
|
||||
# RSpec split test files by test examples feature - it's optional
|
||||
# https://knapsackpro.com/faq/question/how-to-split-slow-rspec-test-files-by-test-examples-by-individual-it
|
||||
#KNAPSACK_PRO_RSPEC_SPLIT_BY_TEST_EXAMPLES: true
|
||||
KNAPSACK_PRO_TEST_FILE_PATTERN: "{spec/system/admin/**/*_spec.rb,spec/system/consumer/**/*_spec.rb}"
|
||||
KNAPSACK_PRO_TEST_FILE_PATTERN: "{spec/system/admin/**/*_spec.rb}"
|
||||
|
||||
run: |
|
||||
bin/rails assets:precompile knapsack_pro:queue:rspec
|
||||
bin/rake knapsack_pro:queue:rspec
|
||||
|
||||
- name: Save SimpleCov file
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: simplecov-chunk-system-${{ matrix.ci_node_index }}
|
||||
name: simplecov-chunk-system-admin-${{ matrix.ci_node_index }}
|
||||
path: coverage/*.*
|
||||
retention-days: 2 # doesn't need to be long, because it's the combined results that matter
|
||||
if-no-files-found: ignore
|
||||
@@ -177,7 +245,94 @@ jobs:
|
||||
if: failure()
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: failed-system_${{ matrix.ci_node_index }}-tests-screenshots
|
||||
name: failed-admin_${{ matrix.ci_node_index }}-tests-screenshots
|
||||
path: tmp/capybara/screenshots/*.png
|
||||
retention-days: 7
|
||||
if-no-files-found: ignore
|
||||
|
||||
system_consumer:
|
||||
runs-on: ubuntu-22.04
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:10
|
||||
ports: ["5432:5432"]
|
||||
options: >-
|
||||
--health-cmd pg_isready
|
||||
--health-interval 10s
|
||||
--health-timeout 5s
|
||||
--health-retries 5
|
||||
env:
|
||||
POSTGRES_DB: open_food_network_test
|
||||
POSTGRES_USER: ofn
|
||||
POSTGRES_PASSWORD: f00d
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
# [n] - where the n is a number of parallel jobs you want to run your tests on.
|
||||
# Use a higher number if you have slow tests to split them between more parallel jobs.
|
||||
# Remember to update the value of the `ci_node_index` below to (0..n-1).
|
||||
ci_node_total: [12]
|
||||
# Indexes for parallel jobs (starting from zero).
|
||||
# E.g. use [0, 1] for 2 parallel jobs, [0, 1, 2] for 3 parallel jobs, etc.
|
||||
ci_node_index: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Setup redis
|
||||
uses: supercharge/redis-github-action@1.4.0
|
||||
with:
|
||||
redis-version: 6
|
||||
|
||||
- name: Set up Ruby
|
||||
uses: ruby/setup-ruby@v1
|
||||
with:
|
||||
bundler-cache: true # runs 'bundle install' and caches installed gems automatically
|
||||
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version-file: .node-version
|
||||
cache: yarn
|
||||
|
||||
- name: Install JS dependencies
|
||||
run: yarn install --frozen-lockfile
|
||||
|
||||
- name: Set up database
|
||||
run: |
|
||||
bin/rake db:create db:schema:load
|
||||
|
||||
- name: Run tests
|
||||
|
||||
env:
|
||||
KNAPSACK_PRO_TEST_SUITE_TOKEN_RSPEC: e52bd4390c853e6c5bdfe4d0334586c1
|
||||
KNAPSACK_PRO_CI_NODE_TOTAL: ${{ matrix.ci_node_total }}
|
||||
KNAPSACK_PRO_CI_NODE_INDEX: ${{ matrix.ci_node_index }}
|
||||
KNAPSACK_PRO_LOG_LEVEL: info
|
||||
# if you use Knapsack Pro Queue Mode you must set below env variable
|
||||
# to be able to retry CI build and run previously recorded tests
|
||||
# https://github.com/KnapsackPro/knapsack_pro-ruby#knapsack_pro_fixed_queue_split-remember-queue-split-on-retry-ci-node
|
||||
KNAPSACK_PRO_FIXED_QUEUE_SPLIT: true
|
||||
# RSpec split test files by test examples feature - it's optional
|
||||
# https://knapsackpro.com/faq/question/how-to-split-slow-rspec-test-files-by-test-examples-by-individual-it
|
||||
#KNAPSACK_PRO_RSPEC_SPLIT_BY_TEST_EXAMPLES: true
|
||||
KNAPSACK_PRO_TEST_FILE_PATTERN: "{spec/system/consumer/**/*_spec.rb}"
|
||||
|
||||
run: |
|
||||
bin/rake knapsack_pro:queue:rspec
|
||||
|
||||
- name: Save SimpleCov file
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: simplecov-chunk-system-consumer-${{ matrix.ci_node_index }}
|
||||
path: coverage/*.*
|
||||
retention-days: 2 # doesn't need to be long, because it's the combined results that matter
|
||||
if-no-files-found: ignore
|
||||
include-hidden-files: true
|
||||
|
||||
- name: Archive failed tests screenshots
|
||||
if: failure()
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: failed-consumer_${{ matrix.ci_node_index }}-tests-screenshots
|
||||
path: tmp/capybara/screenshots/*.png
|
||||
retention-days: 7
|
||||
if-no-files-found: ignore
|
||||
@@ -231,7 +386,7 @@ jobs:
|
||||
|
||||
- name: Set up database
|
||||
run: |
|
||||
bin/rails db:create db:schema:load
|
||||
bin/rake db:create db:schema:load
|
||||
|
||||
- name: Run tests
|
||||
|
||||
@@ -250,7 +405,7 @@ jobs:
|
||||
KNAPSACK_PRO_TEST_FILE_PATTERN: "{spec/lib/**/*_spec.rb,spec/migrations/**/*_spec.rb,spec/serializers/**/*_spec.rb,engines/**/*_spec.rb}"
|
||||
|
||||
run: |
|
||||
bin/rails assets:precompile knapsack_pro:rspec
|
||||
bin/rake knapsack_pro:rspec
|
||||
|
||||
- name: Save SimpleCov file
|
||||
uses: actions/upload-artifact@v4
|
||||
@@ -282,10 +437,10 @@ jobs:
|
||||
# [n] - where the n is a number of parallel jobs you want to run your tests on.
|
||||
# Use a higher number if you have slow tests to split them between more parallel jobs.
|
||||
# Remember to update the value of the `ci_node_index` below to (0..n-1).
|
||||
ci_node_total: [3]
|
||||
ci_node_total: [5]
|
||||
# Indexes for parallel jobs (starting from zero).
|
||||
# E.g. use [0, 1] for 2 parallel jobs, [0, 1, 2] for 3 parallel jobs, etc.
|
||||
ci_node_index: [0, 1, 2]
|
||||
ci_node_index: [0, 1, 2, 3, 4]
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
@@ -310,7 +465,7 @@ jobs:
|
||||
|
||||
- name: Set up database
|
||||
run: |
|
||||
bin/rails db:create db:schema:load
|
||||
bin/rake db:create db:schema:load
|
||||
|
||||
- name: Run tests
|
||||
env:
|
||||
@@ -327,7 +482,7 @@ jobs:
|
||||
#KNAPSACK_PRO_RSPEC_SPLIT_BY_TEST_EXAMPLES: true
|
||||
KNAPSACK_PRO_TEST_FILE_EXCLUDE_PATTERN: "{engines/**/*_spec.rb,spec/models/**/*_spec.rb,spec/controllers/**/*_spec.rb,spec/serializers/**/*_spec.rb,spec/lib/**/*_spec.rb,spec/migrations/**/*_spec.rb,spec/system/**/*_spec.rb}"
|
||||
run: |
|
||||
bin/rails assets:precompile knapsack_pro:rspec
|
||||
bin/rake knapsack_pro:rspec
|
||||
|
||||
- name: Save SimpleCov file
|
||||
uses: actions/upload-artifact@v4
|
||||
@@ -379,9 +534,11 @@ jobs:
|
||||
collate_simplecov_results:
|
||||
runs-on: ubuntu-22.04
|
||||
needs:
|
||||
- controllers_and_models
|
||||
- controllers
|
||||
- models
|
||||
- engines
|
||||
- system
|
||||
- system_admin
|
||||
- system_consumer
|
||||
- test_the_rest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
@@ -396,6 +553,7 @@ jobs:
|
||||
with:
|
||||
pattern: simplecov-chunk-*
|
||||
path: tmp/simplecov
|
||||
merge-multiple: true
|
||||
|
||||
- name: collate results from each of the workers
|
||||
run: bundle exec rake 'simplecov:collate_results[tmp/simplecov]'
|
||||
@@ -408,8 +566,3 @@ jobs:
|
||||
retention-days: 7
|
||||
if-no-files-found: ignore
|
||||
include-hidden-files: true
|
||||
- name: Compare SimpleCov results with Undercover
|
||||
run: |
|
||||
git fetch --no-tags origin master:master
|
||||
bundle exec undercover
|
||||
if: ${{ github.ref != 'refs/heads/master' }} # Does not run on master, as we can't fetch master in the master branch
|
||||
|
||||
43
.github/workflows/linters.yml
vendored
43
.github/workflows/linters.yml
vendored
@@ -3,32 +3,18 @@ on: [push, pull_request]
|
||||
permissions:
|
||||
contents: read # to fetch code (actions/checkout)
|
||||
jobs:
|
||||
lint:
|
||||
name: prettier and rubocop
|
||||
rubocop:
|
||||
name: runner / rubocop
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version-file: .node-version
|
||||
- name: Install JS dependencies
|
||||
run: yarn install --frozen-lockfile
|
||||
|
||||
- uses: ruby/setup-ruby@v1
|
||||
with:
|
||||
bundler-cache: true # runs 'bundle install' and caches installed gems automatically
|
||||
|
||||
- run: git show --no-patch # the commit being tested (which is often a merge due to actions/checkout@v3)
|
||||
|
||||
- name: prettier
|
||||
uses: EPMatt/reviewdog-action-prettier@v1
|
||||
with:
|
||||
github_token: ${{ secrets.github_token }}
|
||||
reporter: github-pr-check
|
||||
level: error
|
||||
fail_on_error: true
|
||||
|
||||
- name: rubocop
|
||||
uses: reviewdog/action-rubocop@v2
|
||||
with:
|
||||
@@ -38,4 +24,27 @@ jobs:
|
||||
level: error
|
||||
filter_mode: nofilter
|
||||
use_bundler: true
|
||||
fail_level: any
|
||||
fail_on_error: true
|
||||
prettier:
|
||||
name: runner / prettier
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version-file: .node-version
|
||||
|
||||
- name: Install JS dependencies
|
||||
run: yarn install --frozen-lockfile
|
||||
|
||||
- run: git show --no-patch # the commit being tested (which is often a merge due to actions/checkout@v3)
|
||||
|
||||
- name: prettier
|
||||
uses: EPMatt/reviewdog-action-prettier@v1
|
||||
with:
|
||||
github_token: ${{ secrets.github_token }}
|
||||
reporter: github-pr-check
|
||||
level: error
|
||||
fail_on_error: true
|
||||
|
||||
51
.github/workflows/mapi.yml
vendored
Normal file
51
.github/workflows/mapi.yml
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
name: 'Mayhem for API'
|
||||
on: workflow_dispatch
|
||||
permissions:
|
||||
contents: read # to fetch code (actions/checkout)
|
||||
jobs:
|
||||
test:
|
||||
permissions:
|
||||
contents: read # to fetch code (actions/checkout)
|
||||
security-events: write # to upload SARIF results (github/codeql-action/upload-sarif)
|
||||
if: ${{ github.repository_owner == 'openfoodfoundation' }}
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: true
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- run: docker/build
|
||||
- run: docker compose up --detach
|
||||
- run: until curl -f -s http://localhost:3000; do echo "waiting for api server"; sleep 1; done
|
||||
- run: docker compose exec -T db psql postgresql://ofn:f00d@localhost:5432/open_food_network_dev --command="update spree_users set spree_api_key='testing' where login='ofn@example.com'"
|
||||
# equivalent to Flipper.enable(:api_v1)
|
||||
- run: docker compose exec -T db psql postgresql://ofn:f00d@localhost:5432/open_food_network_dev --command="insert into flipper_features (key, created_at, updated_at) values ('api_v1', localtimestamp, localtimestamp)"
|
||||
- run: docker compose exec -T db psql postgresql://ofn:f00d@localhost:5432/open_food_network_dev --command="insert into flipper_gates (feature_key, key, value, created_at, updated_at) values ('api_v1', 'boolean', 'true', localtimestamp, localtimestamp)"
|
||||
|
||||
# Run Mayhem for API
|
||||
- name: Run Mayhem for API
|
||||
uses: ForAllSecure/mapi-action@v1
|
||||
continue-on-error: true
|
||||
with:
|
||||
mapi-token: ${{ secrets.MAPI_TOKEN }}
|
||||
api-url: http://localhost:3000
|
||||
api-spec: swagger/v1.yaml
|
||||
target: openfoodfoundation/openfoodnetwork
|
||||
duration: 1min
|
||||
sarif-report: mapi.sarif
|
||||
html-report: mapi.html
|
||||
run-args: |
|
||||
--header-auth
|
||||
X-Api-Token: testing
|
||||
|
||||
# Archive HTML report
|
||||
- name: Archive Mayhem for API report
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: mapi-report
|
||||
path: mapi.html
|
||||
|
||||
# Upload SARIF file (only available on public repos or github enterprise)
|
||||
- name: Upload SARIF file
|
||||
uses: github/codeql-action/upload-sarif@v2
|
||||
with:
|
||||
sarif_file: mapi.sarif
|
||||
@@ -3,14 +3,10 @@
|
||||
# These are the rules we agreed upon and we work towards.
|
||||
AllCops:
|
||||
NewCops: enable
|
||||
MigratedSchemaVersion: "20250111000000"
|
||||
Exclude:
|
||||
- bin/**/*
|
||||
- db/**/*
|
||||
- config/**/*
|
||||
- db/bad_migrations/*
|
||||
- db/migrate/201*
|
||||
- db/migrate/202[0-4]*
|
||||
- db/schema.rb
|
||||
- script/**/*
|
||||
- vendor/**/*
|
||||
- node_modules/**/*
|
||||
@@ -102,8 +98,6 @@ Naming/VariableNumber:
|
||||
- street_address_2
|
||||
AllowedPatterns:
|
||||
- _v[\d]+
|
||||
# Cf. conversation https://github.com/openfoodfoundation/openfoodnetwork/pull/13306#pullrequestreview-2831644286
|
||||
- menu_[\d]
|
||||
|
||||
Rails/ApplicationRecord:
|
||||
Exclude:
|
||||
@@ -117,10 +111,6 @@ Rails/ApplicationRecord:
|
||||
Rails/HasAndBelongsToMany:
|
||||
Enabled: false
|
||||
|
||||
# Cf. conversation https://github.com/openfoodfoundation/openfoodnetwork/pull/13251
|
||||
Rails/LexicallyScopedActionFilter:
|
||||
Enabled: false
|
||||
|
||||
Rails/OutputSafety:
|
||||
Exclude:
|
||||
- spec/**/*
|
||||
|
||||
@@ -6,6 +6,85 @@
|
||||
# Note that changes in the inspected code, or installation of new
|
||||
# versions of RuboCop, may require this file to be generated again.
|
||||
|
||||
# Offense count: 1
|
||||
# This cop supports safe autocorrection (--autocorrect).
|
||||
Layout/EmptyLines:
|
||||
Exclude:
|
||||
- 'app/services/products_renderer.rb'
|
||||
|
||||
# Offense count: 16
|
||||
# Configuration parameters: AllowComments, AllowEmptyLambdas.
|
||||
Lint/EmptyBlock:
|
||||
Exclude:
|
||||
- 'engines/catalog/config/routes.rb'
|
||||
- 'spec/components/distributor_title_component_spec.rb'
|
||||
- 'spec/components/example_component_spec.rb'
|
||||
- 'spec/controllers/admin/subscription_line_items_controller_spec.rb'
|
||||
- 'spec/controllers/api/v0/shipments_controller_spec.rb'
|
||||
- 'spec/controllers/concerns/extra_fields_spec.rb'
|
||||
- 'spec/factories.rb'
|
||||
- 'spec/factories/enterprise_factory.rb'
|
||||
- 'spec/jobs/order_cycle_opened_job_spec.rb'
|
||||
- 'spec/jobs/subscription_placement_job_spec.rb'
|
||||
- 'spec/models/product_import/entry_validator_spec.rb'
|
||||
|
||||
# Offense count: 4
|
||||
# Configuration parameters: AllowComments.
|
||||
Lint/EmptyClass:
|
||||
Exclude:
|
||||
- 'spec/lib/reports/report_loader_spec.rb'
|
||||
|
||||
# Offense count: 1
|
||||
# Configuration parameters: AllowComments.
|
||||
Lint/EmptyFile:
|
||||
Exclude:
|
||||
- 'spec/lib/open_food_network/enterprise_injection_data_spec.rb'
|
||||
|
||||
# Offense count: 2
|
||||
Lint/FloatComparison:
|
||||
Exclude:
|
||||
- 'app/models/product_import/entry_validator.rb'
|
||||
- 'app/models/spree/gateway/pay_pal_express.rb'
|
||||
|
||||
# Offense count: 1
|
||||
Lint/IneffectiveAccessModifier:
|
||||
Exclude:
|
||||
- 'app/models/spree/user.rb'
|
||||
|
||||
# Offense count: 1
|
||||
Lint/NoReturnInBeginEndBlocks:
|
||||
Exclude:
|
||||
- 'app/controllers/payment_gateways/stripe_controller.rb'
|
||||
|
||||
# Offense count: 4
|
||||
# This cop supports unsafe autocorrection (--autocorrect-all).
|
||||
Lint/RedundantDirGlobSort:
|
||||
Exclude:
|
||||
- 'engines/catalog/spec/spec_helper.rb'
|
||||
- 'engines/dfc_provider/spec/spec_helper.rb'
|
||||
- 'spec/base_spec_helper.rb'
|
||||
- 'spec/system_helper.rb'
|
||||
|
||||
# Offense count: 1
|
||||
# This cop supports unsafe autocorrection (--autocorrect-all).
|
||||
# Configuration parameters: AllowedMethods.
|
||||
# AllowedMethods: instance_of?, kind_of?, is_a?, eql?, respond_to?, equal?, presence, present?
|
||||
Lint/RedundantSafeNavigation:
|
||||
Exclude:
|
||||
- 'app/models/spree/payment.rb'
|
||||
|
||||
# Offense count: 1
|
||||
Lint/SelfAssignment:
|
||||
Exclude:
|
||||
- 'app/models/spree/order/checkout.rb'
|
||||
|
||||
# Offense count: 1
|
||||
# This cop supports unsafe autocorrection (--autocorrect-all).
|
||||
# Configuration parameters: AutoCorrect.
|
||||
Lint/UselessMethodDefinition:
|
||||
Exclude:
|
||||
- 'app/models/spree/gateway.rb'
|
||||
|
||||
# Offense count: 24
|
||||
# Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes, Max.
|
||||
Metrics/AbcSize:
|
||||
@@ -13,6 +92,7 @@ Metrics/AbcSize:
|
||||
- 'app/controllers/admin/enterprises_controller.rb'
|
||||
- 'app/controllers/payment_gateways/paypal_controller.rb'
|
||||
- 'app/controllers/spree/admin/payments_controller.rb'
|
||||
- 'app/controllers/spree/admin/taxons_controller.rb'
|
||||
- 'app/controllers/spree/admin/variants_controller.rb'
|
||||
- 'app/controllers/spree/orders_controller.rb'
|
||||
- 'app/helpers/spree/admin/navigation_helper.rb'
|
||||
@@ -47,7 +127,7 @@ Metrics/BlockNesting:
|
||||
Exclude:
|
||||
- 'app/models/spree/payment/processing.rb'
|
||||
|
||||
# Offense count: 47
|
||||
# Offense count: 46
|
||||
# Configuration parameters: CountComments, Max, CountAsOne.
|
||||
Metrics/ClassLength:
|
||||
Exclude:
|
||||
@@ -57,12 +137,12 @@ Metrics/ClassLength:
|
||||
- 'app/controllers/admin/resource_controller.rb'
|
||||
- 'app/controllers/admin/subscriptions_controller.rb'
|
||||
- 'app/controllers/application_controller.rb'
|
||||
- 'app/controllers/checkout_controller.rb'
|
||||
- 'app/controllers/payment_gateways/paypal_controller.rb'
|
||||
- 'app/controllers/spree/admin/orders_controller.rb'
|
||||
- 'app/controllers/spree/admin/payment_methods_controller.rb'
|
||||
- 'app/controllers/spree/admin/payments_controller.rb'
|
||||
- 'app/controllers/spree/admin/products_controller.rb'
|
||||
- 'app/controllers/spree/admin/users_controller.rb'
|
||||
- 'app/controllers/spree/orders_controller.rb'
|
||||
- 'app/models/enterprise.rb'
|
||||
- 'app/models/invoice/data_presenter.rb'
|
||||
@@ -88,7 +168,6 @@ Metrics/ClassLength:
|
||||
- 'app/services/cart_service.rb'
|
||||
- 'app/services/order_cycles/form_service.rb'
|
||||
- 'app/services/orders/sync_service.rb'
|
||||
- 'app/services/sets/product_set.rb'
|
||||
- 'engines/order_management/app/services/order_management/order/updater.rb'
|
||||
- 'lib/open_food_network/enterprise_fee_calculator.rb'
|
||||
- 'lib/open_food_network/order_cycle_form_applicator.rb'
|
||||
@@ -98,14 +177,13 @@ Metrics/ClassLength:
|
||||
- 'lib/reporting/reports/enterprise_fee_summary/enterprise_fees_with_tax_report_by_producer.rb'
|
||||
- 'lib/reporting/reports/enterprise_fee_summary/scope.rb'
|
||||
- 'lib/reporting/reports/xero_invoices/base.rb'
|
||||
- 'app/services/permissions/order.rb'
|
||||
|
||||
# Offense count: 30
|
||||
# Offense count: 32
|
||||
# Configuration parameters: AllowedMethods, AllowedPatterns, Max.
|
||||
Metrics/CyclomaticComplexity:
|
||||
Exclude:
|
||||
- 'app/controllers/admin/enterprises_controller.rb'
|
||||
- 'app/controllers/spree/admin/payments_controller.rb'
|
||||
- 'app/controllers/spree/admin/taxons_controller.rb'
|
||||
- 'app/controllers/spree/orders_controller.rb'
|
||||
- 'app/helpers/checkout_helper.rb'
|
||||
- 'app/helpers/order_cycles_helper.rb'
|
||||
@@ -121,6 +199,7 @@ Metrics/CyclomaticComplexity:
|
||||
- 'app/models/spree/preferences/preferable_class_methods.rb'
|
||||
- 'app/models/spree/return_authorization.rb'
|
||||
- 'app/models/spree/tax_rate.rb'
|
||||
- 'app/models/spree/variant.rb'
|
||||
- 'app/models/spree/zone.rb'
|
||||
- 'lib/open_food_network/enterprise_issue_validator.rb'
|
||||
- 'lib/reporting/reports/xero_invoices/base.rb'
|
||||
@@ -129,12 +208,13 @@ Metrics/CyclomaticComplexity:
|
||||
- 'lib/spree/localized_number.rb'
|
||||
- 'spec/models/product_importer_spec.rb'
|
||||
|
||||
# Offense count: 23
|
||||
# Offense count: 24
|
||||
# Configuration parameters: CountComments, Max, CountAsOne, AllowedMethods, AllowedPatterns.
|
||||
Metrics/MethodLength:
|
||||
Exclude:
|
||||
- 'app/controllers/admin/enterprises_controller.rb'
|
||||
- 'app/controllers/payment_gateways/paypal_controller.rb'
|
||||
- 'app/controllers/spree/admin/taxons_controller.rb'
|
||||
- 'app/controllers/spree/orders_controller.rb'
|
||||
- 'app/helpers/spree/admin/navigation_helper.rb'
|
||||
- 'app/models/spree/ability.rb'
|
||||
@@ -149,7 +229,7 @@ Metrics/MethodLength:
|
||||
- 'lib/spree/localized_number.rb'
|
||||
- 'lib/tasks/sample_data/product_factory.rb'
|
||||
|
||||
# Offense count: 47
|
||||
# Offense count: 49
|
||||
# Configuration parameters: CountComments, Max, CountAsOne.
|
||||
Metrics/ModuleLength:
|
||||
Exclude:
|
||||
@@ -161,7 +241,46 @@ Metrics/ModuleLength:
|
||||
- 'app/helpers/spree/admin/orders_helper.rb'
|
||||
- 'app/models/spree/order/checkout.rb'
|
||||
- 'app/models/spree/payment/processing.rb'
|
||||
- 'engines/catalog/spec/services/catalog/product_import/products_reset_strategy_spec.rb'
|
||||
- 'engines/order_management/spec/services/order_management/order/updater_spec.rb'
|
||||
- 'engines/order_management/spec/services/order_management/stock/package_spec.rb'
|
||||
- 'engines/order_management/spec/services/order_management/subscriptions/estimator_spec.rb'
|
||||
- 'engines/order_management/spec/services/order_management/subscriptions/form_spec.rb'
|
||||
- 'engines/order_management/spec/services/order_management/subscriptions/proxy_order_syncer_spec.rb'
|
||||
- 'engines/order_management/spec/services/order_management/subscriptions/summarizer_spec.rb'
|
||||
- 'engines/order_management/spec/services/order_management/subscriptions/summary_spec.rb'
|
||||
- 'engines/order_management/spec/services/order_management/subscriptions/validator_spec.rb'
|
||||
- 'engines/order_management/spec/services/order_management/subscriptions/variants_list_spec.rb'
|
||||
- 'lib/open_food_network/column_preference_defaults.rb'
|
||||
- 'spec/controllers/admin/customers_controller_spec.rb'
|
||||
- 'spec/controllers/admin/order_cycles_controller_spec.rb'
|
||||
- 'spec/controllers/api/v0/order_cycles_controller_spec.rb'
|
||||
- 'spec/controllers/api/v0/orders_controller_spec.rb'
|
||||
- 'spec/controllers/payment_gateways/stripe_controller_spec.rb'
|
||||
- 'spec/controllers/spree/admin/adjustments_controller_spec.rb'
|
||||
- 'spec/controllers/spree/admin/payment_methods_controller_spec.rb'
|
||||
- 'spec/controllers/spree/admin/variants_controller_spec.rb'
|
||||
- 'spec/lib/open_food_network/address_finder_spec.rb'
|
||||
- 'spec/lib/open_food_network/enterprise_fee_calculator_spec.rb'
|
||||
- 'spec/lib/open_food_network/order_cycle_form_applicator_spec.rb'
|
||||
- 'spec/lib/open_food_network/order_cycle_permissions_spec.rb'
|
||||
- 'spec/lib/open_food_network/permissions_spec.rb'
|
||||
- 'spec/lib/open_food_network/scope_variant_to_hub_spec.rb'
|
||||
- 'spec/lib/open_food_network/tag_rule_applicator_spec.rb'
|
||||
- 'spec/lib/reports/customers_report_spec.rb'
|
||||
- 'spec/lib/reports/enterprise_fee_summary/authorizer_spec.rb'
|
||||
- 'spec/lib/reports/order_cycle_management_report_spec.rb'
|
||||
- 'spec/lib/reports/products_and_inventory_report_spec.rb'
|
||||
- 'spec/lib/reports/users_and_enterprises_report_spec.rb'
|
||||
- 'spec/models/spree/adjustment_spec.rb'
|
||||
- 'spec/models/spree/credit_card_spec.rb'
|
||||
- 'spec/models/spree/line_item_spec.rb'
|
||||
- 'spec/models/spree/order/tax_spec.rb'
|
||||
- 'spec/models/spree/product_spec.rb'
|
||||
- 'spec/models/spree/shipping_method_spec.rb'
|
||||
- 'spec/models/spree/tax_rate_spec.rb'
|
||||
- 'spec/services/permissions/order_spec.rb'
|
||||
- 'spec/services/variant_units/option_value_namer_spec.rb'
|
||||
- 'spec/support/request/stripe_stubs.rb'
|
||||
|
||||
# Offense count: 7
|
||||
@@ -174,20 +293,386 @@ Metrics/ParameterLists:
|
||||
- 'spec/support/controller_requests_helper.rb'
|
||||
- 'spec/system/admin/reports_spec.rb'
|
||||
|
||||
# Offense count: 3
|
||||
# Offense count: 4
|
||||
# Configuration parameters: AllowedMethods, AllowedPatterns, Max.
|
||||
Metrics/PerceivedComplexity:
|
||||
Exclude:
|
||||
- 'app/controllers/spree/admin/taxons_controller.rb'
|
||||
- 'app/models/enterprise_relationship.rb'
|
||||
- 'app/models/spree/ability.rb'
|
||||
- 'app/models/spree/order/checkout.rb'
|
||||
|
||||
# Offense count: 8
|
||||
Naming/AccessorMethodName:
|
||||
Exclude:
|
||||
- 'app/controllers/spree/admin/taxonomies_controller.rb'
|
||||
- 'app/mailers/producer_mailer.rb'
|
||||
- 'app/models/spree/order.rb'
|
||||
- 'app/services/checkout/post_checkout_actions.rb'
|
||||
- 'lib/spree/core/controller_helpers/common.rb'
|
||||
- 'spec/support/request/shop_workflow.rb'
|
||||
- 'spec/support/request/web_helper.rb'
|
||||
|
||||
# Offense count: 1
|
||||
# Configuration parameters: ForbiddenDelimiters.
|
||||
# ForbiddenDelimiters: (?i-mx:(^|\s)(EO[A-Z]{1}|END)(\s|$))
|
||||
Naming/HeredocDelimiterNaming:
|
||||
Exclude:
|
||||
- 'app/models/content_configuration.rb'
|
||||
|
||||
# Offense count: 5
|
||||
# This cop supports unsafe autocorrection (--autocorrect-all).
|
||||
# Configuration parameters: EnforcedStyleForLeadingUnderscores.
|
||||
# SupportedStylesForLeadingUnderscores: disallowed, required, optional
|
||||
Naming/MemoizedInstanceVariableName:
|
||||
Exclude:
|
||||
- 'app/mailers/producer_mailer.rb'
|
||||
- 'app/models/concerns/balance.rb'
|
||||
- 'lib/open_food_network/address_finder.rb'
|
||||
|
||||
# Offense count: 1
|
||||
# Configuration parameters: MinNameLength, AllowNamesEndingInNumbers, AllowedNames, ForbiddenNames.
|
||||
# AllowedNames: as, at, by, cc, db, id, if, in, io, ip, of, on, os, pp, to
|
||||
Naming/MethodParameterName:
|
||||
Exclude:
|
||||
- 'app/services/process_payment_intent.rb'
|
||||
|
||||
# Offense count: 28
|
||||
# Configuration parameters: EnforcedStyle, CheckMethodNames, CheckSymbols, AllowedIdentifiers, AllowedPatterns.
|
||||
# SupportedStyles: snake_case, normalcase, non_integer
|
||||
# AllowedIdentifiers: capture3, iso8601, rfc1123_date, rfc822, rfc2822, rfc3339, x86_64
|
||||
Naming/VariableNumber:
|
||||
Exclude:
|
||||
- 'app/controllers/spree/orders_controller.rb'
|
||||
- 'app/models/content_configuration.rb'
|
||||
- 'app/models/preference_sections/main_links_section.rb'
|
||||
- 'lib/spree/core/controller_helpers/common.rb'
|
||||
- 'spec/controllers/spree/admin/search_controller_spec.rb'
|
||||
- 'spec/factories/stock_location_factory.rb'
|
||||
- 'spec/models/spree/stock_item_spec.rb'
|
||||
- 'spec/models/spree/tax_rate_spec.rb'
|
||||
- 'spec/requests/api/orders_spec.rb'
|
||||
|
||||
# Offense count: 142
|
||||
# This cop supports unsafe autocorrection (--autocorrect-all).
|
||||
# Configuration parameters: ResponseMethods.
|
||||
# ResponseMethods: response, last_response
|
||||
RSpecRails/HaveHttpStatus:
|
||||
Exclude:
|
||||
- 'spec/controllers/admin/bulk_line_items_controller_spec.rb'
|
||||
- 'spec/controllers/admin/order_cycles_controller_spec.rb'
|
||||
- 'spec/controllers/admin/subscriptions_controller_spec.rb'
|
||||
- 'spec/controllers/api/v0/base_controller_spec.rb'
|
||||
- 'spec/controllers/api/v0/customers_controller_spec.rb'
|
||||
- 'spec/controllers/api/v0/enterprises_controller_spec.rb'
|
||||
- 'spec/controllers/api/v0/logos_controller_spec.rb'
|
||||
- 'spec/controllers/api/v0/order_cycles_controller_spec.rb'
|
||||
- 'spec/controllers/api/v0/orders_controller_spec.rb'
|
||||
- 'spec/controllers/api/v0/product_images_controller_spec.rb'
|
||||
- 'spec/controllers/api/v0/products_controller_spec.rb'
|
||||
- 'spec/controllers/api/v0/promo_images_controller_spec.rb'
|
||||
- 'spec/controllers/api/v0/reports/packing_report_spec.rb'
|
||||
- 'spec/controllers/api/v0/reports_controller_spec.rb'
|
||||
- 'spec/controllers/api/v0/shipments_controller_spec.rb'
|
||||
- 'spec/controllers/api/v0/statuses_controller_spec.rb'
|
||||
- 'spec/controllers/api/v0/taxons_controller_spec.rb'
|
||||
- 'spec/controllers/api/v0/terms_and_conditions_controller_spec.rb'
|
||||
- 'spec/controllers/api/v0/variants_controller_spec.rb'
|
||||
- 'spec/controllers/cart_controller_spec.rb'
|
||||
- 'spec/controllers/checkout_controller_spec.rb'
|
||||
- 'spec/controllers/enterprises_controller_spec.rb'
|
||||
- 'spec/controllers/line_items_controller_spec.rb'
|
||||
- 'spec/controllers/shop_controller_spec.rb'
|
||||
- 'spec/controllers/spree/admin/orders/payments/payments_controller_spec.rb'
|
||||
- 'spec/controllers/spree/admin/orders_controller_spec.rb'
|
||||
- 'spec/controllers/spree/admin/products_controller_spec.rb'
|
||||
- 'spec/controllers/spree/credit_cards_controller_spec.rb'
|
||||
- 'spec/controllers/spree/orders_controller_spec.rb'
|
||||
- 'spec/controllers/stripe/callbacks_controller_spec.rb'
|
||||
- 'spec/controllers/stripe/webhooks_controller_spec.rb'
|
||||
- 'spec/controllers/user_passwords_controller_spec.rb'
|
||||
- 'spec/controllers/user_registrations_controller_spec.rb'
|
||||
- 'spec/requests/api/routes_spec.rb'
|
||||
- 'spec/requests/checkout/stripe_sca_spec.rb'
|
||||
- 'spec/requests/home_controller_spec.rb'
|
||||
- 'spec/requests/omniauth_callbacks_controller_spec.rb'
|
||||
- 'spec/services/embedded_page_service_spec.rb'
|
||||
- 'spec/support/api_helper.rb'
|
||||
|
||||
# Offense count: 8
|
||||
# This cop supports safe autocorrection (--autocorrect).
|
||||
# Configuration parameters: EnforcedStyle.
|
||||
# SupportedStyles: numeric, symbolic, be_status
|
||||
RSpecRails/HttpStatus:
|
||||
Exclude:
|
||||
- 'spec/controllers/spree/admin/products_controller_spec.rb'
|
||||
- 'spec/requests/api/orders_spec.rb'
|
||||
|
||||
# Offense count: 144
|
||||
# This cop supports unsafe autocorrection (--autocorrect-all).
|
||||
# Configuration parameters: Inferences.
|
||||
RSpecRails/InferredSpecType:
|
||||
Exclude:
|
||||
- 'engines/dfc_provider/spec/requests/addresses_spec.rb'
|
||||
- 'engines/dfc_provider/spec/requests/catalog_items_spec.rb'
|
||||
- 'engines/dfc_provider/spec/requests/enterprise_groups/affiliated_by_spec.rb'
|
||||
- 'engines/dfc_provider/spec/requests/enterprise_groups_spec.rb'
|
||||
- 'engines/dfc_provider/spec/requests/enterprises_spec.rb'
|
||||
- 'engines/dfc_provider/spec/requests/offers_spec.rb'
|
||||
- 'engines/dfc_provider/spec/requests/persons_spec.rb'
|
||||
- 'engines/dfc_provider/spec/requests/social_medias_spec.rb'
|
||||
- 'engines/dfc_provider/spec/requests/supplied_products_spec.rb'
|
||||
- 'engines/web/spec/helpers/cookies_policy_helper_spec.rb'
|
||||
- 'spec/controllers/admin/bulk_line_items_controller_spec.rb'
|
||||
- 'spec/controllers/admin/column_preferences_controller_spec.rb'
|
||||
- 'spec/controllers/admin/customers_controller_spec.rb'
|
||||
- 'spec/controllers/admin/enterprises_controller_spec.rb'
|
||||
- 'spec/controllers/admin/inventory_items_controller_spec.rb'
|
||||
- 'spec/controllers/admin/invoice_settings_controller_spec.rb'
|
||||
- 'spec/controllers/admin/matomo_settings_controller_spec.rb'
|
||||
- 'spec/controllers/admin/order_cycles_controller_spec.rb'
|
||||
- 'spec/controllers/admin/product_import_controller_spec.rb'
|
||||
- 'spec/controllers/admin/proxy_orders_controller_spec.rb'
|
||||
- 'spec/controllers/admin/reports_controller_spec.rb'
|
||||
- 'spec/controllers/admin/schedules_controller_spec.rb'
|
||||
- 'spec/controllers/admin/stripe_accounts_controller_spec.rb'
|
||||
- 'spec/controllers/admin/stripe_connect_settings_controller_spec.rb'
|
||||
- 'spec/controllers/admin/subscription_line_items_controller_spec.rb'
|
||||
- 'spec/controllers/admin/subscriptions_controller_spec.rb'
|
||||
- 'spec/controllers/admin/tag_rules_controller_spec.rb'
|
||||
- 'spec/controllers/admin/terms_of_service_files_controller_spec.rb'
|
||||
- 'spec/controllers/admin/variant_overrides_controller_spec.rb'
|
||||
- 'spec/controllers/api/v0/customers_controller_spec.rb'
|
||||
- 'spec/controllers/api/v0/enterprise_fees_controller_spec.rb'
|
||||
- 'spec/controllers/api/v0/enterprises_controller_spec.rb'
|
||||
- 'spec/controllers/api/v0/exchange_products_controller_spec.rb'
|
||||
- 'spec/controllers/api/v0/logos_controller_spec.rb'
|
||||
- 'spec/controllers/api/v0/order_cycles_controller_spec.rb'
|
||||
- 'spec/controllers/api/v0/orders_controller_spec.rb'
|
||||
- 'spec/controllers/api/v0/product_images_controller_spec.rb'
|
||||
- 'spec/controllers/api/v0/products_controller_spec.rb'
|
||||
- 'spec/controllers/api/v0/promo_images_controller_spec.rb'
|
||||
- 'spec/controllers/api/v0/reports/packing_report_spec.rb'
|
||||
- 'spec/controllers/api/v0/reports_controller_spec.rb'
|
||||
- 'spec/controllers/api/v0/shipments_controller_spec.rb'
|
||||
- 'spec/controllers/api/v0/shops_controller_spec.rb'
|
||||
- 'spec/controllers/api/v0/statuses_controller_spec.rb'
|
||||
- 'spec/controllers/api/v0/terms_and_conditions_controller_spec.rb'
|
||||
- 'spec/controllers/api/v0/variants_controller_spec.rb'
|
||||
- 'spec/controllers/base_controller_spec.rb'
|
||||
- 'spec/controllers/cart_controller_spec.rb'
|
||||
- 'spec/controllers/checkout_controller_spec.rb'
|
||||
- 'spec/controllers/enterprises_controller_spec.rb'
|
||||
- 'spec/controllers/groups_controller_spec.rb'
|
||||
- 'spec/controllers/line_items_controller_spec.rb'
|
||||
- 'spec/controllers/payment_gateways/paypal_controller_spec.rb'
|
||||
- 'spec/controllers/payment_gateways/stripe_controller_spec.rb'
|
||||
- 'spec/controllers/registration_controller_spec.rb'
|
||||
- 'spec/controllers/shop_controller_spec.rb'
|
||||
- 'spec/controllers/shops_controller_spec.rb'
|
||||
- 'spec/controllers/spree/admin/adjustments_controller_spec.rb'
|
||||
- 'spec/controllers/spree/admin/base_controller_spec.rb'
|
||||
- 'spec/controllers/spree/admin/countries_controller_spec.rb'
|
||||
- 'spec/controllers/spree/admin/general_settings_controller_spec.rb'
|
||||
- 'spec/controllers/spree/admin/orders/customer_details_controller_spec.rb'
|
||||
- 'spec/controllers/spree/admin/orders/invoices_spec.rb'
|
||||
- 'spec/controllers/spree/admin/orders/payments/payments_controller_refunds_spec.rb'
|
||||
- 'spec/controllers/spree/admin/orders/payments/payments_controller_spec.rb'
|
||||
- 'spec/controllers/spree/admin/orders_controller_spec.rb'
|
||||
- 'spec/controllers/spree/admin/overview_controller_spec.rb'
|
||||
- 'spec/controllers/spree/admin/payment_methods_controller_spec.rb'
|
||||
- 'spec/controllers/spree/admin/products_controller_spec.rb'
|
||||
- 'spec/controllers/spree/admin/return_authorizations_controller_spec.rb'
|
||||
- 'spec/controllers/spree/admin/search_controller_spec.rb'
|
||||
- 'spec/controllers/spree/admin/shipping_categories_controller_spec.rb'
|
||||
- 'spec/controllers/spree/admin/shipping_methods_controller_spec.rb'
|
||||
- 'spec/controllers/spree/admin/tax_rates_controller_spec.rb'
|
||||
- 'spec/controllers/spree/admin/tax_settings_controller_spec.rb'
|
||||
- 'spec/controllers/spree/admin/variants_controller_spec.rb'
|
||||
- 'spec/controllers/spree/api_keys_controller_spec.rb'
|
||||
- 'spec/controllers/spree/credit_cards_controller_spec.rb'
|
||||
- 'spec/controllers/spree/orders_controller_spec.rb'
|
||||
- 'spec/controllers/spree/user_sessions_controller_spec.rb'
|
||||
- 'spec/controllers/spree/users_controller_spec.rb'
|
||||
- 'spec/controllers/stripe/callbacks_controller_spec.rb'
|
||||
- 'spec/controllers/stripe/webhooks_controller_spec.rb'
|
||||
- 'spec/controllers/user_confirmations_controller_spec.rb'
|
||||
- 'spec/controllers/user_passwords_controller_spec.rb'
|
||||
- 'spec/controllers/user_registrations_controller_spec.rb'
|
||||
- 'spec/controllers/webhook_endpoints_controller_spec.rb'
|
||||
- 'spec/helpers/admin/enterprises_helper_spec.rb'
|
||||
- 'spec/helpers/admin/orders_helper_spec.rb'
|
||||
- 'spec/helpers/admin/reports_helper_spec.rb'
|
||||
- 'spec/helpers/admin/subscriptions_helper_spec.rb'
|
||||
- 'spec/helpers/application_helper_spec.rb'
|
||||
- 'spec/helpers/checkout_helper_spec.rb'
|
||||
- 'spec/helpers/i18n_helper_spec.rb'
|
||||
- 'spec/helpers/injection_helper_spec.rb'
|
||||
- 'spec/helpers/link_helper_spec.rb'
|
||||
- 'spec/helpers/navigation_helper_spec.rb'
|
||||
- 'spec/helpers/order_cycles_helper_spec.rb'
|
||||
- 'spec/helpers/serializer_helper_spec.rb'
|
||||
- 'spec/helpers/shop_helper_spec.rb'
|
||||
- 'spec/helpers/spree/admin/base_helper_spec.rb'
|
||||
- 'spec/helpers/spree/admin/general_settings_helper_spec.rb'
|
||||
- 'spec/helpers/spree/admin/orders_helper_spec.rb'
|
||||
- 'spec/helpers/spree/orders_helper_spec.rb'
|
||||
- 'spec/helpers/tax_helper_spec.rb'
|
||||
- 'spec/helpers/terms_and_conditions_helper_spec.rb'
|
||||
- 'spec/jobs/connect_app_job_spec.rb'
|
||||
- 'spec/mailers/producer_mailer_spec.rb'
|
||||
- 'spec/mailers/subscription_mailer_spec.rb'
|
||||
- 'spec/models/column_preference_spec.rb'
|
||||
- 'spec/models/connected_app_spec.rb'
|
||||
- 'spec/models/customer_spec.rb'
|
||||
- 'spec/models/invoice_spec.rb'
|
||||
- 'spec/models/oidc_account_spec.rb'
|
||||
- 'spec/models/proxy_order_spec.rb'
|
||||
- 'spec/models/report_blob_spec.rb'
|
||||
- 'spec/models/semantic_link_spec.rb'
|
||||
- 'spec/models/spree/gateway/stripe_sca_spec.rb'
|
||||
- 'spec/models/subscription_spec.rb'
|
||||
- 'spec/models/tag_rule/filter_order_cycles_spec.rb'
|
||||
- 'spec/models/tag_rule/filter_payment_methods_spec.rb'
|
||||
- 'spec/models/tag_rule/filter_products_spec.rb'
|
||||
- 'spec/models/tag_rule/filter_shipping_methods_spec.rb'
|
||||
- 'spec/models/tag_rule_spec.rb'
|
||||
- 'spec/models/webhook_endpoint_spec.rb'
|
||||
- 'spec/requests/admin/images_spec.rb'
|
||||
- 'spec/requests/admin/product_import_spec.rb'
|
||||
- 'spec/requests/admin/vouchers_spec.rb'
|
||||
- 'spec/requests/api/orders_spec.rb'
|
||||
- 'spec/requests/api/routes_spec.rb'
|
||||
- 'spec/requests/api/v1/customers_spec.rb'
|
||||
- 'spec/requests/api_docs_spec.rb'
|
||||
- 'spec/requests/checkout/paypal_spec.rb'
|
||||
- 'spec/requests/checkout/routes_spec.rb'
|
||||
- 'spec/requests/checkout/stripe_sca_spec.rb'
|
||||
- 'spec/requests/errors_spec.rb'
|
||||
- 'spec/requests/home_controller_spec.rb'
|
||||
- 'spec/requests/large_request_spec.rb'
|
||||
- 'spec/requests/omniauth_callbacks_controller_spec.rb'
|
||||
- 'spec/requests/spree/admin/overview_spec.rb'
|
||||
- 'spec/requests/spree/admin/payments_spec.rb'
|
||||
- 'spec/requests/voucher_adjustments_spec.rb'
|
||||
- 'spec/routing/stripe_spec.rb'
|
||||
|
||||
# Offense count: 22
|
||||
# Configuration parameters: IgnoreScopes, Include.
|
||||
# Include: app/models/**/*.rb
|
||||
Rails/InverseOf:
|
||||
Exclude:
|
||||
- 'app/models/enterprise.rb'
|
||||
- 'app/models/order_cycle.rb'
|
||||
- 'app/models/spree/country.rb'
|
||||
- 'app/models/spree/inventory_unit.rb'
|
||||
- 'app/models/spree/line_item.rb'
|
||||
- 'app/models/spree/order.rb'
|
||||
- 'app/models/spree/payment.rb'
|
||||
- 'app/models/spree/price.rb'
|
||||
- 'app/models/spree/product.rb'
|
||||
- 'app/models/spree/stock_item.rb'
|
||||
- 'app/models/spree/taxonomy.rb'
|
||||
- 'app/models/spree/variant.rb'
|
||||
- 'app/models/subscription_line_item.rb'
|
||||
|
||||
# Offense count: 35
|
||||
# Configuration parameters: Include.
|
||||
# Include: app/controllers/**/*.rb, app/mailers/**/*.rb
|
||||
Rails/LexicallyScopedActionFilter:
|
||||
Exclude:
|
||||
- 'app/controllers/admin/enterprise_groups_controller.rb'
|
||||
- 'app/controllers/admin/enterprises_controller.rb'
|
||||
- 'app/controllers/admin/order_cycles_controller.rb'
|
||||
- 'app/controllers/admin/producer_properties_controller.rb'
|
||||
- 'app/controllers/admin/product_import_controller.rb'
|
||||
- 'app/controllers/admin/schedules_controller.rb'
|
||||
- 'app/controllers/admin/subscriptions_controller.rb'
|
||||
- 'app/controllers/concerns/checkout_callbacks.rb'
|
||||
- 'app/controllers/registration_controller.rb'
|
||||
- 'app/controllers/spree/admin/adjustments_controller.rb'
|
||||
- 'app/controllers/spree/admin/payment_methods_controller.rb'
|
||||
- 'app/controllers/spree/admin/payments_controller.rb'
|
||||
- 'app/controllers/spree/admin/products_controller.rb'
|
||||
- 'app/controllers/spree/admin/return_authorizations_controller.rb'
|
||||
- 'app/controllers/spree/admin/search_controller.rb'
|
||||
- 'app/controllers/spree/admin/shipping_methods_controller.rb'
|
||||
- 'app/controllers/spree/admin/users_controller.rb'
|
||||
- 'app/controllers/spree/admin/zones_controller.rb'
|
||||
- 'app/controllers/spree/users_controller.rb'
|
||||
|
||||
# Offense count: 56
|
||||
# This cop supports unsafe autocorrection (--autocorrect-all).
|
||||
# Configuration parameters: Include.
|
||||
# Include: spec/controllers/**/*.rb, spec/requests/**/*.rb, test/controllers/**/*.rb, test/integration/**/*.rb
|
||||
Rails/ResponseParsedBody:
|
||||
Exclude:
|
||||
- 'spec/controllers/admin/bulk_line_items_controller_spec.rb'
|
||||
- 'spec/controllers/admin/customers_controller_spec.rb'
|
||||
- 'spec/controllers/admin/order_cycles_controller_spec.rb'
|
||||
- 'spec/controllers/admin/proxy_orders_controller_spec.rb'
|
||||
- 'spec/controllers/admin/schedules_controller_spec.rb'
|
||||
- 'spec/controllers/admin/stripe_accounts_controller_spec.rb'
|
||||
- 'spec/controllers/admin/subscription_line_items_controller_spec.rb'
|
||||
- 'spec/controllers/admin/subscriptions_controller_spec.rb'
|
||||
- 'spec/controllers/cart_controller_spec.rb'
|
||||
- 'spec/controllers/line_items_controller_spec.rb'
|
||||
- 'spec/controllers/spree/admin/search_controller_spec.rb'
|
||||
- 'spec/controllers/spree/credit_cards_controller_spec.rb'
|
||||
- 'spec/controllers/user_registrations_controller_spec.rb'
|
||||
|
||||
# Offense count: 7
|
||||
# This cop supports unsafe autocorrection (--autocorrect-all).
|
||||
# Configuration parameters: EnforcedStyle.
|
||||
# SupportedStyles: strict, flexible
|
||||
Rails/TimeZone:
|
||||
Exclude:
|
||||
- 'app/models/spree/gateway/pay_pal_express.rb'
|
||||
- 'spec/controllers/spree/credit_cards_controller_spec.rb'
|
||||
- 'spec/services/order_cycles/webhook_service_spec.rb'
|
||||
- 'spec/services/orders/customer_cancellation_service_spec.rb'
|
||||
|
||||
# Offense count: 1
|
||||
# Configuration parameters: TransactionMethods.
|
||||
Rails/TransactionExitStatement:
|
||||
Exclude:
|
||||
- 'app/services/place_proxy_order.rb'
|
||||
|
||||
# Offense count: 5
|
||||
# Configuration parameters: Include.
|
||||
# Include: app/models/**/*.rb
|
||||
Rails/UniqueValidationWithoutIndex:
|
||||
Exclude:
|
||||
- 'app/models/customer.rb'
|
||||
- 'app/models/exchange.rb'
|
||||
- 'app/models/spree/stock_item.rb'
|
||||
- 'app/models/spree/tax_category.rb'
|
||||
- 'app/models/spree/zone.rb'
|
||||
|
||||
# Offense count: 1
|
||||
Security/Open:
|
||||
Exclude:
|
||||
- 'app/services/image_importer.rb'
|
||||
|
||||
# Offense count: 7
|
||||
# This cop supports unsafe autocorrection (--autocorrect-all).
|
||||
Style/ArrayIntersect:
|
||||
Exclude:
|
||||
- 'app/models/spree/ability.rb'
|
||||
- 'app/models/tag_rule/filter_order_cycles.rb'
|
||||
- 'app/models/tag_rule/filter_payment_methods.rb'
|
||||
- 'app/models/tag_rule/filter_products.rb'
|
||||
- 'app/models/tag_rule/filter_shipping_methods.rb'
|
||||
- 'lib/open_food_network/tag_rule_applicator.rb'
|
||||
- 'spec/support/matchers/select2_matchers.rb'
|
||||
|
||||
# Offense count: 1
|
||||
# This cop supports safe autocorrection (--autocorrect).
|
||||
# Configuration parameters: AllowOnConstant, AllowOnSelfClass.
|
||||
Style/CaseEquality:
|
||||
Exclude:
|
||||
- 'spec/models/spree/payment_spec.rb'
|
||||
|
||||
# Offense count: 23
|
||||
# This cop supports unsafe autocorrection (--autocorrect-all).
|
||||
# Configuration parameters: EnforcedStyle.
|
||||
@@ -217,6 +702,56 @@ Style/ClassAndModuleChildren:
|
||||
- 'lib/open_food_network/locking.rb'
|
||||
- 'spec/models/spree/payment_method_spec.rb'
|
||||
|
||||
# Offense count: 1
|
||||
# This cop supports unsafe autocorrection (--autocorrect-all).
|
||||
# Configuration parameters: EnforcedStyle.
|
||||
# SupportedStyles: always, always_true, never
|
||||
Style/FrozenStringLiteralComment:
|
||||
Exclude:
|
||||
- '.simplecov'
|
||||
|
||||
# Offense count: 6
|
||||
# This cop supports unsafe autocorrection (--autocorrect-all).
|
||||
Style/GlobalStdStream:
|
||||
Exclude:
|
||||
- 'lib/tasks/data.rake'
|
||||
- 'lib/tasks/missing_payments.rake'
|
||||
- 'lib/tasks/sample_data/logging.rb'
|
||||
- 'lib/tasks/subscriptions/debug.rake'
|
||||
- 'lib/tasks/subscriptions/test.rake'
|
||||
|
||||
# Offense count: 12
|
||||
# This cop supports unsafe autocorrection (--autocorrect-all).
|
||||
# Configuration parameters: AllowSplatArgument.
|
||||
Style/HashConversion:
|
||||
Exclude:
|
||||
- 'app/controllers/admin/column_preferences_controller.rb'
|
||||
- 'app/controllers/admin/variant_overrides_controller.rb'
|
||||
- 'app/controllers/spree/admin/products_controller.rb'
|
||||
- 'app/models/order_cycle.rb'
|
||||
- 'app/models/product_import/product_importer.rb'
|
||||
- 'app/models/spree/shipping_method.rb'
|
||||
- 'app/serializers/api/admin/exchange_serializer.rb'
|
||||
- 'app/services/variants_stock_levels.rb'
|
||||
- 'spec/controllers/admin/inventory_items_controller_spec.rb'
|
||||
- 'spec/controllers/admin/variant_overrides_controller_spec.rb'
|
||||
|
||||
# Offense count: 13
|
||||
# This cop supports unsafe autocorrection (--autocorrect-all).
|
||||
# Configuration parameters: AllowedReceivers.
|
||||
# AllowedReceivers: Thread.current
|
||||
Style/HashEachMethods:
|
||||
Exclude:
|
||||
- 'app/controllers/admin/enterprises_controller.rb'
|
||||
- 'app/controllers/spree/admin/shipping_methods_controller.rb'
|
||||
- 'app/forms/enterprise_fees_bulk_update.rb'
|
||||
- 'app/models/product_import/entry_processor.rb'
|
||||
- 'app/models/spree/preferences/configuration.rb'
|
||||
- 'app/services/sets/model_set.rb'
|
||||
- 'lib/reporting/reports/sales_tax/sales_tax_totals_by_producer.rb'
|
||||
- 'spec/models/product_importer_spec.rb'
|
||||
- 'spec/support/cancan_helper.rb'
|
||||
|
||||
# Offense count: 4
|
||||
# This cop supports unsafe autocorrection (--autocorrect-all).
|
||||
Style/MapToHash:
|
||||
@@ -226,6 +761,28 @@ Style/MapToHash:
|
||||
- 'lib/reporting/reports/enterprise_fee_summary/fee_summary.rb'
|
||||
- 'lib/tasks/sample_data/user_factory.rb'
|
||||
|
||||
# Offense count: 3
|
||||
Style/MissingRespondToMissing:
|
||||
Exclude:
|
||||
- 'app/helpers/application_helper.rb'
|
||||
- 'app/models/spree/gateway.rb'
|
||||
- 'app/models/spree/preferences/configuration.rb'
|
||||
|
||||
# Offense count: 22
|
||||
# This cop supports safe autocorrection (--autocorrect).
|
||||
Style/NestedModifier:
|
||||
Exclude:
|
||||
- 'spec/controllers/admin/subscriptions_controller_spec.rb'
|
||||
- 'spec/controllers/line_items_controller_spec.rb'
|
||||
- 'spec/controllers/spree/admin/orders_controller_spec.rb'
|
||||
- 'spec/controllers/spree/orders_controller_spec.rb'
|
||||
- 'spec/factories/order_factory.rb'
|
||||
- 'spec/models/proxy_order_spec.rb'
|
||||
- 'spec/models/spree/line_item_spec.rb'
|
||||
- 'spec/services/place_proxy_order_spec.rb'
|
||||
- 'spec/system/admin/payments_stripe_spec.rb'
|
||||
- 'spec/system/admin/reports_spec.rb'
|
||||
|
||||
# Offense count: 38
|
||||
Style/OpenStructUse:
|
||||
Exclude:
|
||||
@@ -254,3 +811,48 @@ Style/OptionalBooleanParameter:
|
||||
- 'engines/order_management/app/services/order_management/stock/estimator.rb'
|
||||
- 'lib/spree/core/controller_helpers/order.rb'
|
||||
- 'spec/support/request/web_helper.rb'
|
||||
|
||||
# Offense count: 1
|
||||
# This cop supports unsafe autocorrection (--autocorrect-all).
|
||||
# Configuration parameters: EnforcedStyle.
|
||||
# SupportedStyles: short, verbose
|
||||
Style/PreferredHashMethods:
|
||||
Exclude:
|
||||
- 'app/controllers/api/v0/shipments_controller.rb'
|
||||
|
||||
# Offense count: 1
|
||||
# This cop supports unsafe autocorrection (--autocorrect-all).
|
||||
# Configuration parameters: Methods.
|
||||
Style/RedundantArgument:
|
||||
Exclude:
|
||||
- 'engines/dfc_provider/app/services/authorization_control.rb'
|
||||
|
||||
# Offense count: 1
|
||||
# This cop supports safe autocorrection (--autocorrect).
|
||||
Style/RedundantAssignment:
|
||||
Exclude:
|
||||
- 'spec/models/database_spec.rb'
|
||||
|
||||
# Offense count: 1
|
||||
# This cop supports unsafe autocorrection (--autocorrect-all).
|
||||
# Configuration parameters: AutoCorrect, AllowComments.
|
||||
Style/RedundantInitialize:
|
||||
Exclude:
|
||||
- 'spec/models/spree/gateway_spec.rb'
|
||||
|
||||
# Offense count: 19
|
||||
# This cop supports unsafe autocorrection (--autocorrect-all).
|
||||
# Configuration parameters: AllowedMethods, AllowedPatterns.
|
||||
Style/ReturnNilInPredicateMethodDefinition:
|
||||
Exclude:
|
||||
- 'app/models/order_cycle.rb'
|
||||
- 'app/serializers/api/admin/customer_serializer.rb'
|
||||
- 'engines/order_management/app/services/order_management/subscriptions/validator.rb'
|
||||
|
||||
# Offense count: 3
|
||||
# This cop supports unsafe autocorrection (--autocorrect-all).
|
||||
Style/SlicingWithRange:
|
||||
Exclude:
|
||||
- 'app/helpers/spree/admin/navigation_helper.rb'
|
||||
- 'app/services/embedded_page_service.rb'
|
||||
- 'engines/order_management/app/services/order_management/subscriptions/validator.rb'
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
#!/bin/env ruby
|
||||
# frozen_string_literal: true
|
||||
|
||||
SimpleCov.start 'rails' do
|
||||
add_filter '/bin/'
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
#!/bin/env ruby
|
||||
# frozen_string_literal: true
|
||||
|
||||
-l coverage/lcov/openfoodnetwork.lcov
|
||||
-c master
|
||||
116
Dockerfile
116
Dockerfile
@@ -1,32 +1,92 @@
|
||||
FROM ruby:3.1.4-alpine3.19 AS base
|
||||
ENV LANG=C.UTF-8 \
|
||||
LC_ALL=C.UTF-8 \
|
||||
TZ=Europe/London \
|
||||
RAILS_ROOT=/usr/src/app
|
||||
RUN apk --no-cache upgrade && \
|
||||
apk add --no-cache tzdata postgresql-client imagemagick imagemagick-jpeg && \
|
||||
apk add --no-cache --virtual wkhtmltopdf
|
||||
FROM ubuntu:20.04
|
||||
|
||||
WORKDIR $RAILS_ROOT
|
||||
ENV TZ Europe/London
|
||||
|
||||
# Development dependencies
|
||||
FROM base AS development-base
|
||||
RUN apk add --no-cache --virtual .build-deps \
|
||||
build-base postgresql-dev git nodejs yarn && \
|
||||
apk add --no-cache --virtual .dev-utils \
|
||||
bash curl less vim chromium-chromedriver zlib-dev openssl-dev \
|
||||
readline-dev yaml-dev sqlite-dev libxml2-dev libxslt-dev libffi-dev vips-dev && \
|
||||
curl -o /usr/local/bin/wait-for-it https://raw.githubusercontent.com/vishnubob/wait-for-it/master/wait-for-it.sh && \
|
||||
chmod +x /usr/local/bin/wait-for-it
|
||||
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
|
||||
|
||||
# Install yarn dependencies separately for caching
|
||||
FROM development-base AS yarn-dependencies
|
||||
COPY package.json yarn.lock ./
|
||||
RUN yarn install --frozen-lockfile
|
||||
RUN echo "deb http://security.ubuntu.com/ubuntu bionic-security main" >> /etc/apt/sources.list
|
||||
|
||||
# Install Ruby gems
|
||||
FROM development-base
|
||||
COPY . $RAILS_ROOT
|
||||
COPY Gemfile Gemfile.lock ./
|
||||
RUN bundle install --jobs "$(nproc)"
|
||||
COPY --from=yarn-dependencies $RAILS_ROOT/node_modules ./node_modules
|
||||
# Install all the requirements
|
||||
RUN apt-get update && apt-get install -y \
|
||||
curl \
|
||||
git \
|
||||
build-essential \
|
||||
software-properties-common \
|
||||
wget \
|
||||
zlib1g-dev \
|
||||
libreadline-dev \
|
||||
libyaml-dev \
|
||||
libffi-dev \
|
||||
libxml2-dev \
|
||||
libxslt1-dev \
|
||||
wait-for-it \
|
||||
imagemagick \
|
||||
unzip \
|
||||
libjemalloc-dev \
|
||||
libssl-dev \
|
||||
ca-certificates \
|
||||
gnupg
|
||||
|
||||
# Setup ENV variables
|
||||
ENV PATH /usr/local/src/rbenv/shims:/usr/local/src/rbenv/bin:/usr/local/src/nodenv/shims:/usr/local/src/nodenv/bin:$PATH
|
||||
ENV RBENV_ROOT /usr/local/src/rbenv
|
||||
ENV NODENV_ROOT /usr/local/src/nodenv
|
||||
ENV CONFIGURE_OPTS --disable-install-doc
|
||||
ENV BUNDLE_PATH /bundles
|
||||
ENV LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libjemalloc.so
|
||||
|
||||
WORKDIR /usr/src/app
|
||||
|
||||
# trim spaces and line return from .ruby-version file
|
||||
COPY .ruby-version .ruby-version.raw
|
||||
RUN cat .ruby-version.raw | tr -d '\r\t ' > .ruby-version
|
||||
|
||||
# Install Rbenv & Ruby
|
||||
RUN git clone --depth 1 https://github.com/rbenv/rbenv.git ${RBENV_ROOT} && \
|
||||
git clone --depth 1 https://github.com/rbenv/ruby-build.git ${RBENV_ROOT}/plugins/ruby-build && \
|
||||
echo 'eval "$(rbenv init -)"' >> /etc/profile.d/rbenv.sh && \
|
||||
RUBY_CONFIGURE_OPTS=--with-jemalloc rbenv install $(cat .ruby-version) && \
|
||||
rbenv global $(cat .ruby-version)
|
||||
|
||||
# Install Postgres
|
||||
RUN sh -c "echo 'deb http://apt.postgresql.org/pub/repos/apt/ `lsb_release -cs`-pgdg main' >> /etc/apt/sources.list.d/pgdg.list" && \
|
||||
curl https://www.postgresql.org/media/keys/ACCC4CF8.asc | gpg --dearmor | tee /etc/apt/trusted.gpg.d/apt.postgresql.org.gpg >/dev/null && \
|
||||
apt-get update && \
|
||||
apt-get install -yqq --no-install-recommends postgresql-client-10 libpq-dev
|
||||
|
||||
|
||||
# trim spaces and line return from .node-version file
|
||||
COPY .node-version .node-version.raw
|
||||
RUN cat .node-version.raw | tr -d '\r\t ' > .node-version
|
||||
|
||||
# Install Node and Yarn with Nodenv
|
||||
RUN git clone --depth 1 https://github.com/nodenv/nodenv.git ${NODENV_ROOT} && \
|
||||
git clone --depth 1 https://github.com/nodenv/node-build.git ${NODENV_ROOT}/plugins/node-build && \
|
||||
git clone --depth 1 https://github.com/pine/nodenv-yarn-install.git ${NODENV_ROOT}/plugins/nodenv-yarn-install && \
|
||||
git clone --depth 1 https://github.com/nodenv/nodenv-package-rehash.git ${NODENV_ROOT}/plugins/nodenv-package-rehash && \
|
||||
echo 'eval "$(nodenv init -)"' >> /etc/profile.d/nodenv.sh && \
|
||||
nodenv install $(cat .node-version) && \
|
||||
nodenv global $(cat .node-version)
|
||||
|
||||
# Install Chrome
|
||||
RUN wget --quiet -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - && \
|
||||
sh -c "echo 'deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main' >> /etc/apt/sources.list.d/google-chrome.list" && \
|
||||
apt-get update && \
|
||||
apt-get install -fy google-chrome-stable
|
||||
|
||||
# Install Chromedriver
|
||||
RUN wget https://chromedriver.storage.googleapis.com/2.41/chromedriver_linux64.zip && \
|
||||
unzip chromedriver_linux64.zip -d /usr/bin && \
|
||||
chmod u+x /usr/bin/chromedriver
|
||||
|
||||
# Copy code and install app dependencies
|
||||
COPY . /usr/src/app/
|
||||
|
||||
# Install Bundler
|
||||
RUN ./script/install-bundler
|
||||
|
||||
# Install front-end dependencies
|
||||
RUN yarn install
|
||||
|
||||
# Run bundler install in parallel with the amount of available CPUs
|
||||
RUN bundle install --jobs="$(nproc)"
|
||||
|
||||
@@ -1,92 +0,0 @@
|
||||
FROM ubuntu:20.04
|
||||
|
||||
ENV TZ Europe/London
|
||||
|
||||
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
|
||||
|
||||
RUN echo "deb http://security.ubuntu.com/ubuntu bionic-security main" >> /etc/apt/sources.list
|
||||
|
||||
# Install all the requirements
|
||||
RUN apt-get update && apt-get install -y \
|
||||
curl \
|
||||
git \
|
||||
build-essential \
|
||||
software-properties-common \
|
||||
wget \
|
||||
zlib1g-dev \
|
||||
libreadline-dev \
|
||||
libyaml-dev \
|
||||
libffi-dev \
|
||||
libxml2-dev \
|
||||
libxslt1-dev \
|
||||
wait-for-it \
|
||||
imagemagick \
|
||||
unzip \
|
||||
libjemalloc-dev \
|
||||
libssl-dev \
|
||||
ca-certificates \
|
||||
gnupg
|
||||
|
||||
# Setup ENV variables
|
||||
ENV PATH /usr/local/src/rbenv/shims:/usr/local/src/rbenv/bin:/usr/local/src/nodenv/shims:/usr/local/src/nodenv/bin:$PATH
|
||||
ENV RBENV_ROOT /usr/local/src/rbenv
|
||||
ENV NODENV_ROOT /usr/local/src/nodenv
|
||||
ENV CONFIGURE_OPTS --disable-install-doc
|
||||
ENV BUNDLE_PATH /bundles
|
||||
ENV LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libjemalloc.so
|
||||
|
||||
WORKDIR /usr/src/app
|
||||
|
||||
# trim spaces and line return from .ruby-version file
|
||||
COPY .ruby-version .ruby-version.raw
|
||||
RUN cat .ruby-version.raw | tr -d '\r\t ' > .ruby-version
|
||||
|
||||
# Install Rbenv & Ruby
|
||||
RUN git clone --depth 1 https://github.com/rbenv/rbenv.git ${RBENV_ROOT} && \
|
||||
git clone --depth 1 https://github.com/rbenv/ruby-build.git ${RBENV_ROOT}/plugins/ruby-build && \
|
||||
echo 'eval "$(rbenv init -)"' >> /etc/profile.d/rbenv.sh && \
|
||||
RUBY_CONFIGURE_OPTS=--with-jemalloc rbenv install $(cat .ruby-version) && \
|
||||
rbenv global $(cat .ruby-version)
|
||||
|
||||
# Install Postgres
|
||||
RUN sh -c "echo 'deb http://apt.postgresql.org/pub/repos/apt/ `lsb_release -cs`-pgdg main' >> /etc/apt/sources.list.d/pgdg.list" && \
|
||||
curl https://www.postgresql.org/media/keys/ACCC4CF8.asc | gpg --dearmor | tee /etc/apt/trusted.gpg.d/apt.postgresql.org.gpg >/dev/null && \
|
||||
apt-get update && \
|
||||
apt-get install -yqq --no-install-recommends postgresql-client-10 libpq-dev
|
||||
|
||||
|
||||
# trim spaces and line return from .node-version file
|
||||
COPY .node-version .node-version.raw
|
||||
RUN cat .node-version.raw | tr -d '\r\t ' > .node-version
|
||||
|
||||
# Install Node and Yarn with Nodenv
|
||||
RUN git clone --depth 1 https://github.com/nodenv/nodenv.git ${NODENV_ROOT} && \
|
||||
git clone --depth 1 https://github.com/nodenv/node-build.git ${NODENV_ROOT}/plugins/node-build && \
|
||||
git clone --depth 1 https://github.com/pine/nodenv-yarn-install.git ${NODENV_ROOT}/plugins/nodenv-yarn-install && \
|
||||
git clone --depth 1 https://github.com/nodenv/nodenv-package-rehash.git ${NODENV_ROOT}/plugins/nodenv-package-rehash && \
|
||||
echo 'eval "$(nodenv init -)"' >> /etc/profile.d/nodenv.sh && \
|
||||
nodenv install $(cat .node-version) && \
|
||||
nodenv global $(cat .node-version)
|
||||
|
||||
# Install Chrome
|
||||
RUN wget --quiet -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - && \
|
||||
sh -c "echo 'deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main' >> /etc/apt/sources.list.d/google-chrome.list" && \
|
||||
apt-get update && \
|
||||
apt-get install -fy google-chrome-stable
|
||||
|
||||
# Install Chromedriver
|
||||
RUN wget https://chromedriver.storage.googleapis.com/2.41/chromedriver_linux64.zip && \
|
||||
unzip chromedriver_linux64.zip -d /usr/bin && \
|
||||
chmod u+x /usr/bin/chromedriver
|
||||
|
||||
# Copy code and install app dependencies
|
||||
COPY . /usr/src/app/
|
||||
|
||||
# Install Bundler
|
||||
RUN ./script/install-bundler
|
||||
|
||||
# Install front-end dependencies
|
||||
RUN yarn install
|
||||
|
||||
# Run bundler install in parallel with the amount of available CPUs
|
||||
RUN bundle install --jobs="$(nproc)"
|
||||
7
Gemfile
7
Gemfile
@@ -65,7 +65,7 @@ gem 'oauth2', '~> 1.4.7' # Used for Stripe Connect
|
||||
|
||||
gem 'datafoodconsortium-connector'
|
||||
gem 'jsonapi-serializer'
|
||||
gem 'pagy', '~> 9'
|
||||
gem 'pagy', '~> 5.1'
|
||||
|
||||
gem 'rswag-api'
|
||||
gem 'rswag-ui'
|
||||
@@ -86,7 +86,7 @@ gem "active_model_serializers", "0.8.4"
|
||||
gem 'activerecord-session_store'
|
||||
gem 'acts-as-taggable-on'
|
||||
gem 'angularjs-file-upload-rails', '~> 2.4.1'
|
||||
gem 'bigdecimal'
|
||||
gem 'bigdecimal', '3.0.2'
|
||||
gem 'bootsnap', require: false
|
||||
gem 'geocoder'
|
||||
gem 'gmaps4rails'
|
||||
@@ -173,8 +173,6 @@ group :test do
|
||||
gem 'pdf-reader'
|
||||
gem 'rails-controller-testing'
|
||||
gem 'simplecov', require: false
|
||||
gem 'simplecov-lcov', require: false
|
||||
gem 'undercover', require: false
|
||||
gem 'vcr', require: false
|
||||
gem 'webmock', require: false
|
||||
# See spec/spec_helper.rb for instructions
|
||||
@@ -184,7 +182,6 @@ end
|
||||
group :development do
|
||||
gem 'debugger-linecache'
|
||||
gem 'foreman'
|
||||
gem 'i18n-tasks'
|
||||
gem 'listen'
|
||||
gem 'pry', '~> 0.13.0'
|
||||
gem 'query_count'
|
||||
|
||||
81
Gemfile.lock
81
Gemfile.lock
@@ -159,7 +159,7 @@ GEM
|
||||
angularjs-rails (1.8.0)
|
||||
arel-helpers (2.14.0)
|
||||
activerecord (>= 3.1.0, < 8)
|
||||
ast (2.4.3)
|
||||
ast (2.4.2)
|
||||
attr_required (1.0.2)
|
||||
aws-eventstream (1.3.0)
|
||||
aws-partitions (1.929.0)
|
||||
@@ -180,7 +180,7 @@ GEM
|
||||
base64 (0.2.0)
|
||||
bcp47_spec (0.2.1)
|
||||
bcrypt (3.1.20)
|
||||
bigdecimal (3.2.2)
|
||||
bigdecimal (3.0.2)
|
||||
bindata (2.5.0)
|
||||
bindex (0.8.1)
|
||||
bootsnap (1.18.3)
|
||||
@@ -191,7 +191,7 @@ GEM
|
||||
bullet (7.1.6)
|
||||
activesupport (>= 3.0.0)
|
||||
uniform_notifier (~> 1.11)
|
||||
cable_ready (5.0.6)
|
||||
cable_ready (5.0.5)
|
||||
actionpack (>= 5.2)
|
||||
actionview (>= 5.2)
|
||||
activesupport (>= 5.2)
|
||||
@@ -246,7 +246,7 @@ GEM
|
||||
activerecord (>= 5.a)
|
||||
database_cleaner-core (~> 2.0.0)
|
||||
database_cleaner-core (2.0.1)
|
||||
datafoodconsortium-connector (1.1.0)
|
||||
datafoodconsortium-connector (1.0.0.pre.alpha.13)
|
||||
virtual_assembly-semantizer (~> 1.0, >= 1.0.5)
|
||||
date (3.3.4)
|
||||
debug (1.9.2)
|
||||
@@ -351,21 +351,9 @@ GEM
|
||||
concurrent-ruby (~> 1.0)
|
||||
i18n-js (3.9.2)
|
||||
i18n (>= 0.6.6)
|
||||
i18n-tasks (1.0.14)
|
||||
activesupport (>= 4.0.2)
|
||||
ast (>= 2.1.0)
|
||||
erubi
|
||||
highline (>= 2.0.0)
|
||||
i18n
|
||||
parser (>= 3.2.2.1)
|
||||
rails-i18n
|
||||
rainbow (>= 2.2.2, < 4.0)
|
||||
terminal-table (>= 1.5.1)
|
||||
image_processing (1.12.2)
|
||||
mini_magick (>= 4.9.5, < 5)
|
||||
ruby-vips (>= 2.0.17, < 3)
|
||||
imagen (0.2.0)
|
||||
parser (>= 2.5, != 2.5.1.1)
|
||||
immigrant (0.3.6)
|
||||
activerecord (>= 3.0)
|
||||
invisible_captcha (2.3.0)
|
||||
@@ -408,7 +396,7 @@ GEM
|
||||
activesupport (>= 4.2)
|
||||
jwt (2.8.1)
|
||||
base64
|
||||
knapsack_pro (8.1.2)
|
||||
knapsack_pro (7.4.0)
|
||||
rake
|
||||
language_server-protocol (3.17.0.3)
|
||||
launchy (3.0.0)
|
||||
@@ -497,15 +485,15 @@ GEM
|
||||
validate_url
|
||||
webfinger (~> 2.0)
|
||||
orm_adapter (0.5.0)
|
||||
ostruct (0.6.1)
|
||||
pagy (9.3.4)
|
||||
pagy (5.10.1)
|
||||
activesupport
|
||||
paper_trail (15.1.0)
|
||||
activerecord (>= 6.1)
|
||||
request_store (~> 1.4)
|
||||
parallel (1.24.0)
|
||||
paranoia (2.6.3)
|
||||
activerecord (>= 5.1, < 7.2)
|
||||
parser (3.3.8.0)
|
||||
parser (3.3.2.0)
|
||||
ast (~> 2.4.1)
|
||||
racc
|
||||
paypal-sdk-core (0.3.4)
|
||||
@@ -527,14 +515,14 @@ GEM
|
||||
psych (5.1.2)
|
||||
stringio
|
||||
public_suffix (5.0.5)
|
||||
puma (6.5.0)
|
||||
puma (6.4.2)
|
||||
nio4r (~> 2.0)
|
||||
query_count (1.1.1)
|
||||
activerecord (>= 4.2)
|
||||
railties (>= 4.2)
|
||||
raabro (1.4.0)
|
||||
racc (1.8.1)
|
||||
rack (2.2.11)
|
||||
racc (1.8.0)
|
||||
rack (2.2.9)
|
||||
rack-mini-profiler (2.3.4)
|
||||
rack (>= 1.2.0)
|
||||
rack-oauth2 (2.2.1)
|
||||
@@ -605,9 +593,8 @@ GEM
|
||||
rb-fsevent (0.11.2)
|
||||
rb-inotify (0.10.1)
|
||||
ffi (~> 1.0)
|
||||
rdf (3.3.2)
|
||||
rdf (3.3.1)
|
||||
bcp47_spec (~> 0.2)
|
||||
bigdecimal (~> 3.1, >= 3.1.5)
|
||||
link_header (~> 0.0, >= 0.0.8)
|
||||
rdoc (6.6.3.1)
|
||||
psych (>= 4.0.0)
|
||||
@@ -624,8 +611,8 @@ GEM
|
||||
responders (3.1.1)
|
||||
actionpack (>= 5.2)
|
||||
railties (>= 5.2)
|
||||
rexml (3.2.9)
|
||||
strscan
|
||||
rexml (3.2.8)
|
||||
strscan (>= 3.0.9)
|
||||
roadie (5.2.1)
|
||||
css_parser (~> 1.4)
|
||||
nokogiri (~> 1.15)
|
||||
@@ -660,7 +647,7 @@ GEM
|
||||
rspec-support (~> 3.13)
|
||||
rspec-retry (0.6.2)
|
||||
rspec-core (> 3.3)
|
||||
rspec-sql (0.0.3)
|
||||
rspec-sql (0.0.2)
|
||||
activesupport
|
||||
rspec
|
||||
rspec-support (3.13.1)
|
||||
@@ -696,10 +683,10 @@ GEM
|
||||
rubocop (~> 1.41)
|
||||
rubocop-factory_bot (2.25.1)
|
||||
rubocop (~> 1.41)
|
||||
rubocop-rails (2.28.0)
|
||||
rubocop-rails (2.24.1)
|
||||
activesupport (>= 4.2.0)
|
||||
rack (>= 1.1)
|
||||
rubocop (>= 1.52.0, < 2.0)
|
||||
rubocop (>= 1.33.0, < 2.0)
|
||||
rubocop-ast (>= 1.31.1, < 2.0)
|
||||
rubocop-rspec (2.29.2)
|
||||
rubocop (~> 1.40)
|
||||
@@ -717,7 +704,6 @@ GEM
|
||||
rubyzip (2.3.2)
|
||||
rufus-scheduler (3.8.2)
|
||||
fugit (~> 1.1, >= 1.1.6)
|
||||
rugged (1.9.0)
|
||||
sanitize (6.1.0)
|
||||
crass (~> 1.0.2)
|
||||
nokogiri (>= 1.12.0)
|
||||
@@ -746,7 +732,6 @@ GEM
|
||||
simplecov-html (~> 0.11)
|
||||
simplecov_json_formatter (~> 0.1)
|
||||
simplecov-html (0.12.3)
|
||||
simplecov-lcov (0.8.0)
|
||||
simplecov_json_formatter (0.1.4)
|
||||
spreadsheet_architect (5.0.0)
|
||||
caxlsx (>= 3.3.0, < 4)
|
||||
@@ -770,30 +755,27 @@ GEM
|
||||
state_machines-activerecord (0.9.0)
|
||||
activerecord (>= 6.0)
|
||||
state_machines-activemodel (>= 0.9.0)
|
||||
stimulus_reflex (3.5.5)
|
||||
actioncable (>= 5.2)
|
||||
actionpack (>= 5.2)
|
||||
actionview (>= 5.2)
|
||||
activesupport (>= 5.2)
|
||||
stimulus_reflex (3.5.1)
|
||||
actioncable (>= 5.2, < 8)
|
||||
actionpack (>= 5.2, < 8)
|
||||
actionview (>= 5.2, < 8)
|
||||
activesupport (>= 5.2, < 8)
|
||||
cable_ready (~> 5.0)
|
||||
nokogiri (~> 1.0)
|
||||
nokogiri-html5-inference (~> 0.3)
|
||||
ostruct (~> 0.6)
|
||||
rack (>= 2, < 4)
|
||||
railties (>= 5.2)
|
||||
railties (>= 5.2, < 8)
|
||||
redis (>= 4.0, < 6.0)
|
||||
stringex (2.8.6)
|
||||
stringio (3.1.0)
|
||||
stripe (11.1.0)
|
||||
strscan (3.1.2)
|
||||
strscan (3.1.0)
|
||||
swd (2.0.3)
|
||||
activesupport (>= 3)
|
||||
attr_required (>= 0.0.5)
|
||||
faraday (~> 2.0)
|
||||
faraday-follow_redirects
|
||||
temple (0.8.2)
|
||||
terminal-table (4.0.0)
|
||||
unicode-display_width (>= 1.1.1, < 4)
|
||||
thor (1.3.1)
|
||||
thread-local (1.1.0)
|
||||
tilt (2.3.0)
|
||||
@@ -808,14 +790,6 @@ GEM
|
||||
turbo-rails (>= 1.3.0)
|
||||
tzinfo (2.0.6)
|
||||
concurrent-ruby (~> 1.0)
|
||||
undercover (0.7.4)
|
||||
base64
|
||||
bigdecimal
|
||||
imagen (>= 0.2.0)
|
||||
rainbow (>= 2.1, < 4.0)
|
||||
rugged (>= 0.27, < 1.10)
|
||||
simplecov
|
||||
simplecov_json_formatter
|
||||
unicode-display_width (2.5.0)
|
||||
uniform_notifier (1.16.0)
|
||||
uri (0.13.0)
|
||||
@@ -891,7 +865,7 @@ DEPENDENCIES
|
||||
angularjs-rails (= 1.8.0)
|
||||
arel-helpers (~> 2.12)
|
||||
aws-sdk-s3
|
||||
bigdecimal
|
||||
bigdecimal (= 3.0.2)
|
||||
bootsnap
|
||||
bugsnag
|
||||
bullet
|
||||
@@ -930,7 +904,6 @@ DEPENDENCIES
|
||||
highline (= 2.0.3)
|
||||
i18n
|
||||
i18n-js (~> 3.9.0)
|
||||
i18n-tasks
|
||||
image_processing
|
||||
immigrant
|
||||
invisible_captcha
|
||||
@@ -953,7 +926,7 @@ DEPENDENCIES
|
||||
omniauth_openid_connect
|
||||
openid_connect
|
||||
order_management!
|
||||
pagy (~> 9)
|
||||
pagy (~> 5.1)
|
||||
paper_trail
|
||||
paranoia (~> 2.4)
|
||||
paypal-sdk-merchant (= 1.117.2)
|
||||
@@ -992,7 +965,6 @@ DEPENDENCIES
|
||||
sidekiq
|
||||
sidekiq-scheduler
|
||||
simplecov
|
||||
simplecov-lcov
|
||||
spreadsheet_architect
|
||||
spring
|
||||
spring-commands-rspec
|
||||
@@ -1005,7 +977,6 @@ DEPENDENCIES
|
||||
timecop
|
||||
turbo-rails
|
||||
turbo_power
|
||||
undercover
|
||||
valid_email2
|
||||
validates_lengths_from_database
|
||||
vcr
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
# Foreman Procfile for Docker env. Start all dev server processes with: `bundle exec foreman start -f Procfile.docker`
|
||||
|
||||
webpack: WEBPACKER_DEV_SERVER_HOST=0.0.0.0 ./bin/webpack-dev-server
|
||||
sidekiq: DEV_CACHING=true bundle exec sidekiq -q mailers -q default
|
||||
rails: WEBPACKER_DEV_SERVER_HOST=0.0.0.0 DEV_CACHING=true bundle exec rails s -p 3000 -b 0.0.0.0
|
||||
@@ -67,5 +67,8 @@
|
||||
// foundation
|
||||
//= require ../shared/mm-foundation-tpls-0.9.0-20180826174721.min.js
|
||||
|
||||
// LocalStorage
|
||||
//= require ../shared/angular-local-storage.js
|
||||
|
||||
// requires the rest of the JS code in this folder
|
||||
//= require_tree .
|
||||
|
||||
@@ -307,6 +307,9 @@ filterSubmitProducts = (productsToFilter) ->
|
||||
variantHasUpdatableProperty = result.hasUpdatableProperty
|
||||
filteredVariants.push filteredVariant if variantHasUpdatableProperty
|
||||
|
||||
if product.hasOwnProperty("sku")
|
||||
filteredProduct.sku = product.sku
|
||||
hasUpdatableProperty = true
|
||||
if product.hasOwnProperty("name")
|
||||
filteredProduct.name = product.name
|
||||
hasUpdatableProperty = true
|
||||
|
||||
@@ -55,6 +55,12 @@ angular.module("admin.enterprises")
|
||||
else
|
||||
alert ("#{manager.email}" + " " + t("is_already_manager"))
|
||||
|
||||
$scope.removeLogo = ->
|
||||
$scope.performEnterpriseAction("removeLogo", "immediate_logo_removal_warning", "removed_logo_successfully")
|
||||
|
||||
$scope.removePromoImage = ->
|
||||
$scope.performEnterpriseAction("removePromoImage", "immediate_promo_image_removal_warning", "removed_promo_image_successfully")
|
||||
|
||||
$scope.performEnterpriseAction = (enterpriseActionName, warning_message_key, success_message_key) ->
|
||||
return unless confirm($scope.translation(warning_message_key))
|
||||
|
||||
|
||||
@@ -19,6 +19,18 @@ angular.module("admin.lineItems").controller 'LineItemsCtrl', ($scope, $timeout,
|
||||
$scope.page = 1
|
||||
$scope.per_page = $scope.per_page_options[0].id
|
||||
$scope.filterByVariantId = null
|
||||
searchThrough = ["order_distributor_name",
|
||||
"order_bill_address_phone",
|
||||
"order_bill_address_firstname",
|
||||
"order_bill_address_lastname",
|
||||
"order_bill_address_full_name",
|
||||
"order_bill_address_full_name_reversed",
|
||||
"order_bill_address_full_name_with_comma",
|
||||
"order_bill_address_full_name_with_comma_reversed",
|
||||
"variant_supplier_name",
|
||||
"order_email",
|
||||
"order_number",
|
||||
"product_name"].join("_or_") + "_cont"
|
||||
|
||||
$scope.confirmRefresh = ->
|
||||
LineItems.allSaved() || confirm(t("unsaved_changes_warning"))
|
||||
@@ -63,10 +75,11 @@ angular.module("admin.lineItems").controller 'LineItemsCtrl', ($scope, $timeout,
|
||||
[formattedStartDate, formattedEndDate] = $scope.formatDates($scope.startDate, $scope.endDate)
|
||||
|
||||
RequestMonitor.load LineItems.index(
|
||||
"q[#{searchThrough}]": $scope.query,
|
||||
"q[variant_id_eq]": $scope.filterByVariantId if $scope.filterByVariantId,
|
||||
"q[order_state_not_eq]": "canceled",
|
||||
"q[order_shipment_state_not_eq]": "shipped",
|
||||
"q[order_completed_at_not_null]": "true",
|
||||
"q[variant_id_eq]": $scope.filterByVariantId if $scope.filterByVariantId,
|
||||
"q[order_distributor_id_eq]": $scope.distributorFilter,
|
||||
"q[variant_supplier_id_eq]": $scope.supplierFilter,
|
||||
"q[order_order_cycle_id_eq]": $scope.orderCycleFilter,
|
||||
@@ -74,8 +87,7 @@ angular.module("admin.lineItems").controller 'LineItemsCtrl', ($scope, $timeout,
|
||||
"q[order_completed_at_lt]": if formattedEndDate then formattedEndDate else undefined,
|
||||
"q[s]": "order_completed_at desc",
|
||||
"page": $scope.page,
|
||||
"per_page": $scope.per_page,
|
||||
"search_query": $scope.query
|
||||
"per_page": $scope.per_page
|
||||
)
|
||||
|
||||
$scope.formatDates = (startDate, endDate) ->
|
||||
@@ -85,7 +97,7 @@ angular.module("admin.lineItems").controller 'LineItemsCtrl', ($scope, $timeout,
|
||||
|
||||
$scope.loadAssociatedData = ->
|
||||
RequestMonitor.load $scope.distributors = Enterprises.index(action: "visible", ams_prefix: "basic", "q[sells_in][]": ["own", "any"])
|
||||
RequestMonitor.load $scope.orderCycles = OrderCycles.index(ams_prefix: "basic", as: "distributor", "q[orders_close_at_gt]": "#{moment().subtract(1,'year').format()}")
|
||||
RequestMonitor.load $scope.orderCycles = OrderCycles.index(ams_prefix: "basic", as: "distributor", "q[orders_close_at_gt]": "#{moment().subtract(90,'days').format()}")
|
||||
RequestMonitor.load $scope.suppliers = Enterprises.index(action: "visible", ams_prefix: "basic", "q[is_primary_producer_eq]": "true")
|
||||
|
||||
$scope.dereferenceLoadedData = ->
|
||||
|
||||
@@ -5,8 +5,6 @@ angular.module("admin.orders").controller "orderCtrl", ($scope, shops, orderCycl
|
||||
|
||||
$scope.distributor_id = parseInt($attrs.ofnDistributorId)
|
||||
$scope.order_cycle_id = parseInt($attrs.ofnOrderCycleId)
|
||||
$scope.search_variants_as = $attrs.ofnSearchVariantsAs
|
||||
$scope.order_id = $attrs.ofnOrderId
|
||||
|
||||
$scope.validOrderCycle = (oc) ->
|
||||
$scope.orderCycleHasDistributor oc, parseInt($scope.distributor_id)
|
||||
|
||||
@@ -8,4 +8,10 @@ angular.module("admin.resources").factory 'EnterpriseResource', ($resource) ->
|
||||
isArray: true
|
||||
'update':
|
||||
method: 'PUT'
|
||||
'removeLogo':
|
||||
url: '/api/v0/enterprises/:id/logo.json'
|
||||
method: 'DELETE'
|
||||
'removePromoImage':
|
||||
url: '/api/v0/enterprises/:id/promo_image.json'
|
||||
method: 'DELETE'
|
||||
})
|
||||
|
||||
@@ -39,6 +39,17 @@ angular.module("admin.resources").factory 'Enterprises', ($q, $filter, Enterpris
|
||||
resetAttribute: (enterprise, attribute) ->
|
||||
enterprise[attribute] = @pristineByID[enterprise.id][attribute]
|
||||
|
||||
performActionOnEnterpriseResource = (resourceAction) ->
|
||||
(enterprise) ->
|
||||
deferred = $q.defer()
|
||||
resourceAction({id: enterprise.permalink}, ((data) =>
|
||||
@pristineByID[enterprise.id] = angular.copy(data)
|
||||
deferred.resolve(data)
|
||||
), ((response) ->
|
||||
deferred.reject(response)
|
||||
))
|
||||
deferred.promise
|
||||
|
||||
findByID: (id) ->
|
||||
@byID[id]
|
||||
|
||||
@@ -50,3 +61,5 @@ angular.module("admin.resources").factory 'Enterprises', ($q, $filter, Enterpris
|
||||
$filter('filter')(enterprises, term)
|
||||
|
||||
|
||||
removeLogo: performActionOnEnterpriseResource(EnterpriseResource.removeLogo)
|
||||
removePromoImage: performActionOnEnterpriseResource(EnterpriseResource.removePromoImage)
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
angular.module("admin.indexUtils").factory 'KeyValueMapStore', (localStorageService)->
|
||||
new class KeyValueMapStore
|
||||
localStorageKey: ''
|
||||
storableKeys: []
|
||||
|
||||
constructor: ->
|
||||
localStorageService.setStorageType("sessionStorage")
|
||||
|
||||
getStoredKeyValueMap: ->
|
||||
localStorageService.get(@localStorageKey) || {}
|
||||
|
||||
setStoredValues: (source) ->
|
||||
keyValueMap = {}
|
||||
for key in @storableKeys
|
||||
keyValueMap[key] = source[key]
|
||||
localStorageService.set(@localStorageKey, keyValueMap)
|
||||
|
||||
restoreValues: (target) ->
|
||||
storedKeyValueMap = @getStoredKeyValueMap()
|
||||
|
||||
return false if _.isEmpty(storedKeyValueMap)
|
||||
|
||||
for k,v of storedKeyValueMap
|
||||
target[k] = v
|
||||
|
||||
return true
|
||||
|
||||
clearKeyValueMap: () ->
|
||||
localStorageService.remove(@localStorageKey)
|
||||
@@ -187,17 +187,18 @@ addVariantFromStockLocation = function() {
|
||||
$('#stock_details').hide();
|
||||
|
||||
var variant_id = $('input.variant_autocomplete').val();
|
||||
var quantity = $("input.quantity").val();
|
||||
var stock_location_id = $(this).data('stock-location-id');
|
||||
var quantity = $("input.quantity[data-stock-location-id='" + stock_location_id + "']").val();
|
||||
|
||||
var shipment = _.find(shipments, function(shipment){
|
||||
return shipment.state == 'ready' || shipment.state == 'pending';
|
||||
return shipment.stock_location_id == stock_location_id && (shipment.state == 'ready' || shipment.state == 'pending');
|
||||
});
|
||||
|
||||
if(shipment==undefined){
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: Spree.url(Spree.routes.orders_api + "/" + order_number + "/shipments.json"),
|
||||
data: { variant_id: variant_id, quantity: quantity }
|
||||
data: { variant_id: variant_id, quantity: quantity, stock_location_id: stock_location_id }
|
||||
}).done(function( msg ) {
|
||||
window.location.reload();
|
||||
}).error(function( msg ) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
angular.module("admin.tagRules").directive 'newTagRuleDialog', ($rootScope, $compile, $templateCache, DialogDefaults, ruleTypes) ->
|
||||
angular.module("admin.tagRules").directive 'newTagRuleDialog', ($rootScope, $compile, $templateCache, DialogDefaults) ->
|
||||
restrict: 'A'
|
||||
scope:
|
||||
tagGroup: '='
|
||||
@@ -7,7 +7,12 @@ angular.module("admin.tagRules").directive 'newTagRuleDialog', ($rootScope, $com
|
||||
# Compile modal template
|
||||
template = $compile($templateCache.get('admin/new_tag_rule_dialog.html'))(scope)
|
||||
|
||||
scope.ruleTypes = ruleTypes
|
||||
scope.ruleTypes = [
|
||||
{ id: "FilterProducts", name: t('js.tag_rules.show_hide_variants') }
|
||||
{ id: "FilterShippingMethods", name: t('js.tag_rules.show_hide_shipping') }
|
||||
{ id: "FilterPaymentMethods", name: t('js.tag_rules.show_hide_payment') }
|
||||
{ id: "FilterOrderCycles", name: t('js.tag_rules.show_hide_order_cycles') }
|
||||
]
|
||||
|
||||
scope.ruleType = scope.ruleTypes[0].id
|
||||
|
||||
|
||||
@@ -26,8 +26,6 @@ angular.module("admin.utils").directive "variantAutocomplete", ($timeout) ->
|
||||
order_cycle_id: scope.order_cycle_id
|
||||
eligible_for_subscriptions: scope.eligible_for_subscriptions
|
||||
include_out_of_stock: scope.include_out_of_stock
|
||||
search_variants_as: scope.search_variants_as
|
||||
order_id: scope.order_id
|
||||
results: (data, page) ->
|
||||
window.variants = data # this is how spree auto complete JS code picks up variants
|
||||
results: data
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#= require angular-google-maps.min.js
|
||||
#= require ../shared/mm-foundation-tpls-0.9.0-20180826174721.min.js
|
||||
#= require ../shared/ng-infinite-scroll.min.js
|
||||
#= require ../shared/angular-local-storage.js
|
||||
#= require ../shared/angular-slideables.js
|
||||
#= require ../shared/shared
|
||||
#= require_tree ../shared/directives
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
angular.module("Darkswarm", [
|
||||
'ngResource',
|
||||
'mm.foundation',
|
||||
'LocalStorageModule',
|
||||
'infinite-scroll',
|
||||
'angular-flash.service',
|
||||
'templates',
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
angular.module('Darkswarm').directive "ofnDisableScroll", ()->
|
||||
# Stops scrolling from incrementing or decrementing input value
|
||||
# Useful for number inputs
|
||||
restrict: 'A'
|
||||
link: (scope, element, attrs)->
|
||||
element.bind 'focus', ->
|
||||
element.bind 'mousewheel', (e)->
|
||||
e.preventDefault()
|
||||
element.bind 'blur', ->
|
||||
element.unbind 'mousewheel'
|
||||
@@ -0,0 +1,5 @@
|
||||
angular.module('Darkswarm').directive "integer", ->
|
||||
restrict: 'A'
|
||||
link: (scope, elem, attr) ->
|
||||
elem.bind 'input', ->
|
||||
elem.val Math.round(elem.val())
|
||||
@@ -20,13 +20,10 @@ angular.module('Darkswarm').directive 'mapSearch', ($timeout, Search) ->
|
||||
$timeout =>
|
||||
map = ctrl.getMap()
|
||||
|
||||
if !map
|
||||
alert(t('gmap_load_failure'))
|
||||
else
|
||||
searchBox = scope.createSearchBox map
|
||||
scope.bindSearchResponse map, searchBox
|
||||
scope.biasResults map, searchBox
|
||||
scope.performUrlSearch map
|
||||
searchBox = scope.createSearchBox map
|
||||
scope.bindSearchResponse map, searchBox
|
||||
scope.biasResults map, searchBox
|
||||
scope.performUrlSearch map
|
||||
|
||||
scope.createSearchBox = (map) ->
|
||||
map.controls[google.maps.ControlPosition.TOP_LEFT].push scope.input
|
||||
|
||||
@@ -13,8 +13,6 @@ angular.module('Darkswarm').directive 'ofnOpenStreetMap', ($window, MapCentreCal
|
||||
|
||||
buildMarker = (enterprise, latlng, title) ->
|
||||
icon = L.icon
|
||||
iconAnchor: [14, 33]
|
||||
iconSize: [28, 33]
|
||||
iconUrl: enterprise.icon
|
||||
marker = L.marker latlng,
|
||||
draggable: true,
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
angular.module('Darkswarm').directive "renderSvg", ()->
|
||||
# Magical directive that'll render SVGs from URLs
|
||||
# If only there were a neater way of doing this
|
||||
restrict: 'E'
|
||||
priority: 99
|
||||
template: "<svg-wrapper></svg-wrapper>"
|
||||
|
||||
# Fetch SVG via ajax, inject into page using DOM
|
||||
link: (scope, elem, attr)->
|
||||
if /.svg/.test attr.path # Only do this if we've got an svg
|
||||
$.ajax
|
||||
url: attr.path
|
||||
success: (html)->
|
||||
elem.html($(html).find("svg"))
|
||||
@@ -0,0 +1,9 @@
|
||||
angular.module('Darkswarm').directive "ofnScrollTo", ($location, $anchorScroll)->
|
||||
# Onclick sets $location.hash to attrs.ofnScrollTo
|
||||
# Then triggers anchorScroll
|
||||
restrict: 'A'
|
||||
link: (scope, element, attrs)->
|
||||
element.bind 'click', (ev)->
|
||||
ev.stopPropagation()
|
||||
$location.hash attrs.ofnScrollTo
|
||||
$anchorScroll()
|
||||
@@ -1,4 +1,4 @@
|
||||
angular.module('Darkswarm').factory 'Cart', (CurrentOrder, Variants, $timeout, $http, $modal, $rootScope, $resource, Messages) ->
|
||||
angular.module('Darkswarm').factory 'Cart', (CurrentOrder, Variants, $timeout, $http, $modal, $rootScope, $resource, localStorageService, Messages) ->
|
||||
# Handles syncing of current cart/order state to server
|
||||
new class Cart
|
||||
dirty: false
|
||||
@@ -113,6 +113,7 @@ angular.module('Darkswarm').factory 'Cart', (CurrentOrder, Variants, $timeout, $
|
||||
|
||||
clear: ->
|
||||
@line_items = []
|
||||
localStorageService.clearAll() # One day this will have to be moar GRANULAR
|
||||
|
||||
isOnlyItemInOrder: (id) =>
|
||||
deletedItem = @line_items_finalised.find((item) -> item.id == id)
|
||||
|
||||
546
app/assets/javascripts/shared/angular-local-storage.js
vendored
Normal file
546
app/assets/javascripts/shared/angular-local-storage.js
vendored
Normal file
@@ -0,0 +1,546 @@
|
||||
/**
|
||||
* An Angular module that gives you access to the browsers local storage
|
||||
* @version v0.5.0 - 2016-08-29
|
||||
* @link https://github.com/grevory/angular-local-storage
|
||||
* @author grevory <greg@gregpike.ca>
|
||||
* @license MIT License, http://www.opensource.org/licenses/MIT
|
||||
*/
|
||||
(function (window, angular) {
|
||||
var isDefined = angular.isDefined,
|
||||
isUndefined = angular.isUndefined,
|
||||
isNumber = angular.isNumber,
|
||||
isObject = angular.isObject,
|
||||
isArray = angular.isArray,
|
||||
extend = angular.extend,
|
||||
toJson = angular.toJson;
|
||||
|
||||
angular
|
||||
.module('LocalStorageModule', [])
|
||||
.provider('localStorageService', function() {
|
||||
// You should set a prefix to avoid overwriting any local storage variables from the rest of your app
|
||||
// e.g. localStorageServiceProvider.setPrefix('yourAppName');
|
||||
// With provider you can use config as this:
|
||||
// myApp.config(function (localStorageServiceProvider) {
|
||||
// localStorageServiceProvider.prefix = 'yourAppName';
|
||||
// });
|
||||
this.prefix = 'ls';
|
||||
|
||||
// You could change web storage type localstorage or sessionStorage
|
||||
this.storageType = 'localStorage';
|
||||
|
||||
// Cookie options (usually in case of fallback)
|
||||
// expiry = Number of days before cookies expire // 0 = Does not expire
|
||||
// path = The web path the cookie represents
|
||||
// secure = Wether the cookies should be secure (i.e only sent on HTTPS requests)
|
||||
this.cookie = {
|
||||
expiry: 30,
|
||||
path: '/',
|
||||
secure: false
|
||||
};
|
||||
|
||||
// Decides wether we should default to cookies if localstorage is not supported.
|
||||
this.defaultToCookie = true;
|
||||
|
||||
// Send signals for each of the following actions?
|
||||
this.notify = {
|
||||
setItem: true,
|
||||
removeItem: false
|
||||
};
|
||||
|
||||
// Setter for the prefix
|
||||
this.setPrefix = function(prefix) {
|
||||
this.prefix = prefix;
|
||||
return this;
|
||||
};
|
||||
|
||||
// Setter for the storageType
|
||||
this.setStorageType = function(storageType) {
|
||||
this.storageType = storageType;
|
||||
return this;
|
||||
};
|
||||
// Setter for defaultToCookie value, default is true.
|
||||
this.setDefaultToCookie = function (shouldDefault) {
|
||||
this.defaultToCookie = !!shouldDefault; // Double-not to make sure it's a bool value.
|
||||
return this;
|
||||
};
|
||||
// Setter for cookie config
|
||||
this.setStorageCookie = function(exp, path, secure) {
|
||||
this.cookie.expiry = exp;
|
||||
this.cookie.path = path;
|
||||
this.cookie.secure = secure;
|
||||
return this;
|
||||
};
|
||||
|
||||
// Setter for cookie domain
|
||||
this.setStorageCookieDomain = function(domain) {
|
||||
this.cookie.domain = domain;
|
||||
return this;
|
||||
};
|
||||
|
||||
// Setter for notification config
|
||||
// itemSet & itemRemove should be booleans
|
||||
this.setNotify = function(itemSet, itemRemove) {
|
||||
this.notify = {
|
||||
setItem: itemSet,
|
||||
removeItem: itemRemove
|
||||
};
|
||||
return this;
|
||||
};
|
||||
|
||||
this.$get = ['$rootScope', '$window', '$document', '$parse','$timeout', function($rootScope, $window, $document, $parse, $timeout) {
|
||||
var self = this;
|
||||
var prefix = self.prefix;
|
||||
var cookie = self.cookie;
|
||||
var notify = self.notify;
|
||||
var storageType = self.storageType;
|
||||
var webStorage;
|
||||
|
||||
// When Angular's $document is not available
|
||||
if (!$document) {
|
||||
$document = document;
|
||||
} else if ($document[0]) {
|
||||
$document = $document[0];
|
||||
}
|
||||
|
||||
// If there is a prefix set in the config lets use that with an appended period for readability
|
||||
if (prefix.substr(-1) !== '.') {
|
||||
prefix = !!prefix ? prefix + '.' : '';
|
||||
}
|
||||
var deriveQualifiedKey = function(key) {
|
||||
return prefix + key;
|
||||
};
|
||||
|
||||
// Removes prefix from the key.
|
||||
var underiveQualifiedKey = function (key) {
|
||||
return key.replace(new RegExp('^' + prefix, 'g'), '');
|
||||
};
|
||||
|
||||
// Check if the key is within our prefix namespace.
|
||||
var isKeyPrefixOurs = function (key) {
|
||||
return key.indexOf(prefix) === 0;
|
||||
};
|
||||
|
||||
// Checks the browser to see if local storage is supported
|
||||
var checkSupport = function () {
|
||||
try {
|
||||
var supported = (storageType in $window && $window[storageType] !== null);
|
||||
|
||||
// When Safari (OS X or iOS) is in private browsing mode, it appears as though localStorage
|
||||
// is available, but trying to call .setItem throws an exception.
|
||||
//
|
||||
// "QUOTA_EXCEEDED_ERR: DOM Exception 22: An attempt was made to add something to storage
|
||||
// that exceeded the quota."
|
||||
var key = deriveQualifiedKey('__' + Math.round(Math.random() * 1e7));
|
||||
if (supported) {
|
||||
webStorage = $window[storageType];
|
||||
webStorage.setItem(key, '');
|
||||
webStorage.removeItem(key);
|
||||
}
|
||||
|
||||
return supported;
|
||||
} catch (e) {
|
||||
// Only change storageType to cookies if defaulting is enabled.
|
||||
if (self.defaultToCookie)
|
||||
storageType = 'cookie';
|
||||
$rootScope.$broadcast('LocalStorageModule.notification.error', e.message);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
var browserSupportsLocalStorage = checkSupport();
|
||||
|
||||
// Directly adds a value to local storage
|
||||
// If local storage is not available in the browser use cookies
|
||||
// Example use: localStorageService.add('library','angular');
|
||||
var addToLocalStorage = function (key, value, type) {
|
||||
setStorageType(type);
|
||||
|
||||
// Let's convert undefined values to null to get the value consistent
|
||||
if (isUndefined(value)) {
|
||||
value = null;
|
||||
} else {
|
||||
value = toJson(value);
|
||||
}
|
||||
|
||||
// If this browser does not support local storage use cookies
|
||||
if (!browserSupportsLocalStorage && self.defaultToCookie || self.storageType === 'cookie') {
|
||||
if (!browserSupportsLocalStorage) {
|
||||
$rootScope.$broadcast('LocalStorageModule.notification.warning', 'LOCAL_STORAGE_NOT_SUPPORTED');
|
||||
}
|
||||
|
||||
if (notify.setItem) {
|
||||
$rootScope.$broadcast('LocalStorageModule.notification.setitem', {key: key, newvalue: value, storageType: 'cookie'});
|
||||
}
|
||||
return addToCookies(key, value);
|
||||
}
|
||||
|
||||
try {
|
||||
if (webStorage) {
|
||||
webStorage.setItem(deriveQualifiedKey(key), value);
|
||||
}
|
||||
if (notify.setItem) {
|
||||
$rootScope.$broadcast('LocalStorageModule.notification.setitem', {key: key, newvalue: value, storageType: self.storageType});
|
||||
}
|
||||
} catch (e) {
|
||||
$rootScope.$broadcast('LocalStorageModule.notification.error', e.message);
|
||||
return addToCookies(key, value);
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
// Directly get a value from local storage
|
||||
// Example use: localStorageService.get('library'); // returns 'angular'
|
||||
var getFromLocalStorage = function (key, type) {
|
||||
setStorageType(type);
|
||||
|
||||
if (!browserSupportsLocalStorage && self.defaultToCookie || self.storageType === 'cookie') {
|
||||
if (!browserSupportsLocalStorage) {
|
||||
$rootScope.$broadcast('LocalStorageModule.notification.warning', 'LOCAL_STORAGE_NOT_SUPPORTED');
|
||||
}
|
||||
|
||||
return getFromCookies(key);
|
||||
}
|
||||
|
||||
var item = webStorage ? webStorage.getItem(deriveQualifiedKey(key)) : null;
|
||||
// angular.toJson will convert null to 'null', so a proper conversion is needed
|
||||
// FIXME not a perfect solution, since a valid 'null' string can't be stored
|
||||
if (!item || item === 'null') {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
return JSON.parse(item);
|
||||
} catch (e) {
|
||||
return item;
|
||||
}
|
||||
};
|
||||
|
||||
// Remove an item from local storage
|
||||
// Example use: localStorageService.remove('library'); // removes the key/value pair of library='angular'
|
||||
//
|
||||
// This is var-arg removal, check the last argument to see if it is a storageType
|
||||
// and set type accordingly before removing.
|
||||
//
|
||||
var removeFromLocalStorage = function () {
|
||||
// can't pop on arguments, so we do this
|
||||
var consumed = 0;
|
||||
if (arguments.length >= 1 &&
|
||||
(arguments[arguments.length - 1] === 'localStorage' ||
|
||||
arguments[arguments.length - 1] === 'sessionStorage')) {
|
||||
consumed = 1;
|
||||
setStorageType(arguments[arguments.length - 1]);
|
||||
}
|
||||
|
||||
var i, key;
|
||||
for (i = 0; i < arguments.length - consumed; i++) {
|
||||
key = arguments[i];
|
||||
if (!browserSupportsLocalStorage && self.defaultToCookie || self.storageType === 'cookie') {
|
||||
if (!browserSupportsLocalStorage) {
|
||||
$rootScope.$broadcast('LocalStorageModule.notification.warning', 'LOCAL_STORAGE_NOT_SUPPORTED');
|
||||
}
|
||||
|
||||
if (notify.removeItem) {
|
||||
$rootScope.$broadcast('LocalStorageModule.notification.removeitem', {key: key, storageType: 'cookie'});
|
||||
}
|
||||
removeFromCookies(key);
|
||||
}
|
||||
else {
|
||||
try {
|
||||
webStorage.removeItem(deriveQualifiedKey(key));
|
||||
if (notify.removeItem) {
|
||||
$rootScope.$broadcast('LocalStorageModule.notification.removeitem', {
|
||||
key: key,
|
||||
storageType: self.storageType
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
$rootScope.$broadcast('LocalStorageModule.notification.error', e.message);
|
||||
removeFromCookies(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Return array of keys for local storage
|
||||
// Example use: var keys = localStorageService.keys()
|
||||
var getKeysForLocalStorage = function (type) {
|
||||
setStorageType(type);
|
||||
|
||||
if (!browserSupportsLocalStorage) {
|
||||
$rootScope.$broadcast('LocalStorageModule.notification.warning', 'LOCAL_STORAGE_NOT_SUPPORTED');
|
||||
return [];
|
||||
}
|
||||
|
||||
var prefixLength = prefix.length;
|
||||
var keys = [];
|
||||
for (var key in webStorage) {
|
||||
// Only return keys that are for this app
|
||||
if (key.substr(0, prefixLength) === prefix) {
|
||||
try {
|
||||
keys.push(key.substr(prefixLength));
|
||||
} catch (e) {
|
||||
$rootScope.$broadcast('LocalStorageModule.notification.error', e.Description);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
}
|
||||
return keys;
|
||||
};
|
||||
|
||||
// Remove all data for this app from local storage
|
||||
// Also optionally takes a regular expression string and removes the matching key-value pairs
|
||||
// Example use: localStorageService.clearAll();
|
||||
// Should be used mostly for development purposes
|
||||
var clearAllFromLocalStorage = function (regularExpression, type) {
|
||||
setStorageType(type);
|
||||
|
||||
// Setting both regular expressions independently
|
||||
// Empty strings result in catchall RegExp
|
||||
var prefixRegex = !!prefix ? new RegExp('^' + prefix) : new RegExp();
|
||||
var testRegex = !!regularExpression ? new RegExp(regularExpression) : new RegExp();
|
||||
|
||||
if (!browserSupportsLocalStorage && self.defaultToCookie || self.storageType === 'cookie') {
|
||||
if (!browserSupportsLocalStorage) {
|
||||
$rootScope.$broadcast('LocalStorageModule.notification.warning', 'LOCAL_STORAGE_NOT_SUPPORTED');
|
||||
}
|
||||
return clearAllFromCookies();
|
||||
}
|
||||
if (!browserSupportsLocalStorage && !self.defaultToCookie)
|
||||
return false;
|
||||
var prefixLength = prefix.length;
|
||||
|
||||
for (var key in webStorage) {
|
||||
// Only remove items that are for this app and match the regular expression
|
||||
if (prefixRegex.test(key) && testRegex.test(key.substr(prefixLength))) {
|
||||
try {
|
||||
removeFromLocalStorage(key.substr(prefixLength));
|
||||
} catch (e) {
|
||||
$rootScope.$broadcast('LocalStorageModule.notification.error', e.message);
|
||||
return clearAllFromCookies();
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
// Checks the browser to see if cookies are supported
|
||||
var browserSupportsCookies = (function() {
|
||||
try {
|
||||
return $window.navigator.cookieEnabled ||
|
||||
("cookie" in $document && ($document.cookie.length > 0 ||
|
||||
($document.cookie = "test").indexOf.call($document.cookie, "test") > -1));
|
||||
} catch (e) {
|
||||
$rootScope.$broadcast('LocalStorageModule.notification.error', e.message);
|
||||
return false;
|
||||
}
|
||||
}());
|
||||
|
||||
// Directly adds a value to cookies
|
||||
// Typically used as a fallback if local storage is not available in the browser
|
||||
// Example use: localStorageService.cookie.add('library','angular');
|
||||
var addToCookies = function (key, value, daysToExpiry, secure) {
|
||||
|
||||
if (isUndefined(value)) {
|
||||
return false;
|
||||
} else if(isArray(value) || isObject(value)) {
|
||||
value = toJson(value);
|
||||
}
|
||||
|
||||
if (!browserSupportsCookies) {
|
||||
$rootScope.$broadcast('LocalStorageModule.notification.error', 'COOKIES_NOT_SUPPORTED');
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
var expiry = '',
|
||||
expiryDate = new Date(),
|
||||
cookieDomain = '';
|
||||
|
||||
if (value === null) {
|
||||
// Mark that the cookie has expired one day ago
|
||||
expiryDate.setTime(expiryDate.getTime() + (-1 * 24 * 60 * 60 * 1000));
|
||||
expiry = "; expires=" + expiryDate.toGMTString();
|
||||
value = '';
|
||||
} else if (isNumber(daysToExpiry) && daysToExpiry !== 0) {
|
||||
expiryDate.setTime(expiryDate.getTime() + (daysToExpiry * 24 * 60 * 60 * 1000));
|
||||
expiry = "; expires=" + expiryDate.toGMTString();
|
||||
} else if (cookie.expiry !== 0) {
|
||||
expiryDate.setTime(expiryDate.getTime() + (cookie.expiry * 24 * 60 * 60 * 1000));
|
||||
expiry = "; expires=" + expiryDate.toGMTString();
|
||||
}
|
||||
if (!!key) {
|
||||
var cookiePath = "; path=" + cookie.path;
|
||||
if (cookie.domain) {
|
||||
cookieDomain = "; domain=" + cookie.domain;
|
||||
}
|
||||
/* Providing the secure parameter always takes precedence over config
|
||||
* (allows developer to mix and match secure + non-secure) */
|
||||
if (typeof secure === 'boolean') {
|
||||
if (secure === true) {
|
||||
/* We've explicitly specified secure,
|
||||
* add the secure attribute to the cookie (after domain) */
|
||||
cookieDomain += "; secure";
|
||||
}
|
||||
// else - secure has been supplied but isn't true - so don't set secure flag, regardless of what config says
|
||||
}
|
||||
else if (cookie.secure === true) {
|
||||
// secure parameter wasn't specified, get default from config
|
||||
cookieDomain += "; secure";
|
||||
}
|
||||
$document.cookie = deriveQualifiedKey(key) + "=" + encodeURIComponent(value) + expiry + cookiePath + cookieDomain;
|
||||
}
|
||||
} catch (e) {
|
||||
$rootScope.$broadcast('LocalStorageModule.notification.error', e.message);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
// Directly get a value from a cookie
|
||||
// Example use: localStorageService.cookie.get('library'); // returns 'angular'
|
||||
var getFromCookies = function (key) {
|
||||
if (!browserSupportsCookies) {
|
||||
$rootScope.$broadcast('LocalStorageModule.notification.error', 'COOKIES_NOT_SUPPORTED');
|
||||
return false;
|
||||
}
|
||||
|
||||
var cookies = $document.cookie && $document.cookie.split(';') || [];
|
||||
for(var i=0; i < cookies.length; i++) {
|
||||
var thisCookie = cookies[i];
|
||||
while (thisCookie.charAt(0) === ' ') {
|
||||
thisCookie = thisCookie.substring(1,thisCookie.length);
|
||||
}
|
||||
if (thisCookie.indexOf(deriveQualifiedKey(key) + '=') === 0) {
|
||||
var storedValues = decodeURIComponent(thisCookie.substring(prefix.length + key.length + 1, thisCookie.length));
|
||||
try {
|
||||
return JSON.parse(storedValues);
|
||||
} catch(e) {
|
||||
return storedValues;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
var removeFromCookies = function (key) {
|
||||
addToCookies(key,null);
|
||||
};
|
||||
|
||||
var clearAllFromCookies = function () {
|
||||
var thisCookie = null;
|
||||
var prefixLength = prefix.length;
|
||||
var cookies = $document.cookie.split(';');
|
||||
for(var i = 0; i < cookies.length; i++) {
|
||||
thisCookie = cookies[i];
|
||||
|
||||
while (thisCookie.charAt(0) === ' ') {
|
||||
thisCookie = thisCookie.substring(1, thisCookie.length);
|
||||
}
|
||||
|
||||
var key = thisCookie.substring(prefixLength, thisCookie.indexOf('='));
|
||||
removeFromCookies(key);
|
||||
}
|
||||
};
|
||||
|
||||
var getStorageType = function() {
|
||||
return storageType;
|
||||
};
|
||||
|
||||
var setStorageType = function(type) {
|
||||
if (type && storageType !== type) {
|
||||
storageType = type;
|
||||
browserSupportsLocalStorage = checkSupport();
|
||||
}
|
||||
return browserSupportsLocalStorage;
|
||||
};
|
||||
|
||||
// Add a listener on scope variable to save its changes to local storage
|
||||
// Return a function which when called cancels binding
|
||||
var bindToScope = function(scope, key, def, lsKey, type) {
|
||||
lsKey = lsKey || key;
|
||||
var value = getFromLocalStorage(lsKey, type);
|
||||
|
||||
if (value === null && isDefined(def)) {
|
||||
value = def;
|
||||
} else if (isObject(value) && isObject(def)) {
|
||||
value = extend(value, def);
|
||||
}
|
||||
|
||||
$parse(key).assign(scope, value);
|
||||
|
||||
return scope.$watch(key, function(newVal) {
|
||||
addToLocalStorage(lsKey, newVal, type);
|
||||
}, isObject(scope[key]));
|
||||
};
|
||||
|
||||
// Add listener to local storage, for update callbacks.
|
||||
if (browserSupportsLocalStorage) {
|
||||
if ($window.addEventListener) {
|
||||
$window.addEventListener("storage", handleStorageChangeCallback, false);
|
||||
$rootScope.$on('$destroy', function() {
|
||||
$window.removeEventListener("storage", handleStorageChangeCallback);
|
||||
});
|
||||
} else if($window.attachEvent){
|
||||
// attachEvent and detachEvent are proprietary to IE v6-10
|
||||
$window.attachEvent("onstorage", handleStorageChangeCallback);
|
||||
$rootScope.$on('$destroy', function() {
|
||||
$window.detachEvent("onstorage", handleStorageChangeCallback);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Callback handler for storage changed.
|
||||
function handleStorageChangeCallback(e) {
|
||||
if (!e) { e = $window.event; }
|
||||
if (notify.setItem) {
|
||||
if (isKeyPrefixOurs(e.key)) {
|
||||
var key = underiveQualifiedKey(e.key);
|
||||
// Use timeout, to avoid using $rootScope.$apply.
|
||||
$timeout(function () {
|
||||
$rootScope.$broadcast('LocalStorageModule.notification.changed', { key: key, newvalue: e.newValue, storageType: self.storageType });
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Return localStorageService.length
|
||||
// ignore keys that not owned
|
||||
var lengthOfLocalStorage = function(type) {
|
||||
setStorageType(type);
|
||||
|
||||
var count = 0;
|
||||
var storage = $window[storageType];
|
||||
for(var i = 0; i < storage.length; i++) {
|
||||
if(storage.key(i).indexOf(prefix) === 0 ) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
};
|
||||
|
||||
return {
|
||||
isSupported: browserSupportsLocalStorage,
|
||||
getStorageType: getStorageType,
|
||||
setStorageType: setStorageType,
|
||||
set: addToLocalStorage,
|
||||
add: addToLocalStorage, //DEPRECATED
|
||||
get: getFromLocalStorage,
|
||||
keys: getKeysForLocalStorage,
|
||||
remove: removeFromLocalStorage,
|
||||
clearAll: clearAllFromLocalStorage,
|
||||
bind: bindToScope,
|
||||
deriveKey: deriveQualifiedKey,
|
||||
underiveKey: underiveQualifiedKey,
|
||||
length: lengthOfLocalStorage,
|
||||
defaultToCookie: this.defaultToCookie,
|
||||
cookie: {
|
||||
isSupported: browserSupportsCookies,
|
||||
set: addToCookies,
|
||||
add: addToCookies, //DEPRECATED
|
||||
get: getFromCookies,
|
||||
remove: removeFromCookies,
|
||||
clearAll: clearAllFromCookies
|
||||
}
|
||||
};
|
||||
}];
|
||||
});
|
||||
})(window, window.angular);
|
||||
@@ -1,4 +1,5 @@
|
||||
window.OFNShared = angular.module("OFNShared", [
|
||||
"mm.foundation",
|
||||
"LocalStorageModule"
|
||||
]).config ($httpProvider) ->
|
||||
$httpProvider.defaults.headers.common["Accept"] = "application/json, text/javascript, */*"
|
||||
|
||||
@@ -2,13 +2,13 @@
|
||||
.ofn-drop-down-label
|
||||
= " #{t('admin.columns')}".html_safe
|
||||
%span{ 'ng-class' => "expanded && 'icon-caret-up' || !expanded && 'icon-caret-down'" }
|
||||
.menu{ 'ng-show' => "expanded" }
|
||||
%div.menu{ 'ng-show' => "expanded" }
|
||||
.menu_items
|
||||
.menu_item{ "ng-repeat": "column in columns", "ng-click": "toggle(column);" }
|
||||
%input{ type: "checkbox", "ng-checked": "column.visible" }
|
||||
%span
|
||||
{{ column.name }}
|
||||
%hr
|
||||
.menu_item.text-center
|
||||
%div.menu_item.text-center
|
||||
%input.fullwidth.orange{ type: "button", "ng-value": "saved() ? 'Saved': 'Saving'", "ng-show": "saved() || saving", "ng-disabled": "saved()" }
|
||||
%input.fullwidth.red{ type: "button", value: t('admin.column_save_as_default').html_safe, "ng-show": "!saved() && !saving", "ng-click": "saveColumnPreferences(action)" }
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
%i.fa.fa-times-circle{'aria-hidden' => "true"}
|
||||
|
||||
%form#image_upload{ name: 'form', novalidate: true, enctype: 'multipart/form-data', multipart: true, "ng-controller": "ProductImageCtrl" }
|
||||
.image-preview
|
||||
%div.image-preview
|
||||
%img.spinner{ src: image_path("/spinning-circles.svg"), "ng-hide": "!imageUploader.isUploading" }
|
||||
%img.preview{ "ng-src": "{{imagePreview}}", "ng-class": "{'faded': imageUploader.isUploading}" }
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
.exchange-product{'ng-repeat' => 'product in enterprises[exchange.enterprise_id].supplied_products | filter:visibleProducts:exchange:order_cycle.visible_variants_for_outgoing_exchanges' }
|
||||
.exchange-product-details
|
||||
%label
|
||||
%img{'ng-src' => '{{ product.image_url }}'}
|
||||
%img{'ng-src' => '{{ product.image_url }}'}
|
||||
.name {{ product.name }}
|
||||
.supplier {{ product.supplier_name }}
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// please update the modal html in app/components/out_of_stock_modal_component/out_of_stock_modal_component.html.haml if updating this template
|
||||
%a.close-reveal-modal{"ng-click" => "$close()"}
|
||||
%i.ofn-i_009-close
|
||||
|
||||
@@ -13,4 +12,4 @@
|
||||
%span{'ng-if' => "v.on_hand == 0"}
|
||||
{{ 'js.out_of_stock.now_out_of_stock' | t }}
|
||||
%span{'ng-if' => "v.on_hand > 0"}
|
||||
{{ 'js.out_of_stock.only_n_remaining' | t:{ num: v.on_hand } }}
|
||||
{{ 'js.out_of_stock.only_n_remainging' | t:{ num: v.on_hand } }}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
.contact-container
|
||||
.modal-centered{"ng-if" => "::enterprise.email_address || enterprise.website || enterprise.phone || enterprise.whatsapp_phone"}
|
||||
%div.contact-container
|
||||
%div.modal-centered{"ng-if" => "::enterprise.email_address || enterprise.website || enterprise.phone || enterprise.whatsapp_phone"}
|
||||
%p.modal-header {{'contact' | t}}
|
||||
%p{"ng-if" => "::enterprise.phone", "ng-bind" => "::enterprise.phone"}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
.modal-centered{ "ng-if" => "::enterprise.twitter || enterprise.facebook || enterprise.linkedin || enterprise.instagram"}
|
||||
%div.modal-centered{ "ng-if" => "::enterprise.twitter || enterprise.facebook || enterprise.linkedin || enterprise.instagram"}
|
||||
%p.modal-header {{'follow' | t}}
|
||||
.follow-icons
|
||||
%span{"ng-if" => "::enterprise.twitter"}
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
.columns.small-12.fat
|
||||
%div{"ng-if" => "::enterprise.name"}
|
||||
%label{"ng-bind-html" => "::'shop_for_products_html' | t:{enterprise: enterprise.name}"}
|
||||
.show-for-medium-up{"ng-if" => "::!enterprise.name"}
|
||||
%div.show-for-medium-up{"ng-if" => "::!enterprise.name"}
|
||||
|
||||
.row
|
||||
.columns.small-12
|
||||
|
||||
@@ -12,6 +12,11 @@ img {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.collapse {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
body {
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-webkit-text-size-adjust: none;
|
||||
@@ -27,6 +32,18 @@ a {
|
||||
color: #0096ad;
|
||||
}
|
||||
|
||||
.btn {
|
||||
text-decoration: none;
|
||||
color: #FFF;
|
||||
background-color: #666;
|
||||
padding: 10px 16px;
|
||||
font-weight: bold;
|
||||
margin-right: 10px;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
p.callout {
|
||||
padding: 15px;
|
||||
background-color: #e1f0f5;
|
||||
@@ -104,12 +121,6 @@ table.order-summary {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.logo {
|
||||
vertical-align: middle;
|
||||
max-height: 50px;
|
||||
max-width: 247px;
|
||||
}
|
||||
|
||||
.social .soc-btn {
|
||||
padding: 3px 7px;
|
||||
font-size: 12px;
|
||||
@@ -167,11 +178,17 @@ del.quantity_was {
|
||||
|
||||
table.head-wrap {
|
||||
width: 100%;
|
||||
background-color: #f2f2f2;
|
||||
}
|
||||
|
||||
.collapse {
|
||||
margin: 0;
|
||||
.header.container table td {
|
||||
&.logo {
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
&.label {
|
||||
padding: 15px;
|
||||
padding-left: 0px;
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------
|
||||
@@ -250,6 +267,10 @@ h6 {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.collapse {
|
||||
margin: 0 !important;
|
||||
}
|
||||
|
||||
p, ul {
|
||||
margin-bottom: 10px;
|
||||
font-weight: normal;
|
||||
@@ -361,6 +382,12 @@ ul {
|
||||
}
|
||||
}
|
||||
|
||||
.column-wrap {
|
||||
padding: 0 !important;
|
||||
margin: 0 auto;
|
||||
max-width: 600px !important;
|
||||
}
|
||||
|
||||
.column table {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
@@ -1,3 +1 @@
|
||||
- # the stimulus contoller "example-component--example" lives in app/component/example_component/example_controller.js
|
||||
%div{ "data-controller": "example-component--example"}
|
||||
%h1 #{@title}
|
||||
%h1 #{@title}
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
// This controller will be called "example-component--example", ie "component-subdirectory--js-file-name"
|
||||
import { Controller } from "stimulus";
|
||||
|
||||
export default class extends Controller {}
|
||||
@@ -1,12 +1,12 @@
|
||||
.ofn-drop-down.ofn-drop-down-v2{ data: { controller: "multiple-checked-select" } }
|
||||
.ofn-drop-down-label{ "data-multiple-checked-select-target": "button" }
|
||||
%div.ofn-drop-down-label{ "data-multiple-checked-select-target": "button" }
|
||||
%span{class: "label"}= t('admin.columns')
|
||||
%span{ class: "icon-caret-down", "data-multiple-checked-select-target": "caret" }
|
||||
.menu{ class: "hidden", "data-multiple-checked-select-target": "options" }
|
||||
.filter
|
||||
%div.menu{ class: "hidden", "data-multiple-checked-select-target": "options" }
|
||||
%div.filter
|
||||
%input{ type: "text", "data-multiple-checked-select-target": "filter", placeholder: I18n.t('components.multiple_checked_select.filter_placeholder') }
|
||||
%hr
|
||||
.menu_items
|
||||
%div.menu_items
|
||||
- @options.each do |option|
|
||||
%label.menu_item{ "data-multiple-checked-select-target": "option", "data-value": option[1], "data-label": option[0] }
|
||||
%input{ type: "checkbox", checked: @selected.include?(option[1]), name: "#{@name}[]", value: option[1] }
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class OutOfStockModalComponent < ModalComponent
|
||||
def initialize(id:, variants: [], redirect: false)
|
||||
super(id:, modal_class: "medium", instant: true)
|
||||
|
||||
@variants = variants
|
||||
@redirect = redirect
|
||||
end
|
||||
end
|
||||
@@ -1,26 +0,0 @@
|
||||
%div{ id: @id, "data-controller": "modal out-of-stock-modal", "data-action": "keyup@document->modal#closeIfEscapeKey modal:closing->out-of-stock-modal#redirect", "data-modal-instant-value": @instant, "data-out-of-stock-modal-redirect-value": @redirect }
|
||||
.reveal-modal-bg.fade{ "data-modal-target": "background", "data-action": "click->modal#close" }
|
||||
.reveal-modal.fade.modal-component{ "data-modal-target": "modal", class: @modal_class }
|
||||
- # please update app/assets/javascripts/templates/out_of_stock.html.haml if updating this view
|
||||
%a.close-reveal-modal{"data-action": "click->modal#close" }
|
||||
%i.ofn-i_009-close
|
||||
%h3
|
||||
= t("js.out_of_stock.reduced_stock_available")
|
||||
%p
|
||||
= t("js.out_of_stock.out_of_stock_text")
|
||||
- @variants.each do |variant|
|
||||
- if variant.on_hand == 0
|
||||
%p
|
||||
%em
|
||||
= "#{variant.name_to_display} - #{variant.unit_to_display}"
|
||||
%span
|
||||
= t("js.out_of_stock.now_out_of_stock")
|
||||
- if variant.on_hand > 0
|
||||
%p
|
||||
%em
|
||||
= "#{variant.name_to_display} - #{variant.unit_to_display}"
|
||||
%span
|
||||
= t("js.out_of_stock.only_n_remaining", num: variant.on_hand)
|
||||
|
||||
.text-center
|
||||
%input{ class: "button icon-plus #{close_button_class}", type: 'button', value: t('js.admin.modals.close'), "data-action": "click->modal#close" }
|
||||
@@ -1,16 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class TagListInputComponent < ViewComponent::Base
|
||||
# method in a "hidden_field" form helper and is the method used to get a list of tag on the model
|
||||
def initialize(form:, method:, tags:,
|
||||
placeholder: I18n.t("components.tag_list_input.default_placeholder"),
|
||||
aria_label: nil)
|
||||
@f = form
|
||||
@method = method
|
||||
@tags = tags
|
||||
@placeholder = placeholder
|
||||
@aria_label_option = aria_label ? { 'aria-label': aria_label } : {}
|
||||
end
|
||||
|
||||
attr_reader :f, :method, :tags, :placeholder, :aria_label_option
|
||||
end
|
||||
@@ -1,19 +0,0 @@
|
||||
%div{ "data-controller": "tag-list-input-component--tag-list-input" }
|
||||
.tags-input
|
||||
.tags
|
||||
- # We use display:none instead of hidden field, so changes to the value can be picked up by the bulkFormController
|
||||
= f.text_field method.to_sym, value: tags.join(","), "data-tag-list-input-component--tag-list-input-target": "tagList", "style": "display: none"
|
||||
%ul.tag-list{"data-tag-list-input-component--tag-list-input-target": "list"}
|
||||
%template{"data-tag-list-input-component--tag-list-input-target": "template"}
|
||||
%li.tag-item
|
||||
.tag-template
|
||||
%span
|
||||
%a.remove-button{ "data-action": "click->tag-list-input-component--tag-list-input#removeTag" }
|
||||
×
|
||||
- tags.each do |tag|
|
||||
%li.tag-item
|
||||
.tag-template
|
||||
%span=tag
|
||||
%a.remove-button{ "data-action": "click->tag-list-input-component--tag-list-input#removeTag" }
|
||||
×
|
||||
= text_field_tag "variant_add_tag_#{f.object.id}".to_sym, nil, class: "input", placeholder: placeholder, "data-action": "keydown.enter->tag-list-input-component--tag-list-input#addTag keyup->tag-list-input-component--tag-list-input#filterInput", "data-tag-list-input-component--tag-list-input-target": "newTag", **aria_label_option
|
||||
@@ -1,70 +0,0 @@
|
||||
// Tags input
|
||||
.tags-input {
|
||||
display: block;
|
||||
|
||||
.tags {
|
||||
-moz-appearance: textfield;
|
||||
-webkit-appearance: textfield;
|
||||
overflow: hidden;
|
||||
word-wrap: break-word;
|
||||
cursor: text;
|
||||
background-color: #fff;
|
||||
height: 100%;
|
||||
box-shadow: none;
|
||||
|
||||
&:has(.changed) {
|
||||
border: 1px solid $color-txt-changed-brd;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.tag-error {
|
||||
color: $color-error;
|
||||
}
|
||||
|
||||
.tag-list {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style-type: none;
|
||||
}
|
||||
|
||||
li.tag-item {
|
||||
border-radius: 3px;
|
||||
margin: 2px 0 2px 3px;
|
||||
padding: 0 0 0 5px;
|
||||
display: inline-block;
|
||||
float: left;
|
||||
font-size: 14px;
|
||||
line-height: 25px;
|
||||
border: none;
|
||||
box-shadow: none;
|
||||
color: white !important;
|
||||
background-image: none;
|
||||
background-color: $teal;
|
||||
|
||||
.remove-button {
|
||||
border-left: 1px solid darken($teal, 5);
|
||||
margin-left: 2px;
|
||||
padding: 0 6px;
|
||||
background: 0 0;
|
||||
cursor: pointer;
|
||||
vertical-align: middle;
|
||||
font-size: 14px;
|
||||
color: white;
|
||||
|
||||
&:hover {
|
||||
background: rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.input {
|
||||
border: 0;
|
||||
outline: 0;
|
||||
margin: 2px;
|
||||
padding: 0 0 0 5px;
|
||||
float: left;
|
||||
height: 26px;
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
import { Controller } from "stimulus";
|
||||
|
||||
export default class extends Controller {
|
||||
static targets = ["tagList", "newTag", "template", "list"];
|
||||
|
||||
addTag(event) {
|
||||
// prevent hotkey form submitting the form (default action for "enter" key)
|
||||
event.preventDefault();
|
||||
|
||||
// Check if tag already exist
|
||||
const newTagName = this.newTagTarget.value.trim();
|
||||
if (newTagName.length == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const tags = this.tagListTarget.value.split(",");
|
||||
const index = tags.indexOf(newTagName);
|
||||
if (index != -1) {
|
||||
// highlight the value in red
|
||||
this.newTagTarget.classList.add("tag-error");
|
||||
return;
|
||||
}
|
||||
|
||||
// add to tagList
|
||||
this.tagListTarget.value = this.tagListTarget.value.concat(`,${newTagName}`);
|
||||
|
||||
// Create new li component with value
|
||||
const newTagElement = this.templateTarget.content.cloneNode(true);
|
||||
const spanElement = newTagElement.querySelector("span");
|
||||
spanElement.innerText = newTagName;
|
||||
this.listTarget.appendChild(newTagElement);
|
||||
|
||||
// Clear new tag value
|
||||
this.newTagTarget.value = "";
|
||||
}
|
||||
|
||||
removeTag(event) {
|
||||
// Text to remove
|
||||
const tagName = event.srcElement.previousElementSibling.textContent;
|
||||
|
||||
// Remove tag from list
|
||||
const tags = this.tagListTarget.value.split(",");
|
||||
this.tagListTarget.value = tags.filter(tag => tag != tagName).join(",");
|
||||
|
||||
// manualy dispatch an Input event so the change gets picked up by the bulk form controller
|
||||
this.tagListTarget.dispatchEvent(new InputEvent("input"));
|
||||
|
||||
// Remove HTML element from the list
|
||||
event.srcElement.parentElement.parentElement.remove();
|
||||
}
|
||||
|
||||
filterInput(event) {
|
||||
// clear error class if key is not enter
|
||||
if (event.key !== "Enter") {
|
||||
this.newTagTarget.classList.remove("tag-error");
|
||||
}
|
||||
|
||||
// Strip comma from tag name
|
||||
if (event.key === ",") {
|
||||
event.srcElement.value = event.srcElement.value.replace(",", "");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12,7 +12,7 @@ module Admin
|
||||
@line_items = order_permissions.
|
||||
editable_line_items.where(order_id: orders).
|
||||
includes(:variant).
|
||||
ransack(line_items_search_query).result.order(:id)
|
||||
ransack(params[:q]).result.order(:id)
|
||||
|
||||
@pagy, @line_items = pagy(@line_items) if pagination_required?
|
||||
|
||||
@@ -88,27 +88,5 @@ module Admin
|
||||
def page
|
||||
params[:page] || 1
|
||||
end
|
||||
|
||||
def line_items_search_query
|
||||
query = params.permit(q: {}).to_h[:q] || {}
|
||||
|
||||
search_fields_string = [
|
||||
spree_current_user.admin? ? "order_distributor_name" : "order_distributor_name_alias",
|
||||
"order_bill_address_phone",
|
||||
"order_bill_address_firstname",
|
||||
"order_bill_address_lastname",
|
||||
"order_bill_address_full_name",
|
||||
"order_bill_address_full_name_reversed",
|
||||
"order_bill_address_full_name_with_comma",
|
||||
"order_bill_address_full_name_with_comma_reversed",
|
||||
"variant_supplier_name",
|
||||
"order_email",
|
||||
"order_number",
|
||||
"product_name"
|
||||
].join("_or_")
|
||||
search_query = "#{search_fields_string}_cont"
|
||||
|
||||
query.merge({ search_query => params[:search_query] })
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -40,8 +40,8 @@ module Admin
|
||||
|
||||
respond_to do |format|
|
||||
format.json do
|
||||
collection_attributes = permitted_params[:column_preferences].
|
||||
each_with_index.to_h { |cp, i| [i, cp] }
|
||||
collection_attributes = Hash[permitted_params[:column_preferences].
|
||||
each_with_index.map { |cp, i| [i, cp] }]
|
||||
collection_attributes.select!{ |_i, cp|
|
||||
cp[:action_name] == permitted_params[:action_name]
|
||||
}
|
||||
|
||||
@@ -44,9 +44,9 @@ module Admin
|
||||
|
||||
create_connected_app
|
||||
|
||||
jwt_service = Vine::JwtService.new(secret: connected_app_params[:vine_secret])
|
||||
vine_api = Vine::ApiService.new(api_key: connected_app_params[:vine_api_key],
|
||||
jwt_generator: jwt_service)
|
||||
jwt_service = VineJwtService.new(secret: connected_app_params[:vine_secret])
|
||||
vine_api = VineApiService.new(api_key: connected_app_params[:vine_api_key],
|
||||
jwt_generator: jwt_service)
|
||||
|
||||
if !@app.connect(api_key: connected_app_params[:vine_api_key],
|
||||
secret: connected_app_params[:vine_secret], vine_api:)
|
||||
@@ -77,7 +77,7 @@ module Admin
|
||||
|
||||
def log_and_notify_exception(exception)
|
||||
Rails.logger.error exception.inspect
|
||||
Alert.raise(exception)
|
||||
Bugsnag.notify(exception)
|
||||
end
|
||||
|
||||
def vine_params_empty?
|
||||
|
||||
@@ -5,89 +5,50 @@ require "private_address_check/tcpsocket_ext"
|
||||
|
||||
module Admin
|
||||
class DfcProductImportsController < Spree::Admin::BaseController
|
||||
before_action :load_enterprise
|
||||
|
||||
# Define model class for `can?` permissions:
|
||||
def model_class
|
||||
self.class
|
||||
end
|
||||
|
||||
def index
|
||||
# Fetch DFC catalog JSON for preview
|
||||
@catalog_url = params.require(:catalog_url).strip
|
||||
@catalog_json = api.call(@catalog_url)
|
||||
catalog = DfcCatalog.from_json(@catalog_json)
|
||||
# The plan:
|
||||
#
|
||||
# * Fetch DFC catalog as JSON from URL.
|
||||
enterprise = OpenFoodNetwork::Permissions.new(spree_current_user)
|
||||
.managed_product_enterprises.is_primary_producer
|
||||
.find(params.require(:enterprise_id))
|
||||
|
||||
# Render table and let user decide which ones to import.
|
||||
@items = list_products(catalog)
|
||||
@absent_items = importer(catalog).absent_variants
|
||||
rescue URI::InvalidURIError
|
||||
flash[:error] = t ".invalid_url"
|
||||
redirect_to admin_product_import_path
|
||||
rescue Faraday::Error,
|
||||
Addressable::URI::InvalidURIError,
|
||||
ActionController::ParameterMissing => e
|
||||
flash[:error] = e.message
|
||||
redirect_to admin_product_import_path
|
||||
rescue Rack::OAuth2::Client::Error
|
||||
oidc_settings_link = helpers.link_to(
|
||||
t('spree.admin.tab.oidc_settings'),
|
||||
admin_oidc_settings_path
|
||||
)
|
||||
flash[:error] = t(".connection_invalid_html", oidc_settings_link:)
|
||||
redirect_to admin_product_import_path
|
||||
end
|
||||
catalog_url = params.require(:catalog_url)
|
||||
|
||||
def import
|
||||
ids = params.require(:semanticIds)
|
||||
json_catalog = fetch_catalog(catalog_url)
|
||||
graph = DfcIo.import(json_catalog)
|
||||
|
||||
# Load DFC catalog JSON
|
||||
catalog = DfcCatalog.from_json(params.require(:catalog_json))
|
||||
catalog.apply_wholesale_values!
|
||||
# * First step: import all products for given enterprise.
|
||||
# * Second step: render table and let user decide which ones to import.
|
||||
imported = graph.map do |subject|
|
||||
next unless subject.is_a? DataFoodConsortium::Connector::SuppliedProduct
|
||||
|
||||
# Import all selected products for given enterprise.
|
||||
imported = ids.map do |semantic_id|
|
||||
subject = catalog.item(semantic_id)
|
||||
existing_variant = @enterprise.supplied_variants.linked_to(semantic_id)
|
||||
existing_variant = enterprise.supplied_variants.linked_to(subject.semanticId)
|
||||
|
||||
if existing_variant
|
||||
SuppliedProductImporter.update_product(subject, existing_variant)
|
||||
SuppliedProductBuilder.update_product(subject, existing_variant)
|
||||
else
|
||||
SuppliedProductImporter.store_product(subject, @enterprise)
|
||||
SuppliedProductBuilder.store_product(subject, enterprise)
|
||||
end
|
||||
end
|
||||
|
||||
@count = imported.compact.count
|
||||
@reset_count = importer(catalog).reset_absent_variants.count
|
||||
rescue ActionController::ParameterMissing => e
|
||||
rescue Faraday::Error,
|
||||
Addressable::URI::InvalidURIError,
|
||||
ActionController::ParameterMissing => e
|
||||
flash[:error] = e.message
|
||||
redirect_to admin_product_import_path
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def api
|
||||
@api ||= DfcRequest.new(spree_current_user)
|
||||
end
|
||||
|
||||
def load_enterprise
|
||||
@enterprise = OpenFoodNetwork::Permissions.new(spree_current_user)
|
||||
.managed_product_enterprises.is_primary_producer
|
||||
.find(params.require(:enterprise_id))
|
||||
end
|
||||
|
||||
# List internal and external products for the preview.
|
||||
def list_products(catalog)
|
||||
catalog.products.map do |subject|
|
||||
[
|
||||
subject,
|
||||
@enterprise.supplied_variants.linked_to(subject.semanticId)&.product
|
||||
]
|
||||
end
|
||||
end
|
||||
|
||||
def importer(catalog)
|
||||
DfcCatalogImporter.new(@enterprise.supplied_variants, catalog)
|
||||
def fetch_catalog(url)
|
||||
DfcRequest.new(spree_current_user).call(url)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -14,8 +14,7 @@ module Admin
|
||||
prepend_before_action :override_owner, only: :create
|
||||
prepend_before_action :override_sells, only: :create
|
||||
|
||||
before_action :load_countries, except: [:index, :register]
|
||||
before_action :require_enterprise, only: [:edit, :update]
|
||||
before_action :load_countries, except: [:index, :register, :check_permalink]
|
||||
before_action :load_methods_and_fees, only: [:edit, :update]
|
||||
before_action :load_groups, only: [:new, :edit, :update, :create]
|
||||
before_action :load_taxons, only: [:new, :edit, :update, :create]
|
||||
@@ -48,9 +47,6 @@ module Admin
|
||||
@object = Enterprise.where(permalink: params[:id]).
|
||||
includes(users: [:ship_address, :bill_address]).first
|
||||
@object.build_custom_tab if @object.custom_tab.nil?
|
||||
|
||||
load_tag_rule_types
|
||||
|
||||
return unless params[:stimulus]
|
||||
|
||||
@enterprise.is_primary_producer = params[:is_primary_producer]
|
||||
@@ -72,15 +68,13 @@ module Admin
|
||||
delete_custom_tab if params[:custom_tab] == 'false'
|
||||
|
||||
if @object.update(enterprise_params)
|
||||
flash[:success] = flash_success_message
|
||||
|
||||
flash[:success] = flash_message_for(@object, :successfully_updated)
|
||||
respond_with(@object) do |format|
|
||||
format.html { redirect_to location_after_save }
|
||||
format.js { render layout: false }
|
||||
format.json {
|
||||
render_as_json @object, ams_prefix: 'index', spree_current_user:
|
||||
}
|
||||
format.turbo_stream
|
||||
end
|
||||
else
|
||||
respond_with(@object) do |format|
|
||||
@@ -169,25 +163,6 @@ module Admin
|
||||
|
||||
private
|
||||
|
||||
def flash_success_message
|
||||
if attachment_removal?
|
||||
I18n.t("admin.controllers.enterprises.#{attachment_removal_parameter}_success")
|
||||
else
|
||||
flash_message_for(@object, :successfully_updated)
|
||||
end
|
||||
end
|
||||
|
||||
def attachment_removal?
|
||||
attachment_removal_parameter.present?
|
||||
end
|
||||
|
||||
def attachment_removal_parameter
|
||||
if enterprise_params.keys.one? && enterprise_params.keys.first.to_s.start_with?("remove_")
|
||||
enterprise_params.keys.first
|
||||
end
|
||||
end
|
||||
helper_method :attachment_removal_parameter
|
||||
|
||||
def load_enterprise_set_on_index
|
||||
return unless spree_current_user.admin?
|
||||
|
||||
@@ -241,10 +216,6 @@ module Admin
|
||||
[:index, :for_order_cycle, :visible, :bulk_update]
|
||||
end
|
||||
|
||||
def require_enterprise
|
||||
raise ActiveRecord::RecordNotFound if @enterprise.blank?
|
||||
end
|
||||
|
||||
def load_methods_and_fees
|
||||
enterprise_payment_methods = @enterprise.payment_methods.to_a
|
||||
enterprise_shipping_methods = @enterprise.shipping_methods.to_a
|
||||
@@ -278,7 +249,7 @@ module Admin
|
||||
# methods that are specific to each class do not become available until after the
|
||||
# record is persisted. This problem is compounded by the use of calculators.
|
||||
@object.transaction do
|
||||
tag_rules_attributes.select{ |_i, attrs| attrs[:type].present? }.each_value do |attrs|
|
||||
tag_rules_attributes.select{ |_i, attrs| attrs[:type].present? }.each do |_i, attrs|
|
||||
rule = @object.tag_rules.find_by(id: attrs.delete(:id)) ||
|
||||
attrs[:type].constantize.new(enterprise: @object)
|
||||
|
||||
@@ -317,7 +288,7 @@ module Admin
|
||||
def check_can_change_bulk_sells
|
||||
return if spree_current_user.admin?
|
||||
|
||||
params[:sets_enterprise_set][:collection_attributes].each_value do |enterprise_params|
|
||||
params[:sets_enterprise_set][:collection_attributes].each do |_i, enterprise_params|
|
||||
unless spree_current_user == Enterprise.find_by(id: enterprise_params[:id]).owner
|
||||
enterprise_params.delete :sells
|
||||
end
|
||||
@@ -351,7 +322,7 @@ module Admin
|
||||
def check_can_change_bulk_owner
|
||||
return if spree_current_user.admin?
|
||||
|
||||
bulk_params[:collection_attributes].each_value do |enterprise_params|
|
||||
bulk_params[:collection_attributes].each do |_i, enterprise_params|
|
||||
enterprise_params.delete :owner_id
|
||||
end
|
||||
end
|
||||
@@ -378,19 +349,6 @@ module Admin
|
||||
@properties = Spree::Property.pluck(:name)
|
||||
end
|
||||
|
||||
def load_tag_rule_types
|
||||
# Load rule types
|
||||
@tag_rule_types = [
|
||||
{ id: "FilterShippingMethods", name: t('js.tag_rules.show_hide_shipping') },
|
||||
{ id: "FilterPaymentMethods", name: t('js.tag_rules.show_hide_payment') },
|
||||
{ id: "FilterOrderCycles", name: t('js.tag_rules.show_hide_order_cycles') }
|
||||
]
|
||||
|
||||
return unless helpers.feature?(:inventory, @object)
|
||||
|
||||
@tag_rule_types.prepend({ id: "FilterProducts", name: t('js.tag_rules.show_hide_variants') })
|
||||
end
|
||||
|
||||
def setup_property
|
||||
@enterprise.producer_properties.build
|
||||
end
|
||||
|
||||
@@ -17,10 +17,7 @@ module Admin
|
||||
end
|
||||
|
||||
def import
|
||||
return unless can_import_into_inventories?
|
||||
|
||||
@filepath = save_uploaded_file(params[:file])
|
||||
|
||||
@importer = ProductImport::ProductImporter.new(File.new(@filepath), spree_current_user,
|
||||
params[:settings])
|
||||
@original_filename = params[:file].try(:original_filename)
|
||||
@@ -33,28 +30,13 @@ module Admin
|
||||
def validate_data
|
||||
return unless process_data('validate')
|
||||
|
||||
render json: @importer.import_results
|
||||
render json: @importer.import_results, response: 200
|
||||
end
|
||||
|
||||
def save_data
|
||||
return unless process_data('save')
|
||||
|
||||
json = {
|
||||
results: {
|
||||
products_created: @importer.products_created_count,
|
||||
products_updated: @importer.products_updated_count,
|
||||
products_reset: @importer.products_reset_count,
|
||||
},
|
||||
updated_ids: @importer.updated_ids,
|
||||
errors: @importer.errors.full_messages
|
||||
}
|
||||
|
||||
if helpers.feature?(:inventory, spree_current_user.enterprises)
|
||||
json[:results][:inventory_created] = @importer.inventory_created_count
|
||||
json[:results][:inventory_updated] = @importer.inventory_updated_count
|
||||
end
|
||||
|
||||
render json:
|
||||
render json: @importer.save_results, response: 200
|
||||
end
|
||||
|
||||
def reset_absent_products
|
||||
@@ -94,7 +76,7 @@ module Admin
|
||||
begin
|
||||
@importer.public_send("#{method}_entries")
|
||||
rescue StandardError => e
|
||||
render plain: e.message, status: :internal_server_error
|
||||
render json: e.message, response: 500
|
||||
return false
|
||||
end
|
||||
|
||||
@@ -172,15 +154,5 @@ module Admin
|
||||
notice: I18n.t(:product_import_no_data_in_spreadsheet_notice)
|
||||
raise 'Invalid File Path'
|
||||
end
|
||||
|
||||
# Return an error if trying to import into inventories when inventory is disable
|
||||
def can_import_into_inventories?
|
||||
return true if helpers.feature?(:inventory, spree_current_user.enterprises) ||
|
||||
params.dig(:settings, "import_into") != 'inventories'
|
||||
|
||||
redirect_to admin_product_import_url, notice: I18n.t(:product_import_inventory_disable)
|
||||
|
||||
false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -10,8 +10,7 @@ module Admin
|
||||
|
||||
def index
|
||||
fetch_products
|
||||
render "index",
|
||||
locals: { producers:, categories:, tax_category_options:, available_tags:, flash: }
|
||||
render "index", locals: { producers:, categories:, tax_category_options:, flash: }
|
||||
|
||||
session[:products_return_to_url] = request.url
|
||||
end
|
||||
@@ -31,9 +30,7 @@ module Admin
|
||||
@error_counts = { saved: product_set.saved_count, invalid: product_set.invalid.count }
|
||||
|
||||
render "index", status: :unprocessable_entity,
|
||||
locals: {
|
||||
producers:, categories:, tax_category_options:, available_tags:, flash:
|
||||
}
|
||||
locals: { producers:, categories:, tax_category_options:, flash: }
|
||||
end
|
||||
end
|
||||
|
||||
@@ -115,7 +112,6 @@ module Admin
|
||||
@search_term = params[:search_term] || params[:_search_term]
|
||||
@producer_id = params[:producer_id] || params[:_producer_id]
|
||||
@category_id = params[:category_id] || params[:_category_id]
|
||||
@tags = params[:tags_name_in] || params[:_tags_name_in]
|
||||
end
|
||||
|
||||
def init_pagination_params
|
||||
@@ -139,39 +135,22 @@ module Admin
|
||||
Spree::TaxCategory.order(:name).pluck(:name, :id)
|
||||
end
|
||||
|
||||
def available_tags
|
||||
variants = Spree::Variant.where(
|
||||
product: OpenFoodNetwork::Permissions.new(spree_current_user)
|
||||
.editable_products
|
||||
.merge(product_scope)
|
||||
)
|
||||
|
||||
ActsAsTaggableOn::Tag.joins(:taggings).where(
|
||||
taggings: { taggable_type: "Spree::Variant", taggable_id: variants }
|
||||
).distinct.order(:name).pluck(:name)
|
||||
end
|
||||
|
||||
def fetch_products
|
||||
product_query = OpenFoodNetwork::Permissions.new(spree_current_user)
|
||||
.editable_products.merge(product_scope_with_includes).ransack(ransack_query).result
|
||||
|
||||
@pagy, @products = pagy(product_query.order(:name), limit: @per_page, page: @page,
|
||||
.editable_products.merge(product_scope).ransack(ransack_query).result
|
||||
@pagy, @products = pagy(product_query.order(:name), items: @per_page, page: @page,
|
||||
size: [1, 2, 2, 1])
|
||||
end
|
||||
|
||||
def product_scope
|
||||
user = spree_current_user
|
||||
scope = if user.admin? || user.enterprises.present?
|
||||
scope = if user.has_spree_role?("admin") || user.enterprises.present?
|
||||
Spree::Product
|
||||
else
|
||||
Spree::Product.active
|
||||
end
|
||||
|
||||
scope.distinct
|
||||
end
|
||||
|
||||
def product_scope_with_includes
|
||||
product_scope.includes(product_query_includes)
|
||||
scope.includes(product_query_includes).distinct
|
||||
end
|
||||
|
||||
def ransack_query
|
||||
@@ -181,7 +160,6 @@ module Admin
|
||||
query.merge!(Spree::Variant::SEARCH_KEY => @search_term)
|
||||
end
|
||||
query.merge!(variants_primary_taxon_id_in: @category_id) if @category_id.present?
|
||||
query.merge!(variants_tags_name_in: @tags) if @tags.present?
|
||||
query.merge!(@q) if @q
|
||||
|
||||
query
|
||||
@@ -198,7 +176,6 @@ module Admin
|
||||
:stock_items,
|
||||
:tax_category,
|
||||
:supplier,
|
||||
:taggings,
|
||||
] },
|
||||
]
|
||||
end
|
||||
|
||||
@@ -53,9 +53,7 @@ module Admin
|
||||
return unless @order_cycle
|
||||
|
||||
fee_calculator = OpenFoodNetwork::EnterpriseFeeCalculator.new(@shop, @order_cycle)
|
||||
|
||||
OpenFoodNetwork::ScopeVariantToHub.new(@shop).scope(@variant)
|
||||
|
||||
@variant.price + fee_calculator.indexed_fees_for(@variant)
|
||||
end
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ module Admin
|
||||
include OpenFoodNetwork::SpreeApiKeyLoader
|
||||
include EnterprisesHelper
|
||||
|
||||
prepend_before_action :load_data, if: :spree_current_user
|
||||
prepend_before_action :load_data
|
||||
before_action :load_collection, only: [:bulk_update]
|
||||
before_action :load_spree_api_key, only: :index
|
||||
|
||||
@@ -70,13 +70,7 @@ module Admin
|
||||
end
|
||||
|
||||
def load_collection
|
||||
collection_hash = variant_overrides_params.each_with_index.to_h { |vo, i| [i, vo] }
|
||||
|
||||
# Reset count_on_hand when switching to producer settings:
|
||||
collection_hash.each_value do |vo|
|
||||
vo["count_on_hand"] = nil if vo.fetch("on_demand", :unchanged).nil?
|
||||
end
|
||||
|
||||
collection_hash = Hash[variant_overrides_params.each_with_index.map { |vo, i| [i, vo] }]
|
||||
@vo_set = Sets::VariantOverrideSet.new(@variant_overrides,
|
||||
collection_attributes: collection_hash)
|
||||
end
|
||||
|
||||
@@ -66,7 +66,7 @@ module Api
|
||||
end
|
||||
|
||||
def error_during_processing(exception)
|
||||
Alert.raise(exception)
|
||||
Bugsnag.notify(exception)
|
||||
|
||||
render(json: { exception: exception.message },
|
||||
status: :unprocessable_entity) && return
|
||||
|
||||
@@ -77,7 +77,7 @@ module Api
|
||||
|
||||
if pagination_required?
|
||||
@pagy, results = pagy(results,
|
||||
limit: params[:per_page] || DEFAULT_PER_PAGE)
|
||||
items: params[:per_page] || DEFAULT_PER_PAGE)
|
||||
end
|
||||
|
||||
serialized_products = ActiveModel::ArraySerializer.new(
|
||||
|
||||
@@ -22,8 +22,7 @@ module Api
|
||||
distributor,
|
||||
order_cycle,
|
||||
customer,
|
||||
search_params,
|
||||
inventory_enabled:
|
||||
search_params
|
||||
).products_json
|
||||
|
||||
render plain: products
|
||||
@@ -96,13 +95,9 @@ module Api
|
||||
|
||||
def distributed_products
|
||||
OrderCycles::DistributedProductsService.new(
|
||||
distributor, order_cycle, customer, inventory_enabled:
|
||||
distributor, order_cycle, customer
|
||||
).products_relation.pluck(:id)
|
||||
end
|
||||
|
||||
def inventory_enabled
|
||||
OpenFoodNetwork::FeatureToggle.enabled?(:inventory, distributor)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -12,7 +12,7 @@ module Api
|
||||
|
||||
if pagination_required?
|
||||
@pagy, orders = pagy(orders,
|
||||
limit: params[:per_page] || default_per_page)
|
||||
items: params[:per_page] || default_per_page)
|
||||
end
|
||||
|
||||
render json: {
|
||||
@@ -67,8 +67,7 @@ module Api
|
||||
def serialized_orders(orders)
|
||||
ActiveModel::ArraySerializer.new(
|
||||
orders,
|
||||
each_serializer: Api::Admin::OrderSerializer,
|
||||
current_user: current_api_user
|
||||
each_serializer: Api::Admin::OrderSerializer
|
||||
)
|
||||
end
|
||||
|
||||
|
||||
@@ -78,7 +78,7 @@ module Api
|
||||
end
|
||||
|
||||
def render_paged_products(products, product_serializer = ::Api::Admin::ProductSerializer)
|
||||
@pagy, products = pagy(products, limit: params[:per_page] || DEFAULT_PER_PAGE)
|
||||
@pagy, products = pagy(products, items: params[:per_page] || DEFAULT_PER_PAGE)
|
||||
|
||||
serialized_products = ActiveModel::ArraySerializer.new(
|
||||
products,
|
||||
|
||||
@@ -14,7 +14,7 @@ module Api
|
||||
def create
|
||||
variant = scoped_variant(params[:variant_id])
|
||||
quantity = params[:quantity].to_i
|
||||
@shipment = @order.shipment || @order.shipments.create
|
||||
@shipment = get_or_create_shipment(params[:stock_location_id])
|
||||
|
||||
@order.contents.add(variant, quantity, @shipment)
|
||||
|
||||
@@ -24,7 +24,6 @@ module Api
|
||||
Orders::WorkflowService.new(@order).advance_to_payment if @order.line_items.any?
|
||||
|
||||
@order.recreate_all_fees!
|
||||
AmendBackorderJob.perform_later(@order) if @order.completed?
|
||||
|
||||
render json: @shipment, serializer: Api::ShipmentSerializer, status: :ok
|
||||
end
|
||||
@@ -74,7 +73,6 @@ module Api
|
||||
|
||||
@order.contents.add(variant, quantity, @shipment)
|
||||
@order.recreate_all_fees!
|
||||
AmendBackorderJob.perform_later(@order) if @order.completed?
|
||||
|
||||
render json: @shipment, serializer: Api::ShipmentSerializer, status: :ok
|
||||
end
|
||||
@@ -88,7 +86,6 @@ module Api
|
||||
@shipment.reload if @shipment.persisted?
|
||||
|
||||
@order.recreate_all_fees!
|
||||
AmendBackorderJob.perform_later(@order) if @order.completed?
|
||||
|
||||
render json: @shipment, serializer: Api::ShipmentSerializer, status: :ok
|
||||
end
|
||||
@@ -112,14 +109,16 @@ module Api
|
||||
|
||||
def scoped_variant(variant_id)
|
||||
variant = Spree::Variant.find(variant_id)
|
||||
|
||||
OpenFoodNetwork::ScopeVariantToHub.new(@order.distributor).scope(variant)
|
||||
|
||||
variant
|
||||
end
|
||||
|
||||
def get_or_create_shipment(stock_location_id)
|
||||
@order.shipment || @order.shipments.create(stock_location_id:)
|
||||
end
|
||||
|
||||
def shipment_params
|
||||
return {} unless params.key? :shipment
|
||||
return {} unless params.has_key? :shipment
|
||||
|
||||
params.require(:shipment).permit(:tracking, :selected_shipping_rate_id)
|
||||
end
|
||||
|
||||
@@ -55,14 +55,14 @@ module Api
|
||||
|
||||
def scope
|
||||
if @product
|
||||
variants = if current_api_user.admin? || params[:show_deleted]
|
||||
variants = if current_api_user.has_spree_role?("admin") || params[:show_deleted]
|
||||
@product.variants.with_deleted
|
||||
else
|
||||
@product.variants
|
||||
end
|
||||
else
|
||||
variants = Spree::Variant.where(nil)
|
||||
if current_api_user.admin?
|
||||
if current_api_user.has_spree_role?("admin")
|
||||
unless params[:show_deleted]
|
||||
variants = Spree::Variant.active
|
||||
end
|
||||
|
||||
@@ -52,7 +52,7 @@ module Api
|
||||
end
|
||||
|
||||
def error_during_processing(exception)
|
||||
Alert.raise(exception)
|
||||
Bugsnag.notify(exception)
|
||||
|
||||
if Rails.env.development? || Rails.env.test?
|
||||
render status: :unprocessable_entity,
|
||||
|
||||
@@ -18,7 +18,7 @@ module Api
|
||||
end
|
||||
|
||||
def index
|
||||
@pagy, customers = pagy(search_customers, **pagy_options)
|
||||
@pagy, customers = pagy(search_customers, pagy_options)
|
||||
|
||||
render json: Api::V1::CustomerSerializer.new(customers, pagination_options)
|
||||
end
|
||||
|
||||
@@ -25,6 +25,6 @@ class BaseController < ApplicationController
|
||||
def set_order_cycle
|
||||
return if @order_cycles.count != 1
|
||||
|
||||
current_order(true).assign_order_cycle! @order_cycles.first
|
||||
current_order(true).set_order_cycle! @order_cycles.first
|
||||
end
|
||||
end
|
||||
|
||||
@@ -11,7 +11,7 @@ class CartController < BaseController
|
||||
order.cap_quantity_at_stock!
|
||||
order.recreate_all_fees!
|
||||
|
||||
StockSyncJob.sync_linked_catalogs_later(order)
|
||||
StockSyncJob.sync_linked_catalogs(order)
|
||||
|
||||
render json: { error: false, stock_levels: stock_levels(order) }, status: :ok
|
||||
else
|
||||
|
||||
@@ -26,7 +26,6 @@ class CheckoutController < BaseController
|
||||
if params[:step].blank?
|
||||
redirect_to_step_based_on_order
|
||||
else
|
||||
handle_insufficient_stock if details_step?
|
||||
update_order_state
|
||||
check_step
|
||||
end
|
||||
@@ -37,9 +36,6 @@ class CheckoutController < BaseController
|
||||
end
|
||||
|
||||
def update
|
||||
return render cable_ready: cable_car.redirect_to(url: checkout_step_path(:details)) \
|
||||
unless sufficient_stock?
|
||||
|
||||
if confirm_order || update_order
|
||||
return if performed?
|
||||
|
||||
@@ -82,21 +78,8 @@ class CheckoutController < BaseController
|
||||
|
||||
return true if redirect_to_payment_gateway
|
||||
|
||||
# Redeem VINE voucher
|
||||
vine_voucher_redeemer = Vine::VoucherRedeemerService.new(order: @order)
|
||||
unless vine_voucher_redeemer.redeem
|
||||
# rubocop:disable Rails/DeprecatedActiveModelErrorsMethods
|
||||
flash[:error] = if vine_voucher_redeemer.errors.keys.include?(:redeeming_failed)
|
||||
vine_voucher_redeemer.errors[:redeeming_failed]
|
||||
else
|
||||
I18n.t('checkout.errors.voucher_redeeming_error')
|
||||
end
|
||||
return false
|
||||
# rubocop:enable Rails/DeprecatedActiveModelErrorsMethods
|
||||
end
|
||||
@order.process_payments!
|
||||
@order.confirm!
|
||||
BackorderJob.check_stock(@order)
|
||||
order_completion_reset @order
|
||||
end
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ module CheckoutCallbacks
|
||||
|
||||
before_action :ensure_order_not_completed
|
||||
before_action :ensure_checkout_allowed
|
||||
before_action :handle_insufficient_stock
|
||||
before_action :check_authorization
|
||||
end
|
||||
|
||||
@@ -48,8 +49,7 @@ module CheckoutCallbacks
|
||||
end
|
||||
|
||||
def load_saved_addresses
|
||||
finder = OpenFoodNetwork::AddressFinder.new(email: @order.email, customer: @order.customer,
|
||||
user: spree_current_user)
|
||||
finder = OpenFoodNetwork::AddressFinder.new(@order.email, @order.customer, spree_current_user)
|
||||
|
||||
@order.bill_address ||= finder.bill_address
|
||||
@order.ship_address ||= finder.ship_address
|
||||
|
||||
@@ -26,7 +26,7 @@ module OrderCompletion
|
||||
# Builds an order setting the token and distributor of the one specified
|
||||
def build_new_order(distributor, token)
|
||||
new_order = current_order(true)
|
||||
new_order.assign_distributor!(distributor)
|
||||
new_order.set_distributor!(distributor)
|
||||
new_order.tokenized_permission.token = token
|
||||
new_order.tokenized_permission.save!
|
||||
end
|
||||
@@ -50,7 +50,9 @@ module OrderCompletion
|
||||
end
|
||||
|
||||
def order_invalid!
|
||||
Alert.raise_with_record("Notice: invalid order loaded during checkout", @order)
|
||||
Bugsnag.notify("Notice: invalid order loaded during checkout") do |payload|
|
||||
payload.add_metadata :order, :order, @order
|
||||
end
|
||||
|
||||
flash[:error] = t('checkout.order_not_loaded')
|
||||
redirect_to main_app.shop_path
|
||||
@@ -90,7 +92,9 @@ module OrderCompletion
|
||||
end
|
||||
|
||||
def notify_failure(error = RuntimeError.new(order_processing_error))
|
||||
Alert.raise_with_record(error, @order)
|
||||
Bugsnag.notify(error) do |payload|
|
||||
payload.add_metadata :order, @order
|
||||
end
|
||||
flash[:error] = order_processing_error if flash.blank?
|
||||
end
|
||||
|
||||
|
||||
@@ -4,28 +4,27 @@ module OrderStockCheck
|
||||
include CablecarResponses
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
delegate :sufficient_stock?, to: :check_stock_service
|
||||
|
||||
def valid_order_line_items?
|
||||
OrderCycles::DistributedVariantsService.new(@order.order_cycle, @order.distributor).
|
||||
distributes_order_variants?(@order)
|
||||
@order.insufficient_stock_lines.empty? &&
|
||||
OrderCycles::DistributedVariantsService.new(@order.order_cycle, @order.distributor).
|
||||
distributes_order_variants?(@order)
|
||||
end
|
||||
|
||||
def handle_insufficient_stock
|
||||
@any_out_of_stock = false
|
||||
|
||||
return if sufficient_stock?
|
||||
|
||||
@any_out_of_stock = true
|
||||
@updated_variants = check_stock_service.update_line_items
|
||||
flash[:error] = Spree.t(:inventory_error_flash_for_insufficient_quantity)
|
||||
redirect_to main_app.cart_path
|
||||
end
|
||||
|
||||
def check_order_cycle_expiry
|
||||
return unless current_order_cycle&.closed?
|
||||
|
||||
Alert.raise_with_record("Notice: order cycle closed during checkout completion", current_order)
|
||||
Bugsnag.notify("Notice: order cycle closed during checkout completion") do |payload|
|
||||
payload.add_metadata :order, :order, current_order
|
||||
end
|
||||
current_order.empty!
|
||||
current_order.assign_order_cycle! nil
|
||||
current_order.set_order_cycle! nil
|
||||
|
||||
flash[:info] = I18n.t('order_cycle_closed')
|
||||
respond_to do |format|
|
||||
@@ -39,7 +38,7 @@ module OrderStockCheck
|
||||
|
||||
private
|
||||
|
||||
def check_stock_service
|
||||
@check_stock_service ||= Orders::CheckStockService.new(order: @order)
|
||||
def sufficient_stock?
|
||||
@sufficient_stock ||= @order.insufficient_stock_lines.blank?
|
||||
end
|
||||
end
|
||||
|
||||
@@ -24,7 +24,6 @@ class EnterprisesController < BaseController
|
||||
set_noindex_meta_tag
|
||||
|
||||
@enterprise = current_distributor
|
||||
store_location_for :spree_user, request.original_fullpath
|
||||
end
|
||||
|
||||
def relatives
|
||||
|
||||
@@ -4,6 +4,11 @@ class ErrorsController < ApplicationController
|
||||
layout "errors"
|
||||
|
||||
def not_found
|
||||
Bugsnag.notify("404") do |event|
|
||||
event.severity = "info"
|
||||
|
||||
event.add_metadata(:request, :env, request.env)
|
||||
end
|
||||
render status: :not_found, formats: :html
|
||||
end
|
||||
|
||||
|
||||
@@ -2,13 +2,8 @@
|
||||
|
||||
class OmniauthCallbacksController < Devise::OmniauthCallbacksController
|
||||
def openid_connect
|
||||
ActiveRecord::Base.transaction do
|
||||
OidcAccount.link(spree_current_user, request.env["omniauth.auth"])
|
||||
end
|
||||
OidcAccount.link(spree_current_user, request.env["omniauth.auth"])
|
||||
|
||||
redirect_to admin_oidc_settings_path
|
||||
rescue ActiveRecord::RecordNotUnique
|
||||
flash[:error] = t("devise.oidc.record_not_unique", uid: request.env["omniauth.auth"].uid)
|
||||
redirect_to admin_oidc_settings_path
|
||||
end
|
||||
|
||||
|
||||
@@ -14,8 +14,6 @@ module PaymentGateways
|
||||
after_action :reset_order_when_complete, only: :confirm
|
||||
|
||||
def express
|
||||
return redirect_to order_failed_route if @any_out_of_stock == true
|
||||
|
||||
pp_request = provider.build_set_express_checkout(
|
||||
express_checkout_request_details(@order)
|
||||
)
|
||||
@@ -43,8 +41,6 @@ module PaymentGateways
|
||||
end
|
||||
|
||||
def confirm
|
||||
return redirect_to order_failed_route if @any_out_of_stock == true
|
||||
|
||||
# At this point the user has come back from the Paypal form, and we get one
|
||||
# last chance to interact with the payment process before the money moves...
|
||||
|
||||
|
||||
@@ -8,12 +8,9 @@ module PaymentGateways
|
||||
before_action :load_checkout_order, only: :confirm
|
||||
before_action :validate_payment_intent, only: :confirm
|
||||
before_action :check_order_cycle_expiry, only: :confirm
|
||||
before_action :validate_stock, only: :confirm
|
||||
|
||||
def confirm
|
||||
validate_stock
|
||||
|
||||
return redirect_to order_failed_route if @any_out_of_stock == true
|
||||
|
||||
process_payment_completion!
|
||||
end
|
||||
|
||||
@@ -24,7 +21,7 @@ module PaymentGateways
|
||||
|
||||
result = ProcessPaymentIntent.new(params["payment_intent"], @order).call!
|
||||
|
||||
unless result.success?
|
||||
unless result.ok?
|
||||
flash.now[:error] = "#{I18n.t('payment_could_not_process')}. #{result.error}"
|
||||
end
|
||||
|
||||
@@ -68,8 +65,11 @@ module PaymentGateways
|
||||
end
|
||||
|
||||
def valid_payment_intent?
|
||||
@valid_payment_intent ||= params["payment_intent"]&.starts_with?("pi_") &&
|
||||
order_and_payment_valid?
|
||||
@valid_payment_intent ||= begin
|
||||
return false unless params["payment_intent"]&.starts_with?("pi_")
|
||||
|
||||
order_and_payment_valid?
|
||||
end
|
||||
end
|
||||
|
||||
def order_and_payment_valid?
|
||||
|
||||
@@ -11,7 +11,7 @@ class ShopController < BaseController
|
||||
def order_cycle
|
||||
if request.post?
|
||||
if oc = OrderCycle.with_distributor(@distributor).active.find_by(id: params[:order_cycle_id])
|
||||
current_order(true).assign_order_cycle! oc
|
||||
current_order(true).set_order_cycle! oc
|
||||
@current_order_cycle = oc
|
||||
render json: @current_order_cycle, serializer: Api::OrderCycleSerializer
|
||||
else
|
||||
|
||||
@@ -9,7 +9,6 @@ module Spree
|
||||
helper CheckoutHelper
|
||||
|
||||
before_action :load_order, only: [:edit, :update, :fire, :resend, :invoice, :print]
|
||||
before_action :refuse_changing_shipped_orders, only: [:update]
|
||||
before_action :load_distribution_choices, only: [:new, :create, :edit, :update]
|
||||
before_action :require_distributor_abn, only: :invoice
|
||||
before_action :restore_saved_query!, only: :index
|
||||
@@ -18,7 +17,7 @@ module Spree
|
||||
|
||||
def index
|
||||
orders = SearchOrders.new(search_params, spree_current_user).orders
|
||||
@pagy, @orders = pagy(orders, limit: params[:per_page] || 15)
|
||||
@pagy, @orders = pagy(orders, items: params[:per_page] || 15)
|
||||
|
||||
update_search_results if searching?
|
||||
end
|
||||
@@ -70,8 +69,7 @@ module Spree
|
||||
@order.send_cancellation_email = params[:send_cancellation_email] != "false"
|
||||
@order.restock_items = params.fetch(:restock_items, "true") == "true"
|
||||
|
||||
if allowed_events.include?(event) && @order.public_send(event.to_s)
|
||||
AmendBackorderJob.perform_later(@order) if @order.completed?
|
||||
if @order.public_send(event.to_s)
|
||||
flash[:success] = Spree.t(:order_updated)
|
||||
else
|
||||
flash[:error] = Spree.t(:cannot_perform_operation)
|
||||
@@ -162,13 +160,6 @@ module Spree
|
||||
@order.update_order!
|
||||
end
|
||||
|
||||
def refuse_changing_shipped_orders
|
||||
return unless @order.shipped?
|
||||
|
||||
flash[:error] = I18n.t("spree.admin.orders.add_product.cannot_add_item_to_shipped_order")
|
||||
redirect_to spree.edit_admin_order_path(@order)
|
||||
end
|
||||
|
||||
def order_params
|
||||
return params[:order] if params[:order].blank?
|
||||
|
||||
@@ -206,10 +197,6 @@ module Spree
|
||||
ocs.closed +
|
||||
ocs.undated
|
||||
end
|
||||
|
||||
def allowed_events
|
||||
%w{cancel resume}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -5,11 +5,9 @@ module Spree
|
||||
module Admin
|
||||
class OverviewController < Spree::Admin::BaseController
|
||||
def index
|
||||
my_enterprises = Enterprise.managed_by(spree_current_user)
|
||||
@enterprises = my_enterprises
|
||||
@enterprises = Enterprise
|
||||
.managed_by(spree_current_user)
|
||||
.order('is_primary_producer ASC, name')
|
||||
.limit(25)
|
||||
@enterprises_count = my_enterprises.count if @enterprises.count >= 25
|
||||
@product_count = Spree::Product.active.managed_by(spree_current_user).count
|
||||
@order_cycle_count = OrderCycle.active.managed_by(spree_current_user).count
|
||||
|
||||
|
||||
@@ -24,12 +24,9 @@ module Spree
|
||||
end
|
||||
|
||||
def create
|
||||
# Try to redeem VINE voucher first as we don't want to create a payment and complete
|
||||
# the order if it fails
|
||||
return redirect_to spree.admin_order_payments_path(@order) unless redeem_vine_voucher
|
||||
|
||||
@payment = @order.payments.build(object_params)
|
||||
load_payment_source
|
||||
|
||||
begin
|
||||
unless @payment.save
|
||||
redirect_to spree.admin_order_payments_path(@order)
|
||||
@@ -54,10 +51,6 @@ module Spree
|
||||
event = params[:e]
|
||||
return unless event && @payment.payment_source
|
||||
|
||||
# capture_and_complete_order will complete the order, so we want to try to redeem VINE
|
||||
# voucher first and exit if it fails
|
||||
return if event == "capture_and_complete_order" && !redeem_vine_voucher
|
||||
|
||||
# Because we have a transition method also called void, we do this to avoid conflicts.
|
||||
event = "void_transaction" if event == "void"
|
||||
if allowed_events.include?(event) && @payment.public_send("#{event}!")
|
||||
@@ -67,7 +60,7 @@ module Spree
|
||||
end
|
||||
rescue StandardError => e
|
||||
logger.error e.message
|
||||
Alert.raise(e)
|
||||
Bugsnag.notify(e)
|
||||
flash[:error] = e.message
|
||||
ensure
|
||||
redirect_to request.referer
|
||||
@@ -189,22 +182,6 @@ module Spree
|
||||
%w{capture void_transaction credit refund resend_authorization_email
|
||||
capture_and_complete_order}
|
||||
end
|
||||
|
||||
def redeem_vine_voucher
|
||||
vine_voucher_redeemer = Vine::VoucherRedeemerService.new(order: @order)
|
||||
if vine_voucher_redeemer.redeem == false
|
||||
# rubocop:disable Rails/DeprecatedActiveModelErrorsMethods
|
||||
flash[:error] = if vine_voucher_redeemer.errors.keys.include?(:redeeming_failed)
|
||||
vine_voucher_redeemer.errors[:redeeming_failed]
|
||||
else
|
||||
I18n.t('checkout.errors.voucher_redeeming_error')
|
||||
end
|
||||
# rubocop:enable Rails/DeprecatedActiveModelErrorsMethods
|
||||
return false
|
||||
end
|
||||
|
||||
true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -11,7 +11,6 @@ module Spree
|
||||
include OrderCyclesHelper
|
||||
include EnterprisesHelper
|
||||
helper ::Admin::ProductsHelper
|
||||
helper Spree::Admin::TaxCategoriesHelper
|
||||
|
||||
before_action :load_data
|
||||
before_action :load_producers, only: [:index, :new]
|
||||
@@ -134,9 +133,9 @@ module Spree
|
||||
end
|
||||
|
||||
def product_set_from_params
|
||||
collection_hash = products_bulk_params[:products].each_with_index.to_h { |p, i|
|
||||
[i, p]
|
||||
}
|
||||
collection_hash = Hash[products_bulk_params[:products].each_with_index.map { |p, i|
|
||||
[i, p]
|
||||
} ]
|
||||
Sets::ProductSet.new(collection_attributes: collection_hash)
|
||||
end
|
||||
|
||||
@@ -214,7 +213,7 @@ module Spree
|
||||
end
|
||||
|
||||
def notify_bugsnag(error, product, variant)
|
||||
Alert.raise(error) do |report|
|
||||
Bugsnag.notify(error) do |report|
|
||||
report.add_metadata(:product,
|
||||
{ product: product.attributes, variant: variant.attributes })
|
||||
report.add_metadata(:product, :product_error, product.errors.first) unless product.valid?
|
||||
|
||||
@@ -104,7 +104,7 @@ module Spree
|
||||
|
||||
return unless shipping_fees
|
||||
|
||||
shipping_fees.each_value do |shipping_amount|
|
||||
shipping_fees.each do |_, shipping_amount|
|
||||
unless shipping_amount.nil? || Float(shipping_amount, exception: false)
|
||||
flash[:error] = I18n.t(:calculator_preferred_value_error)
|
||||
return redirect_to location_after_save
|
||||
|
||||
@@ -11,6 +11,8 @@ module Spree
|
||||
|
||||
# http://spreecommerce.com/blog/2010/11/02/json-hijacking-vulnerability/
|
||||
before_action :check_json_authenticity, only: :index
|
||||
before_action :load_roles, only: [:edit, :new, :update, :create,
|
||||
:generate_api_key, :clear_api_key]
|
||||
|
||||
def index
|
||||
respond_with(@collection) do |format|
|
||||
@@ -20,9 +22,17 @@ module Spree
|
||||
end
|
||||
|
||||
def create
|
||||
if params[:user]
|
||||
roles = params[:user].delete("spree_role_ids")
|
||||
end
|
||||
|
||||
@user = Spree::User.new(user_params)
|
||||
if @user.save
|
||||
|
||||
if roles
|
||||
@user.spree_roles = roles.compact_blank.collect{ |r| Spree::Role.find(r) }
|
||||
end
|
||||
|
||||
flash[:success] = Spree.t(:created_successfully)
|
||||
redirect_to edit_admin_user_path(@user)
|
||||
else
|
||||
@@ -31,7 +41,15 @@ module Spree
|
||||
end
|
||||
|
||||
def update
|
||||
if params[:user]
|
||||
roles = params[:user].delete("spree_role_ids")
|
||||
end
|
||||
|
||||
if @user.update(user_params)
|
||||
if roles
|
||||
@user.spree_roles = roles.compact_blank.collect{ |r| Spree::Role.find(r) }
|
||||
end
|
||||
|
||||
flash[:success] = update_message
|
||||
redirect_to edit_admin_user_path(@user)
|
||||
else
|
||||
@@ -60,7 +78,7 @@ module Spree
|
||||
limit(params[:limit] || 100)
|
||||
else
|
||||
@search = Spree::User.ransack(params[:q])
|
||||
@pagy, @collection = pagy(@search.result, limit: Spree::Config[:admin_products_per_page])
|
||||
@pagy, @collection = pagy(@search.result, items: Spree::Config[:admin_products_per_page])
|
||||
@collection
|
||||
end
|
||||
end
|
||||
@@ -105,6 +123,10 @@ module Spree
|
||||
sign_in(@user, event: :authentication, bypass: true)
|
||||
end
|
||||
|
||||
def load_roles
|
||||
@roles = Spree::Role.where(nil)
|
||||
end
|
||||
|
||||
def new_email_unconfirmed?
|
||||
params[:user][:email] != @user.email
|
||||
end
|
||||
@@ -115,7 +137,7 @@ module Spree
|
||||
|
||||
def user_params
|
||||
::PermittedAttributes::User.new(params).call(
|
||||
%i[admin enterprise_limit show_api_key_view]
|
||||
%i[enterprise_limit show_api_key_view]
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -64,10 +64,7 @@ module Spree
|
||||
end
|
||||
|
||||
def search
|
||||
scoper = OpenFoodNetwork::ScopeVariantsForSearch.new(
|
||||
variant_search_params,
|
||||
spree_current_user
|
||||
)
|
||||
scoper = OpenFoodNetwork::ScopeVariantsForSearch.new(variant_search_params)
|
||||
@variants = scoper.search
|
||||
render json: @variants, each_serializer: ::Api::Admin::VariantSerializer
|
||||
end
|
||||
@@ -117,7 +114,7 @@ module Spree
|
||||
def variant_search_params
|
||||
params.permit(
|
||||
:q, :distributor_id, :order_cycle_id, :schedule_id, :eligible_for_subscriptions,
|
||||
:include_out_of_stock, :search_variants_as, :order_id
|
||||
:include_out_of_stock
|
||||
).to_h.with_indifferent_access
|
||||
end
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ module Spree
|
||||
params[:q] ||= {}
|
||||
params[:q][:s] ||= "name asc"
|
||||
@search = super.ransack(params[:q])
|
||||
@pagy, @zones = pagy(@search.result, limit: Spree::Config[:orders_per_page])
|
||||
@pagy, @zones = pagy(@search.result, items: Spree::Config[:orders_per_page])
|
||||
@zones
|
||||
end
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
module Spree
|
||||
class ApiKeysController < ::BaseController
|
||||
include Spree::Core::ControllerHelpers
|
||||
include I18nHelper
|
||||
|
||||
prepend_before_action :load_object
|
||||
|
||||
@@ -9,7 +9,7 @@ module Spree
|
||||
|
||||
layout 'darkswarm'
|
||||
|
||||
rescue_from ActiveRecord::RecordNotFound, with: :render404
|
||||
rescue_from ActiveRecord::RecordNotFound, with: :render_404
|
||||
helper 'spree/orders'
|
||||
|
||||
respond_to :html, :json
|
||||
@@ -70,15 +70,14 @@ module Spree
|
||||
@order.recreate_all_fees! # Enterprise fees on line items and on the order itself
|
||||
|
||||
# Re apply the voucher
|
||||
OrderManagement::Order::Updater.new(@order).update_voucher
|
||||
VoucherAdjustmentsService.new(@order).update
|
||||
@order.update_totals_and_states
|
||||
|
||||
if @order.complete?
|
||||
@order.update_payment_fees!
|
||||
@order.create_tax_charge!
|
||||
end
|
||||
|
||||
AmendBackorderJob.perform_later(@order) if @order.completed?
|
||||
|
||||
respond_with(@order) do |format|
|
||||
format.html do
|
||||
if params.key?(:checkout)
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
module Spree
|
||||
class UsersController < ::BaseController
|
||||
include Spree::Core::ControllerHelpers
|
||||
include I18nHelper
|
||||
include CablecarResponses
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'open_food_network/error_logger'
|
||||
require "spree/core/controller_helpers/auth"
|
||||
require "spree/core/controller_helpers/common"
|
||||
require "spree/core/controller_helpers/order"
|
||||
@@ -31,12 +32,12 @@ class UserRegistrationsController < Devise::RegistrationsController
|
||||
associate_user
|
||||
|
||||
respond_to do |format|
|
||||
format.json do
|
||||
format.js do
|
||||
render json: { email: @user.email }
|
||||
end
|
||||
end
|
||||
rescue StandardError => e
|
||||
Alert.raise(e)
|
||||
OpenFoodNetwork::ErrorLogger.notify(e)
|
||||
render_error(message: I18n.t('unknown_error', scope: I18N_SCOPE))
|
||||
end
|
||||
|
||||
@@ -51,7 +52,7 @@ class UserRegistrationsController < Devise::RegistrationsController
|
||||
def render_error(errors = {})
|
||||
clean_up_passwords(resource)
|
||||
respond_to do |format|
|
||||
format.json do
|
||||
format.js do
|
||||
render json: errors, status: :unauthorized
|
||||
end
|
||||
end
|
||||
|
||||
@@ -4,16 +4,7 @@ class VoucherAdjustmentsController < BaseController
|
||||
before_action :set_order
|
||||
|
||||
def create
|
||||
if voucher_params[:voucher_code].blank?
|
||||
@order.errors.add(:voucher_code, I18n.t('checkout.errors.voucher_code_blank'))
|
||||
return render_error
|
||||
end
|
||||
|
||||
voucher = load_voucher
|
||||
|
||||
return render_error unless valid_voucher?(voucher)
|
||||
|
||||
if add_voucher_to_order(voucher)
|
||||
if add_voucher
|
||||
update_payment_section
|
||||
elsif @order.errors.present?
|
||||
render_error
|
||||
@@ -39,28 +30,19 @@ class VoucherAdjustmentsController < BaseController
|
||||
@order = current_order
|
||||
end
|
||||
|
||||
def valid_voucher?(voucher)
|
||||
return false if @order.errors.present?
|
||||
def add_voucher
|
||||
if voucher_params[:voucher_code].blank?
|
||||
@order.errors.add(:voucher_code, I18n.t('checkout.errors.voucher_not_found'))
|
||||
return false
|
||||
end
|
||||
|
||||
voucher = Voucher.find_by(code: voucher_params[:voucher_code], enterprise: @order.distributor)
|
||||
|
||||
if voucher.nil?
|
||||
@order.errors.add(:voucher_code, I18n.t('checkout.errors.voucher_code_not_found'))
|
||||
@order.errors.add(:voucher_code, I18n.t('checkout.errors.voucher_not_found'))
|
||||
return false
|
||||
end
|
||||
|
||||
if !voucher.valid?
|
||||
@order.errors.add(
|
||||
:voucher_code,
|
||||
I18n.t(
|
||||
'checkout.errors.create_voucher_error', error: voucher.errors.full_messages.to_sentence
|
||||
)
|
||||
)
|
||||
return false
|
||||
end
|
||||
|
||||
true
|
||||
end
|
||||
|
||||
def add_voucher_to_order(voucher)
|
||||
adjustment = voucher.create_adjustment(voucher.code, @order)
|
||||
|
||||
unless adjustment.persisted?
|
||||
@@ -69,38 +51,14 @@ class VoucherAdjustmentsController < BaseController
|
||||
return false
|
||||
end
|
||||
|
||||
# calculate_voucher_adjustment
|
||||
clear_payments
|
||||
|
||||
OrderManagement::Order::Updater.new(@order).update_voucher
|
||||
VoucherAdjustmentsService.new(@order).update
|
||||
@order.update_totals_and_states
|
||||
|
||||
true
|
||||
end
|
||||
|
||||
def load_voucher
|
||||
voucher = Voucher.find_by(code: voucher_params[:voucher_code],
|
||||
enterprise: @order.distributor)
|
||||
return voucher unless voucher.nil? || voucher.is_a?(Vouchers::Vine)
|
||||
|
||||
vine_voucher
|
||||
end
|
||||
|
||||
def vine_voucher
|
||||
vine_voucher_validator = Vine::VoucherValidatorService.new(
|
||||
voucher_code: voucher_params[:voucher_code], enterprise: @order.distributor
|
||||
)
|
||||
voucher = vine_voucher_validator.validate
|
||||
|
||||
return nil if vine_voucher_validator.errors[:not_found_voucher].present?
|
||||
|
||||
if vine_voucher_validator.errors.present?
|
||||
@order.errors.add(:voucher_code, I18n.t('checkout.errors.add_voucher_error'))
|
||||
return nil
|
||||
end
|
||||
|
||||
voucher
|
||||
end
|
||||
|
||||
def update_payment_section
|
||||
render cable_ready: cable_car.replace(
|
||||
selector: "#checkout-payment-methods",
|
||||
|
||||
@@ -30,7 +30,7 @@ class EnterpriseFeesBulkUpdate
|
||||
private
|
||||
|
||||
def check_enterprise_fee_input
|
||||
enterprise_fee_bulk_params['collection_attributes'].each_value do |fee_row|
|
||||
enterprise_fee_bulk_params['collection_attributes'].each do |_, fee_row|
|
||||
enterprise_fees = fee_row['calculator_attributes']&.slice(
|
||||
:preferred_flat_percent, :preferred_amount,
|
||||
:preferred_first_item, :preferred_additional_item,
|
||||
@@ -40,7 +40,7 @@ class EnterpriseFeesBulkUpdate
|
||||
|
||||
next unless enterprise_fees
|
||||
|
||||
enterprise_fees.each_value do |enterprise_amount|
|
||||
enterprise_fees.each do |_, enterprise_amount|
|
||||
unless enterprise_amount.nil? || Float(enterprise_amount, exception: false)
|
||||
@errors.add(:base, I18n.t(:calculator_preferred_value_error))
|
||||
end
|
||||
@@ -49,7 +49,7 @@ class EnterpriseFeesBulkUpdate
|
||||
end
|
||||
|
||||
def check_calculators_compatibility_with_taxes
|
||||
enterprise_fee_bulk_params['collection_attributes'].each_value do |enterprise_fee|
|
||||
enterprise_fee_bulk_params['collection_attributes'].each do |_, enterprise_fee|
|
||||
next unless enterprise_fee['inherits_tax_category'] == "true"
|
||||
next unless EnterpriseFee::PER_ORDER_CALCULATORS.include?(enterprise_fee['calculator_type'])
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user