mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-01-14 18:56:49 +00:00
Compare commits
437 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
90288b8cbf | ||
|
|
c821b0a285 | ||
|
|
c37376d67e | ||
|
|
49ec5b2089 | ||
|
|
92ef5fe3d5 | ||
|
|
ae477b7e52 | ||
|
|
0e191e5fca | ||
|
|
64f9ea6fc0 | ||
|
|
058c6749da | ||
|
|
2d15ec4458 | ||
|
|
56eaa8bb98 | ||
|
|
1e1f1e1e1b | ||
|
|
1f8a9f9c76 | ||
|
|
b1893942ac | ||
|
|
ad59ed4d40 | ||
|
|
8491a167ed | ||
|
|
59277292fb | ||
|
|
354a7ab687 | ||
|
|
a5a1ee9bd9 | ||
|
|
ad3f78ef69 | ||
|
|
e02497b163 | ||
|
|
7d2d94398f | ||
|
|
0ecf004ff2 | ||
|
|
444f448207 | ||
|
|
d9381b23d7 | ||
|
|
6a9a2884d6 | ||
|
|
70edd4b898 | ||
|
|
b57a2befd9 | ||
|
|
fef9a78198 | ||
|
|
dd86736170 | ||
|
|
0d8c7ef118 | ||
|
|
20730b8768 | ||
|
|
ad7c69189b | ||
|
|
3a72aefc1c | ||
|
|
e855ea0dbd | ||
|
|
1eba950e19 | ||
|
|
9cd04c087e | ||
|
|
459d25e533 | ||
|
|
b06e562425 | ||
|
|
2936cfebca | ||
|
|
b8ad428b5d | ||
|
|
ca34d24847 | ||
|
|
6e581fce75 | ||
|
|
66041061fb | ||
|
|
e54c27c900 | ||
|
|
b3d3d6bf06 | ||
|
|
5876c52318 | ||
|
|
842f4ae40e | ||
|
|
342ef4e9eb | ||
|
|
210201514e | ||
|
|
2d3f18a71b | ||
|
|
9d284b7110 | ||
|
|
994f1ca6c6 | ||
|
|
f65e4797cf | ||
|
|
52aeec5ac4 | ||
|
|
7032b3f463 | ||
|
|
c26686b430 | ||
|
|
60c8f4ee20 | ||
|
|
25f396c126 | ||
|
|
0166abcd2a | ||
|
|
4cd0071dd4 | ||
|
|
32c96b72ad | ||
|
|
30701d61e2 | ||
|
|
45b712ddcd | ||
|
|
3153e99497 | ||
|
|
a2f263e081 | ||
|
|
3cb6a2617b | ||
|
|
420deca437 | ||
|
|
76aebf8a72 | ||
|
|
1ec570375f | ||
|
|
75c33b29d5 | ||
|
|
1bfff91c72 | ||
|
|
d469552afc | ||
|
|
e6cffde8fb | ||
|
|
910ded1a8c | ||
|
|
2555a9e710 | ||
|
|
f532c4712e | ||
|
|
3af28c4b5b | ||
|
|
63b864253d | ||
|
|
8efeec4301 | ||
|
|
bed33928e0 | ||
|
|
bb7a31b286 | ||
|
|
75b2fe1dd4 | ||
|
|
c0924fbe5e | ||
|
|
d72bc49409 | ||
|
|
06867ff7ea | ||
|
|
76a1fe7767 | ||
|
|
3363c523ea | ||
|
|
91628f8daa | ||
|
|
f3dfbab109 | ||
|
|
d01474ebcd | ||
|
|
a062a7b697 | ||
|
|
fe8b805e1f | ||
|
|
f3f43225cb | ||
|
|
65604f5b04 | ||
|
|
661bb29029 | ||
|
|
b725697972 | ||
|
|
b8546db1e5 | ||
|
|
bc25a5ecd6 | ||
|
|
71de96e0a6 | ||
|
|
23bcdc1cb7 | ||
|
|
60ac1c9fbe | ||
|
|
fcd4d073c4 | ||
|
|
df4cf4b768 | ||
|
|
3f39d94bd3 | ||
|
|
acfe3f6589 | ||
|
|
1717c5376b | ||
|
|
1426b6eeb7 | ||
|
|
188b2eb754 | ||
|
|
6e055ddbdf | ||
|
|
025fc784a8 | ||
|
|
fefd0239e6 | ||
|
|
0fa67c69fd | ||
|
|
44cbe55c96 | ||
|
|
56d3ac247d | ||
|
|
0ed08f8f9d | ||
|
|
667b49b7f1 | ||
|
|
dd6d1ea64b | ||
|
|
f0dd1885c9 | ||
|
|
05b6200c8f | ||
|
|
fcd6897240 | ||
|
|
c23c773942 | ||
|
|
7af960fceb | ||
|
|
45a0705379 | ||
|
|
6da1200b64 | ||
|
|
1cf31f4028 | ||
|
|
6df71f28ca | ||
|
|
9272d6d82f | ||
|
|
a8114e42a7 | ||
|
|
17e02e7304 | ||
|
|
6ba80f57b3 | ||
|
|
d90200fb3f | ||
|
|
08114b495a | ||
|
|
7b6b3d907c | ||
|
|
cf9ffd8931 | ||
|
|
e6b9373570 | ||
|
|
ec44947b37 | ||
|
|
c0639b37bb | ||
|
|
38388be4da | ||
|
|
352f1ba900 | ||
|
|
7a0ecc777a | ||
|
|
aeefe841bf | ||
|
|
70757ccdef | ||
|
|
7450f8a530 | ||
|
|
618d597f6d | ||
|
|
b7f969eed9 | ||
|
|
b28e30cb6c | ||
|
|
681eee9309 | ||
|
|
6937a133ae | ||
|
|
ddc45e1cd8 | ||
|
|
28a11f1fee | ||
|
|
1c4febd332 | ||
|
|
9e1de75db6 | ||
|
|
8829f6ad03 | ||
|
|
6212cd4d07 | ||
|
|
29a24b7305 | ||
|
|
7c31c951a1 | ||
|
|
33bac6f816 | ||
|
|
a6f0a36b6d | ||
|
|
b253950075 | ||
|
|
b19b987ed0 | ||
|
|
dc84d32028 | ||
|
|
82c99891eb | ||
|
|
f30b899569 | ||
|
|
cd8b7cd239 | ||
|
|
d80481a106 | ||
|
|
174be39c5e | ||
|
|
5f694276f1 | ||
|
|
affb5d7281 | ||
|
|
87b9eeb2f1 | ||
|
|
81c75b2b71 | ||
|
|
ec6d490676 | ||
|
|
80aa8d71a5 | ||
|
|
0408b74987 | ||
|
|
9e9cc28062 | ||
|
|
80fc0a5790 | ||
|
|
5a13aa1c8a | ||
|
|
aabf3c861a | ||
|
|
01e4ca7d93 | ||
|
|
838e88a502 | ||
|
|
4b19d38c58 | ||
|
|
7725fae992 | ||
|
|
b43fa55a7b | ||
|
|
1478990eac | ||
|
|
4a1e32e790 | ||
|
|
75e0a71e10 | ||
|
|
e0efb34fe8 | ||
|
|
4cb9d870b4 | ||
|
|
5b7675cd9b | ||
|
|
b6fc117b17 | ||
|
|
d5c79be7d9 | ||
|
|
7d80033c8e | ||
|
|
1b9d64ad5e | ||
|
|
c648249160 | ||
|
|
765ce68c11 | ||
|
|
020d90b957 | ||
|
|
8d407b1dc9 | ||
|
|
fe1b8aaab3 | ||
|
|
ade35f2fa2 | ||
|
|
cd01a27bdd | ||
|
|
2f9c856645 | ||
|
|
8e8878e43a | ||
|
|
a37e08c2fd | ||
|
|
75b2119dd1 | ||
|
|
6ccc588113 | ||
|
|
7115eb3c0e | ||
|
|
98ebbb2203 | ||
|
|
3c1ee5f033 | ||
|
|
23b8192b2c | ||
|
|
37bf3f495f | ||
|
|
f909bb2c30 | ||
|
|
213b977725 | ||
|
|
f723fe025e | ||
|
|
1525501a9d | ||
|
|
a4c6514275 | ||
|
|
8aba6e9782 | ||
|
|
9a2cd3965c | ||
|
|
b9eeb53901 | ||
|
|
e19caa0caa | ||
|
|
05995bc026 | ||
|
|
6b2297b0e6 | ||
|
|
46ba6b7f9c | ||
|
|
e88a9dab4b | ||
|
|
6a44c45699 | ||
|
|
bb0a6b7f8d | ||
|
|
abaa7c35a7 | ||
|
|
97c4cd382b | ||
|
|
089caa228f | ||
|
|
d9194d3dce | ||
|
|
a792a550b3 | ||
|
|
8c50ed9a45 | ||
|
|
9d09fa9d54 | ||
|
|
8234cc580d | ||
|
|
88b390dac6 | ||
|
|
583acfcc79 | ||
|
|
d9010c3cf3 | ||
|
|
1837d6a381 | ||
|
|
5b1b48afc6 | ||
|
|
a872544b10 | ||
|
|
2b1f75e87e | ||
|
|
9b1c95cbc2 | ||
|
|
3743efd5e4 | ||
|
|
19e654b9e4 | ||
|
|
6b0f690170 | ||
|
|
ffe93fc470 | ||
|
|
a4f28a2fac | ||
|
|
c1e6fff275 | ||
|
|
b5b50f0b5a | ||
|
|
f9764b697d | ||
|
|
0f3626f12d | ||
|
|
be1f4e91e1 | ||
|
|
3dcc4428fa | ||
|
|
2fe49b2070 | ||
|
|
85e4f749f9 | ||
|
|
b671dfda5d | ||
|
|
e6ef52f91c | ||
|
|
da5b147d29 | ||
|
|
b2fd4ccb11 | ||
|
|
5a497bc6ee | ||
|
|
77b7b5ea47 | ||
|
|
035e67c33f | ||
|
|
8e1fb76327 | ||
|
|
441844dd79 | ||
|
|
55f9afef77 | ||
|
|
a9dee9d0ca | ||
|
|
2465880e77 | ||
|
|
7c89f32eb7 | ||
|
|
229a87cf72 | ||
|
|
4f3887fcc8 | ||
|
|
77af4af277 | ||
|
|
677c53303c | ||
|
|
a186de2f8f | ||
|
|
ceeb5f0a3a | ||
|
|
418514b57d | ||
|
|
aa68b69fce | ||
|
|
87aed5d77f | ||
|
|
287cd74b33 | ||
|
|
d217a1394b | ||
|
|
a95767eb04 | ||
|
|
f1138b7a9d | ||
|
|
cb1a7629c5 | ||
|
|
63d284e81a | ||
|
|
00aa60c8a3 | ||
|
|
a1e0feef14 | ||
|
|
1ce167ef16 | ||
|
|
5093fd6eb6 | ||
|
|
0700c65557 | ||
|
|
94cb1f45a0 | ||
|
|
6f9a347b77 | ||
|
|
774aaf4fd8 | ||
|
|
ef22269324 | ||
|
|
c9ec7e13d3 | ||
|
|
d18328c3d1 | ||
|
|
2b3cc71b3d | ||
|
|
6c7676b1a1 | ||
|
|
400f431f88 | ||
|
|
e42015cfd3 | ||
|
|
37d647be94 | ||
|
|
0ac5da33b0 | ||
|
|
d267fa2ea7 | ||
|
|
99bd0cd313 | ||
|
|
a127aa1134 | ||
|
|
d7c39fcab7 | ||
|
|
d98ca6f4c1 | ||
|
|
b431b414a1 | ||
|
|
758d78bfe4 | ||
|
|
2f5981af59 | ||
|
|
5788698e8e | ||
|
|
8be1045f23 | ||
|
|
67f5ae811b | ||
|
|
cf9395f42f | ||
|
|
a7eb95afc5 | ||
|
|
90d8d9fc30 | ||
|
|
60413c2a12 | ||
|
|
7cc4cb0181 | ||
|
|
60914ac8cc | ||
|
|
56855277d7 | ||
|
|
93ac10bb75 | ||
|
|
d6785b2f5a | ||
|
|
c657e31d07 | ||
|
|
6432eceee5 | ||
|
|
af3bb4c419 | ||
|
|
97ceed6cbe | ||
|
|
9c5d393ad1 | ||
|
|
277c51cd51 | ||
|
|
3efa2832de | ||
|
|
f767437f5a | ||
|
|
943d21a767 | ||
|
|
529f3b85eb | ||
|
|
a37b3ed28b | ||
|
|
559a85e4f2 | ||
|
|
7f842d77ea | ||
|
|
8135aeaeda | ||
|
|
5063a772f0 | ||
|
|
f810e500b5 | ||
|
|
b9e1eb2984 | ||
|
|
371d0fbf79 | ||
|
|
71b65b4b98 | ||
|
|
d650d06049 | ||
|
|
be312246ec | ||
|
|
729e62d7db | ||
|
|
6a5faaef22 | ||
|
|
82f94e3969 | ||
|
|
2197656606 | ||
|
|
ffea1cca81 | ||
|
|
d62740da10 | ||
|
|
fa9ed1a66b | ||
|
|
3b1f267465 | ||
|
|
cf30b792f9 | ||
|
|
6daf94875a | ||
|
|
0fcf161889 | ||
|
|
7387b4078a | ||
|
|
e61d951dcf | ||
|
|
f199fb182b | ||
|
|
7f2638f910 | ||
|
|
9034eaa049 | ||
|
|
b5de7b3c5f | ||
|
|
db0922a7cf | ||
|
|
6cdff7c4c7 | ||
|
|
119218b2b5 | ||
|
|
36cada0510 | ||
|
|
4cd088f7a7 | ||
|
|
524d6e87b7 | ||
|
|
0dab580d3e | ||
|
|
5072d65eb7 | ||
|
|
df81fa89f8 | ||
|
|
674f88162e | ||
|
|
71949701ac | ||
|
|
d8fa3e2a19 | ||
|
|
8391ab845f | ||
|
|
e9a205fec9 | ||
|
|
42daf314c4 | ||
|
|
55ad9429db | ||
|
|
0cf9cf3122 | ||
|
|
5d4f8313f3 | ||
|
|
4ef17d3794 | ||
|
|
bc3f847a9d | ||
|
|
c4ab8bb1e7 | ||
|
|
b82bd6c0dc | ||
|
|
eb1919cce9 | ||
|
|
652cbd8874 | ||
|
|
b3834d0476 | ||
|
|
532ce7a4d7 | ||
|
|
af8059c22f | ||
|
|
e7edc068ef | ||
|
|
87f81a51d4 | ||
|
|
1b7aa6406f | ||
|
|
ba46b597f5 | ||
|
|
5cb2d0e061 | ||
|
|
4c6d7148b5 | ||
|
|
6446676853 | ||
|
|
e069cad034 | ||
|
|
81d35741a1 | ||
|
|
5fc3fe03ee | ||
|
|
4d01b2b976 | ||
|
|
8d96411741 | ||
|
|
c533111509 | ||
|
|
e122fe3d2d | ||
|
|
58b6a97d3e | ||
|
|
475cfdc8f0 | ||
|
|
42e2d3cdd5 | ||
|
|
f6df412355 | ||
|
|
45a0185744 | ||
|
|
347d20c3fb | ||
|
|
0ca3dca675 | ||
|
|
ba4b241240 | ||
|
|
8c1c51cb6d | ||
|
|
4d970af2fc | ||
|
|
19fdfbaccb | ||
|
|
57af1de680 | ||
|
|
e7aae5a03c | ||
|
|
3bb0176887 | ||
|
|
0225db6840 | ||
|
|
3ec14607a6 | ||
|
|
29a14848ea | ||
|
|
eadfa8c965 | ||
|
|
2107c05f15 | ||
|
|
074d7194d9 | ||
|
|
44e02b76f9 | ||
|
|
d8959fd7a5 | ||
|
|
65efd3b66c | ||
|
|
ace5d5eb08 | ||
|
|
28c9c53dc0 | ||
|
|
a9a4156251 | ||
|
|
ac7768df05 | ||
|
|
fb7c74471e | ||
|
|
31fedfe083 | ||
|
|
8daa01e228 | ||
|
|
0be87314df | ||
|
|
35198cebcb | ||
|
|
43b874d18b | ||
|
|
d0c687650e | ||
|
|
446be6e127 | ||
|
|
63168086e7 | ||
|
|
17a5b5e620 | ||
|
|
fbb4954ff7 | ||
|
|
ff9e2a33ce |
@@ -1,6 +1,14 @@
|
||||
# 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"
|
||||
|
||||
51
.github/workflows/brakeman-analysis.yml
vendored
51
.github/workflows/brakeman-analysis.yml
vendored
@@ -1,51 +0,0 @@
|
||||
# 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
|
||||
182
.github/workflows/build.yml
vendored
182
.github/workflows/build.yml
vendored
@@ -17,7 +17,7 @@ permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
controllers:
|
||||
controllers_and_models:
|
||||
runs-on: ubuntu-22.04
|
||||
services:
|
||||
postgres:
|
||||
@@ -81,7 +81,7 @@ 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}"
|
||||
KNAPSACK_PRO_TEST_FILE_PATTERN: "{spec/controllers/**/*_spec.rb,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
|
||||
@@ -95,7 +95,7 @@ jobs:
|
||||
if-no-files-found: ignore
|
||||
include-hidden-files: true
|
||||
|
||||
models:
|
||||
system:
|
||||
runs-on: ubuntu-22.04
|
||||
services:
|
||||
postgres:
|
||||
@@ -116,78 +116,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: [2]
|
||||
ci_node_total: [19]
|
||||
# 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]
|
||||
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
|
||||
|
||||
- name: Set up database
|
||||
run: |
|
||||
bin/rails db:create db:schema:load
|
||||
|
||||
- name: Run tests
|
||||
env:
|
||||
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
|
||||
# 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/models/**/*_spec.rb}"
|
||||
run: |
|
||||
bin/rake knapsack_pro:rspec
|
||||
|
||||
- name: Save SimpleCov file
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
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_admin:
|
||||
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: [10]
|
||||
# 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]
|
||||
ci_node_index: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18]
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
@@ -227,7 +159,7 @@ 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}"
|
||||
KNAPSACK_PRO_TEST_FILE_PATTERN: "{spec/system/admin/**/*_spec.rb,spec/system/consumer/**/*_spec.rb}"
|
||||
|
||||
run: |
|
||||
bin/rails assets:precompile knapsack_pro:queue:rspec
|
||||
@@ -235,7 +167,7 @@ jobs:
|
||||
- name: Save SimpleCov file
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: simplecov-chunk-system-admin-${{ matrix.ci_node_index }}
|
||||
name: simplecov-chunk-system-${{ 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
|
||||
@@ -245,94 +177,7 @@ jobs:
|
||||
if: failure()
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
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: [6]
|
||||
# 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]
|
||||
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/rails 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/rails assets:precompile 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
|
||||
name: failed-system_${{ matrix.ci_node_index }}-tests-screenshots
|
||||
path: tmp/capybara/screenshots/*.png
|
||||
retention-days: 7
|
||||
if-no-files-found: ignore
|
||||
@@ -534,11 +379,9 @@ jobs:
|
||||
collate_simplecov_results:
|
||||
runs-on: ubuntu-22.04
|
||||
needs:
|
||||
- controllers
|
||||
- models
|
||||
- controllers_and_models
|
||||
- engines
|
||||
- system_admin
|
||||
- system_consumer
|
||||
- system
|
||||
- test_the_rest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
@@ -565,3 +408,8 @@ 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 ${{ github.event.pull_request.base.ref }}: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
|
||||
|
||||
41
.github/workflows/linters.yml
vendored
41
.github/workflows/linters.yml
vendored
@@ -3,18 +3,32 @@ on: [push, pull_request]
|
||||
permissions:
|
||||
contents: read # to fetch code (actions/checkout)
|
||||
jobs:
|
||||
rubocop:
|
||||
name: runner / rubocop
|
||||
lint:
|
||||
name: prettier and 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:
|
||||
@@ -25,26 +39,3 @@ jobs:
|
||||
filter_mode: nofilter
|
||||
use_bundler: true
|
||||
fail_level: any
|
||||
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
51
.github/workflows/mapi.yml
vendored
@@ -1,51 +0,0 @@
|
||||
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
|
||||
@@ -16,6 +16,7 @@ AllCops:
|
||||
- node_modules/**/*
|
||||
# Excluding: inadequate Naming/FileName rule rejects GemFile name with camelcase
|
||||
- engines/web/Gemfile
|
||||
- .undercover
|
||||
|
||||
Bundler/DuplicatedGem:
|
||||
Enabled: false
|
||||
@@ -102,6 +103,8 @@ Naming/VariableNumber:
|
||||
- street_address_2
|
||||
AllowedPatterns:
|
||||
- _v[\d]+
|
||||
# Cf. conversation https://github.com/openfoodfoundation/openfoodnetwork/pull/13306#pullrequestreview-2831644286
|
||||
- menu_[\d]
|
||||
|
||||
Rails/ApplicationRecord:
|
||||
Exclude:
|
||||
|
||||
@@ -63,7 +63,6 @@ Metrics/ClassLength:
|
||||
- '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'
|
||||
@@ -99,6 +98,7 @@ 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
|
||||
# Configuration parameters: AllowedMethods, AllowedPatterns, Max.
|
||||
@@ -149,7 +149,7 @@ Metrics/MethodLength:
|
||||
- 'lib/spree/localized_number.rb'
|
||||
- 'lib/tasks/sample_data/product_factory.rb'
|
||||
|
||||
# Offense count: 49
|
||||
# Offense count: 47
|
||||
# Configuration parameters: CountComments, Max, CountAsOne.
|
||||
Metrics/ModuleLength:
|
||||
Exclude:
|
||||
@@ -161,46 +161,7 @@ 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
|
||||
@@ -221,276 +182,12 @@ Metrics/PerceivedComplexity:
|
||||
- 'app/models/spree/ability.rb'
|
||||
- 'app/models/spree/order/checkout.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: 26
|
||||
# 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/models/spree/stock_item_spec.rb'
|
||||
- 'spec/models/spree/tax_rate_spec.rb'
|
||||
- 'spec/requests/api/orders_spec.rb'
|
||||
|
||||
# Offense count: 144
|
||||
# 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: 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: 23
|
||||
# This cop supports unsafe autocorrection (--autocorrect-all).
|
||||
# Configuration parameters: EnforcedStyle.
|
||||
@@ -520,36 +217,6 @@ Style/ClassAndModuleChildren:
|
||||
- 'lib/open_food_network/locking.rb'
|
||||
- 'spec/models/spree/payment_method_spec.rb'
|
||||
|
||||
# Offense count: 10
|
||||
# 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/product_import/product_importer.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:
|
||||
@@ -559,28 +226,6 @@ 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:
|
||||
@@ -609,12 +254,3 @@ 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: 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'
|
||||
|
||||
@@ -4,17 +4,8 @@
|
||||
SimpleCov.start 'rails' do
|
||||
add_filter '/bin/'
|
||||
add_filter '/config/'
|
||||
add_filter '/jobs/application_job.rb'
|
||||
add_filter '/schemas/'
|
||||
add_filter '/lib/generators'
|
||||
add_filter '/spec/'
|
||||
add_filter '/vendor/'
|
||||
add_filter '/public'
|
||||
add_filter '/swagger'
|
||||
add_filter '/script'
|
||||
add_filter '/log'
|
||||
add_filter '/db'
|
||||
add_filter '/lib/tasks/sample_data/'
|
||||
|
||||
formatter SimpleCov::Formatter::SimpleFormatter
|
||||
end
|
||||
|
||||
4
.undercover
Normal file
4
.undercover
Normal file
@@ -0,0 +1,4 @@
|
||||
#!/bin/env ruby
|
||||
# frozen_string_literal: true
|
||||
|
||||
-c master
|
||||
3
Gemfile
3
Gemfile
@@ -152,6 +152,7 @@ end
|
||||
group :test, :development do
|
||||
gem 'bullet'
|
||||
gem 'capybara'
|
||||
gem 'capybara-shadowdom'
|
||||
gem 'cuprite'
|
||||
gem 'database_cleaner', require: false
|
||||
gem 'debug', '>= 1.0.0'
|
||||
@@ -171,8 +172,10 @@ end
|
||||
|
||||
group :test do
|
||||
gem 'pdf-reader'
|
||||
gem 'puffing-billy'
|
||||
gem 'rails-controller-testing'
|
||||
gem 'simplecov', require: false
|
||||
gem 'undercover', require: false
|
||||
gem 'vcr', require: false
|
||||
gem 'webmock', require: false
|
||||
# See spec/spec_helper.rb for instructions
|
||||
|
||||
257
Gemfile.lock
257
Gemfile.lock
@@ -48,54 +48,58 @@ PATH
|
||||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
Ascii85 (1.1.0)
|
||||
actioncable (7.0.8)
|
||||
actionpack (= 7.0.8)
|
||||
activesupport (= 7.0.8)
|
||||
Ascii85 (2.0.1)
|
||||
actioncable (7.1.5.2)
|
||||
actionpack (= 7.1.5.2)
|
||||
activesupport (= 7.1.5.2)
|
||||
nio4r (~> 2.0)
|
||||
websocket-driver (>= 0.6.1)
|
||||
actionmailbox (7.0.8)
|
||||
actionpack (= 7.0.8)
|
||||
activejob (= 7.0.8)
|
||||
activerecord (= 7.0.8)
|
||||
activestorage (= 7.0.8)
|
||||
activesupport (= 7.0.8)
|
||||
zeitwerk (~> 2.6)
|
||||
actionmailbox (7.1.5.2)
|
||||
actionpack (= 7.1.5.2)
|
||||
activejob (= 7.1.5.2)
|
||||
activerecord (= 7.1.5.2)
|
||||
activestorage (= 7.1.5.2)
|
||||
activesupport (= 7.1.5.2)
|
||||
mail (>= 2.7.1)
|
||||
net-imap
|
||||
net-pop
|
||||
net-smtp
|
||||
actionmailer (7.0.8)
|
||||
actionpack (= 7.0.8)
|
||||
actionview (= 7.0.8)
|
||||
activejob (= 7.0.8)
|
||||
activesupport (= 7.0.8)
|
||||
actionmailer (7.1.5.2)
|
||||
actionpack (= 7.1.5.2)
|
||||
actionview (= 7.1.5.2)
|
||||
activejob (= 7.1.5.2)
|
||||
activesupport (= 7.1.5.2)
|
||||
mail (~> 2.5, >= 2.5.4)
|
||||
net-imap
|
||||
net-pop
|
||||
net-smtp
|
||||
rails-dom-testing (~> 2.0)
|
||||
actionpack (7.0.8)
|
||||
actionview (= 7.0.8)
|
||||
activesupport (= 7.0.8)
|
||||
rack (~> 2.0, >= 2.2.4)
|
||||
rails-dom-testing (~> 2.2)
|
||||
actionpack (7.1.5.2)
|
||||
actionview (= 7.1.5.2)
|
||||
activesupport (= 7.1.5.2)
|
||||
nokogiri (>= 1.8.5)
|
||||
racc
|
||||
rack (>= 2.2.4)
|
||||
rack-session (>= 1.0.1)
|
||||
rack-test (>= 0.6.3)
|
||||
rails-dom-testing (~> 2.0)
|
||||
rails-html-sanitizer (~> 1.0, >= 1.2.0)
|
||||
rails-dom-testing (~> 2.2)
|
||||
rails-html-sanitizer (~> 1.6)
|
||||
actionpack-action_caching (1.2.2)
|
||||
actionpack (>= 4.0.0)
|
||||
actiontext (7.0.8)
|
||||
actionpack (= 7.0.8)
|
||||
activerecord (= 7.0.8)
|
||||
activestorage (= 7.0.8)
|
||||
activesupport (= 7.0.8)
|
||||
actiontext (7.1.5.2)
|
||||
actionpack (= 7.1.5.2)
|
||||
activerecord (= 7.1.5.2)
|
||||
activestorage (= 7.1.5.2)
|
||||
activesupport (= 7.1.5.2)
|
||||
globalid (>= 0.6.0)
|
||||
nokogiri (>= 1.8.5)
|
||||
actionview (7.0.8)
|
||||
activesupport (= 7.0.8)
|
||||
actionview (7.1.5.2)
|
||||
activesupport (= 7.1.5.2)
|
||||
builder (~> 3.1)
|
||||
erubi (~> 1.4)
|
||||
rails-dom-testing (~> 2.0)
|
||||
rails-html-sanitizer (~> 1.1, >= 1.2.0)
|
||||
erubi (~> 1.11)
|
||||
rails-dom-testing (~> 2.2)
|
||||
rails-html-sanitizer (~> 1.6)
|
||||
active_model_serializers (0.8.4)
|
||||
activemodel (>= 3.0)
|
||||
active_storage_validations (1.1.4)
|
||||
@@ -103,8 +107,8 @@ GEM
|
||||
activemodel (>= 5.2.0)
|
||||
activestorage (>= 5.2.0)
|
||||
activesupport (>= 5.2.0)
|
||||
activejob (7.0.8)
|
||||
activesupport (= 7.0.8)
|
||||
activejob (7.1.5.2)
|
||||
activesupport (= 7.1.5.2)
|
||||
globalid (>= 0.3.6)
|
||||
activemerchant (1.133.0)
|
||||
activesupport (>= 4.2)
|
||||
@@ -112,11 +116,12 @@ GEM
|
||||
i18n (>= 0.6.9)
|
||||
nokogiri (~> 1.4)
|
||||
rexml (~> 3.2.5)
|
||||
activemodel (7.0.8)
|
||||
activesupport (= 7.0.8)
|
||||
activerecord (7.0.8)
|
||||
activemodel (= 7.0.8)
|
||||
activesupport (= 7.0.8)
|
||||
activemodel (7.1.5.2)
|
||||
activesupport (= 7.1.5.2)
|
||||
activerecord (7.1.5.2)
|
||||
activemodel (= 7.1.5.2)
|
||||
activesupport (= 7.1.5.2)
|
||||
timeout (>= 0.4.0)
|
||||
activerecord-import (1.6.0)
|
||||
activerecord (>= 4.2)
|
||||
activerecord-postgresql-adapter (0.0.1)
|
||||
@@ -128,17 +133,24 @@ GEM
|
||||
multi_json (~> 1.11, >= 1.11.2)
|
||||
rack (>= 2.0.8, < 4)
|
||||
railties (>= 6.1)
|
||||
activestorage (7.0.8)
|
||||
actionpack (= 7.0.8)
|
||||
activejob (= 7.0.8)
|
||||
activerecord (= 7.0.8)
|
||||
activesupport (= 7.0.8)
|
||||
activestorage (7.1.5.2)
|
||||
actionpack (= 7.1.5.2)
|
||||
activejob (= 7.1.5.2)
|
||||
activerecord (= 7.1.5.2)
|
||||
activesupport (= 7.1.5.2)
|
||||
marcel (~> 1.0)
|
||||
mini_mime (>= 1.1.0)
|
||||
activesupport (7.0.8)
|
||||
activesupport (7.1.5.2)
|
||||
base64
|
||||
benchmark (>= 0.3)
|
||||
bigdecimal
|
||||
concurrent-ruby (~> 1.0, >= 1.0.2)
|
||||
connection_pool (>= 2.2.5)
|
||||
drb
|
||||
i18n (>= 1.6, < 2)
|
||||
logger (>= 1.4.2)
|
||||
minitest (>= 5.1)
|
||||
mutex_m
|
||||
securerandom (>= 0.3)
|
||||
tzinfo (~> 2.0)
|
||||
acts-as-taggable-on (10.0.0)
|
||||
activerecord (>= 6.1, < 7.2)
|
||||
@@ -159,7 +171,7 @@ GEM
|
||||
angularjs-rails (1.8.0)
|
||||
arel-helpers (2.14.0)
|
||||
activerecord (>= 3.1.0, < 8)
|
||||
ast (2.4.2)
|
||||
ast (2.4.3)
|
||||
attr_required (1.0.2)
|
||||
aws-eventstream (1.3.0)
|
||||
aws-partitions (1.929.0)
|
||||
@@ -177,10 +189,11 @@ GEM
|
||||
aws-sigv4 (~> 1.8)
|
||||
aws-sigv4 (1.8.0)
|
||||
aws-eventstream (~> 1, >= 1.0.2)
|
||||
base64 (0.2.0)
|
||||
base64 (0.3.0)
|
||||
bcp47_spec (0.2.1)
|
||||
bcrypt (3.1.20)
|
||||
bigdecimal (3.1.8)
|
||||
benchmark (0.4.1)
|
||||
bigdecimal (3.2.2)
|
||||
bindata (2.5.0)
|
||||
bindex (0.8.1)
|
||||
bootsnap (1.18.3)
|
||||
@@ -188,7 +201,7 @@ GEM
|
||||
bugsnag (6.26.4)
|
||||
concurrent-ruby (~> 1.0)
|
||||
builder (3.2.4)
|
||||
bullet (7.1.6)
|
||||
bullet (8.0.8)
|
||||
activesupport (>= 3.0.0)
|
||||
uniform_notifier (~> 1.11)
|
||||
cable_ready (5.0.6)
|
||||
@@ -208,12 +221,14 @@ GEM
|
||||
rack-test (>= 0.6.3)
|
||||
regexp_parser (>= 1.5, < 3.0)
|
||||
xpath (~> 3.2)
|
||||
capybara-shadowdom (0.3.0)
|
||||
capybara
|
||||
caxlsx (3.3.0)
|
||||
htmlentities (~> 4.3, >= 4.3.4)
|
||||
marcel (~> 1.0)
|
||||
nokogiri (~> 1.10, >= 1.10.4)
|
||||
rubyzip (>= 1.3.0, < 3)
|
||||
cgi (0.3.6)
|
||||
cgi (0.3.7)
|
||||
childprocess (5.0.0)
|
||||
choice (0.2.0)
|
||||
chronic (0.10.2)
|
||||
@@ -228,8 +243,9 @@ GEM
|
||||
combine_pdf (1.0.26)
|
||||
matrix
|
||||
ruby-rc4 (>= 0.1.5)
|
||||
concurrent-ruby (1.3.1)
|
||||
connection_pool (2.4.1)
|
||||
concurrent-ruby (1.3.5)
|
||||
connection_pool (2.5.3)
|
||||
cookiejar (0.3.4)
|
||||
crack (1.0.0)
|
||||
bigdecimal
|
||||
rexml
|
||||
@@ -248,7 +264,7 @@ GEM
|
||||
database_cleaner-core (2.0.1)
|
||||
datafoodconsortium-connector (1.1.0)
|
||||
virtual_assembly-semantizer (~> 1.0, >= 1.0.5)
|
||||
date (3.3.4)
|
||||
date (3.4.1)
|
||||
debug (1.9.2)
|
||||
irb (~> 1.10)
|
||||
reline (>= 0.3.8)
|
||||
@@ -269,11 +285,25 @@ GEM
|
||||
digest (3.1.1)
|
||||
docile (1.4.0)
|
||||
dotenv (3.1.2)
|
||||
drb (2.2.3)
|
||||
em-http-request (1.1.7)
|
||||
addressable (>= 2.3.4)
|
||||
cookiejar (!= 0.3.1)
|
||||
em-socksify (>= 0.3)
|
||||
eventmachine (>= 1.0.3)
|
||||
http_parser.rb (>= 0.6.0)
|
||||
em-socksify (0.3.3)
|
||||
base64
|
||||
eventmachine (>= 1.0.0.beta.4)
|
||||
em-synchrony (1.0.6)
|
||||
eventmachine (>= 1.0.0.beta.1)
|
||||
email_validator (2.2.4)
|
||||
activemodel
|
||||
erubi (1.12.0)
|
||||
et-orbi (1.2.7)
|
||||
et-orbi (1.3.0)
|
||||
tzinfo
|
||||
eventmachine (1.2.7)
|
||||
eventmachine_httpserver (0.2.1)
|
||||
excon (0.81.0)
|
||||
execjs (2.7.0)
|
||||
factory_bot (6.2.0)
|
||||
@@ -323,8 +353,8 @@ GEM
|
||||
nokogiri (>= 1.5.11, < 2.0.0)
|
||||
foreman (0.88.1)
|
||||
formatador (0.2.5)
|
||||
fugit (1.8.1)
|
||||
et-orbi (~> 1, >= 1.2.7)
|
||||
fugit (1.11.1)
|
||||
et-orbi (~> 1, >= 1.2.11)
|
||||
raabro (~> 1.4)
|
||||
fuubar (2.5.1)
|
||||
rspec-core (~> 3.0)
|
||||
@@ -347,6 +377,7 @@ GEM
|
||||
hashie (5.0.0)
|
||||
highline (2.0.3)
|
||||
htmlentities (4.3.4)
|
||||
http_parser.rb (0.8.0)
|
||||
i18n (1.14.5)
|
||||
concurrent-ruby (~> 1.0)
|
||||
i18n-js (3.9.2)
|
||||
@@ -364,6 +395,8 @@ GEM
|
||||
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)
|
||||
@@ -406,7 +439,7 @@ GEM
|
||||
activesupport (>= 4.2)
|
||||
jwt (2.8.1)
|
||||
base64
|
||||
knapsack_pro (7.4.0)
|
||||
knapsack_pro (8.1.2)
|
||||
rake
|
||||
language_server-protocol (3.17.0.3)
|
||||
launchy (3.0.0)
|
||||
@@ -418,7 +451,8 @@ GEM
|
||||
listen (3.9.0)
|
||||
rb-fsevent (~> 0.10, >= 0.10.3)
|
||||
rb-inotify (~> 0.9, >= 0.9.10)
|
||||
loofah (2.22.0)
|
||||
logger (1.7.0)
|
||||
loofah (2.24.1)
|
||||
crass (~> 1.0.2)
|
||||
nokogiri (>= 1.12.0)
|
||||
mail (2.8.1)
|
||||
@@ -438,7 +472,7 @@ GEM
|
||||
mini_magick (4.11.0)
|
||||
mini_mime (1.1.5)
|
||||
mini_portile2 (2.8.6)
|
||||
minitest (5.23.1)
|
||||
minitest (5.25.5)
|
||||
monetize (1.13.0)
|
||||
money (~> 6.12)
|
||||
money (6.16.0)
|
||||
@@ -446,9 +480,10 @@ GEM
|
||||
msgpack (1.7.2)
|
||||
multi_json (1.15.0)
|
||||
multi_xml (0.6.0)
|
||||
mutex_m (0.3.0)
|
||||
net-http (0.4.1)
|
||||
uri
|
||||
net-imap (0.4.10)
|
||||
net-imap (0.4.20)
|
||||
date
|
||||
net-protocol
|
||||
net-pop (0.1.2)
|
||||
@@ -459,7 +494,7 @@ GEM
|
||||
net-protocol
|
||||
newrelic_rpm (9.9.0)
|
||||
nio4r (2.7.1)
|
||||
nokogiri (1.16.5)
|
||||
nokogiri (1.18.9)
|
||||
mini_portile2 (~> 2.8.2)
|
||||
racc (~> 1.4)
|
||||
nokogiri-html5-inference (0.3.0)
|
||||
@@ -495,6 +530,7 @@ GEM
|
||||
validate_url
|
||||
webfinger (~> 2.0)
|
||||
orm_adapter (0.5.0)
|
||||
ostruct (0.6.1)
|
||||
pagy (9.3.4)
|
||||
paper_trail (15.1.0)
|
||||
activerecord (>= 6.1)
|
||||
@@ -502,7 +538,7 @@ GEM
|
||||
parallel (1.24.0)
|
||||
paranoia (2.6.3)
|
||||
activerecord (>= 5.1, < 7.2)
|
||||
parser (3.3.2.0)
|
||||
parser (3.3.8.0)
|
||||
ast (~> 2.4.1)
|
||||
racc
|
||||
paypal-sdk-core (0.3.4)
|
||||
@@ -510,9 +546,9 @@ GEM
|
||||
xml-simple
|
||||
paypal-sdk-merchant (1.117.2)
|
||||
paypal-sdk-core (~> 0.3.0)
|
||||
pdf-reader (2.12.0)
|
||||
Ascii85 (~> 1.0)
|
||||
afm (~> 0.2.1)
|
||||
pdf-reader (2.15.0)
|
||||
Ascii85 (>= 1.0, < 3.0, != 2.0.0)
|
||||
afm (>= 0.2.1, < 2)
|
||||
hashery (~> 2.0)
|
||||
ruby-rc4
|
||||
ttfunk
|
||||
@@ -524,14 +560,22 @@ GEM
|
||||
psych (5.1.2)
|
||||
stringio
|
||||
public_suffix (5.0.5)
|
||||
puffing-billy (4.0.2)
|
||||
addressable (~> 2.5)
|
||||
em-http-request (~> 1.1, >= 1.1.0)
|
||||
em-synchrony
|
||||
eventmachine (~> 1.2)
|
||||
eventmachine_httpserver
|
||||
http_parser.rb (~> 0.8.0)
|
||||
multi_json
|
||||
puma (6.5.0)
|
||||
nio4r (~> 2.0)
|
||||
query_count (1.1.1)
|
||||
activerecord (>= 4.2)
|
||||
railties (>= 4.2)
|
||||
raabro (1.4.0)
|
||||
racc (1.8.0)
|
||||
rack (2.2.11)
|
||||
racc (1.8.1)
|
||||
rack (2.2.14)
|
||||
rack-mini-profiler (2.3.4)
|
||||
rack (>= 1.2.0)
|
||||
rack-oauth2 (2.2.1)
|
||||
@@ -552,20 +596,23 @@ GEM
|
||||
rack-test (2.1.0)
|
||||
rack (>= 1.3)
|
||||
rack-timeout (0.7.0)
|
||||
rails (7.0.8)
|
||||
actioncable (= 7.0.8)
|
||||
actionmailbox (= 7.0.8)
|
||||
actionmailer (= 7.0.8)
|
||||
actionpack (= 7.0.8)
|
||||
actiontext (= 7.0.8)
|
||||
actionview (= 7.0.8)
|
||||
activejob (= 7.0.8)
|
||||
activemodel (= 7.0.8)
|
||||
activerecord (= 7.0.8)
|
||||
activestorage (= 7.0.8)
|
||||
activesupport (= 7.0.8)
|
||||
rackup (1.0.1)
|
||||
rack (< 3)
|
||||
webrick
|
||||
rails (7.1.5.2)
|
||||
actioncable (= 7.1.5.2)
|
||||
actionmailbox (= 7.1.5.2)
|
||||
actionmailer (= 7.1.5.2)
|
||||
actionpack (= 7.1.5.2)
|
||||
actiontext (= 7.1.5.2)
|
||||
actionview (= 7.1.5.2)
|
||||
activejob (= 7.1.5.2)
|
||||
activemodel (= 7.1.5.2)
|
||||
activerecord (= 7.1.5.2)
|
||||
activestorage (= 7.1.5.2)
|
||||
activesupport (= 7.1.5.2)
|
||||
bundler (>= 1.15.0)
|
||||
railties (= 7.0.8)
|
||||
railties (= 7.1.5.2)
|
||||
rails-controller-testing (1.0.5)
|
||||
actionpack (>= 5.0.1.rc1)
|
||||
actionview (>= 5.0.1.rc1)
|
||||
@@ -579,20 +626,21 @@ GEM
|
||||
activesupport (>= 4.2)
|
||||
choice (~> 0.2.0)
|
||||
ruby-graphviz (~> 1.2)
|
||||
rails-html-sanitizer (1.6.0)
|
||||
rails-html-sanitizer (1.6.1)
|
||||
loofah (~> 2.21)
|
||||
nokogiri (~> 1.14)
|
||||
nokogiri (>= 1.15.7, != 1.16.7, != 1.16.6, != 1.16.5, != 1.16.4, != 1.16.3, != 1.16.2, != 1.16.1, != 1.16.0.rc1, != 1.16.0)
|
||||
rails-i18n (7.0.9)
|
||||
i18n (>= 0.7, < 2)
|
||||
railties (>= 6.0.0, < 8)
|
||||
rails_safe_tasks (1.0.0)
|
||||
railties (7.0.8)
|
||||
actionpack (= 7.0.8)
|
||||
activesupport (= 7.0.8)
|
||||
method_source
|
||||
railties (7.1.5.2)
|
||||
actionpack (= 7.1.5.2)
|
||||
activesupport (= 7.1.5.2)
|
||||
irb
|
||||
rackup (>= 1.0.0)
|
||||
rake (>= 12.2)
|
||||
thor (~> 1.0)
|
||||
zeitwerk (~> 2.5)
|
||||
thor (~> 1.0, >= 1.2.2)
|
||||
zeitwerk (~> 2.6)
|
||||
rainbow (3.1.1)
|
||||
rake (13.2.1)
|
||||
ransack (4.1.1)
|
||||
@@ -714,6 +762,7 @@ 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)
|
||||
@@ -725,6 +774,7 @@ GEM
|
||||
sprockets-rails (>= 2.0, < 4.0)
|
||||
tilt (>= 1.1, < 3)
|
||||
sd_notify (0.1.1)
|
||||
securerandom (0.4.1)
|
||||
semantic_range (3.0.0)
|
||||
shoulda-matchers (6.2.0)
|
||||
activesupport (>= 5.2.0)
|
||||
@@ -765,7 +815,7 @@ GEM
|
||||
state_machines-activerecord (0.9.0)
|
||||
activerecord (>= 6.0)
|
||||
state_machines-activemodel (>= 0.9.0)
|
||||
stimulus_reflex (3.5.3)
|
||||
stimulus_reflex (3.5.5)
|
||||
actioncable (>= 5.2)
|
||||
actionpack (>= 5.2)
|
||||
actionview (>= 5.2)
|
||||
@@ -773,6 +823,7 @@ GEM
|
||||
cable_ready (~> 5.0)
|
||||
nokogiri (~> 1.0)
|
||||
nokogiri-html5-inference (~> 0.3)
|
||||
ostruct (~> 0.6)
|
||||
rack (>= 2, < 4)
|
||||
railties (>= 5.2)
|
||||
redis (>= 4.0, < 6.0)
|
||||
@@ -788,12 +839,13 @@ GEM
|
||||
temple (0.8.2)
|
||||
terminal-table (4.0.0)
|
||||
unicode-display_width (>= 1.1.1, < 4)
|
||||
thor (1.3.1)
|
||||
thor (1.4.0)
|
||||
thread-local (1.1.0)
|
||||
tilt (2.3.0)
|
||||
timecop (0.9.8)
|
||||
timeout (0.4.1)
|
||||
ttfunk (1.7.0)
|
||||
timecop (0.9.10)
|
||||
timeout (0.4.3)
|
||||
ttfunk (1.8.0)
|
||||
bigdecimal (~> 3.1)
|
||||
turbo-rails (2.0.5)
|
||||
actionpack (>= 6.0.0)
|
||||
activejob (>= 6.0.0)
|
||||
@@ -802,9 +854,17 @@ 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)
|
||||
uniform_notifier (1.17.0)
|
||||
uri (0.13.2)
|
||||
valid_email2 (5.2.3)
|
||||
activemodel (>= 3.2)
|
||||
mail (~> 2.5)
|
||||
@@ -844,7 +904,7 @@ GEM
|
||||
rack-proxy (>= 0.6.1)
|
||||
railties (>= 5.2)
|
||||
semantic_range (>= 2.3.0)
|
||||
webrick (1.8.1)
|
||||
webrick (1.8.2)
|
||||
websocket-driver (0.7.6)
|
||||
websocket-extensions (>= 0.1.0)
|
||||
websocket-extensions (0.1.5)
|
||||
@@ -884,6 +944,7 @@ DEPENDENCIES
|
||||
cable_ready
|
||||
cancancan (~> 1.15.0)
|
||||
capybara
|
||||
capybara-shadowdom
|
||||
catalog!
|
||||
coffee-rails (~> 5.0.0)
|
||||
combine_pdf
|
||||
@@ -947,6 +1008,7 @@ DEPENDENCIES
|
||||
pg (~> 1.2.3)
|
||||
private_address_check
|
||||
pry (~> 0.13.0)
|
||||
puffing-billy
|
||||
puma
|
||||
query_count
|
||||
rack-mini-profiler (< 3.0.0)
|
||||
@@ -990,6 +1052,7 @@ DEPENDENCIES
|
||||
timecop
|
||||
turbo-rails
|
||||
turbo_power
|
||||
undercover
|
||||
valid_email2
|
||||
validates_lengths_from_database
|
||||
vcr
|
||||
|
||||
@@ -1,390 +0,0 @@
|
||||
angular.module("ofn.admin").controller "AdminProductEditCtrl", ($scope, $timeout, $filter, $http, $window, $location, BulkProducts, DisplayProperties, DirtyProducts, VariantUnitManager, StatusMessage, producers, Taxons, Columns, tax_categories, RequestMonitor, SortOptions, ErrorsParser, ProductFiltersUrl) ->
|
||||
$scope.StatusMessage = StatusMessage
|
||||
|
||||
$scope.columns = Columns.columns
|
||||
|
||||
$scope.variant_unit_options = VariantUnitManager.variantUnitOptions()
|
||||
|
||||
$scope.RequestMonitor = RequestMonitor
|
||||
$scope.pagination = BulkProducts.pagination
|
||||
$scope.per_page_options = [
|
||||
{id: 15, name: t('js.admin.orders.index.per_page', results: 15)},
|
||||
{id: 50, name: t('js.admin.orders.index.per_page', results: 50)},
|
||||
{id: 100, name: t('js.admin.orders.index.per_page', results: 100)}
|
||||
]
|
||||
|
||||
$scope.q = {
|
||||
producerFilter: ""
|
||||
categoryFilter: ""
|
||||
importDateFilter: ""
|
||||
query: ""
|
||||
sorting: ""
|
||||
}
|
||||
|
||||
$scope.sorting = "name asc"
|
||||
$scope.producers = producers
|
||||
$scope.taxons = Taxons.all
|
||||
$scope.tax_categories = tax_categories
|
||||
$scope.page = 1
|
||||
$scope.per_page = 15
|
||||
$scope.products = BulkProducts.products
|
||||
$scope.DisplayProperties = DisplayProperties
|
||||
|
||||
$scope.sortOptions = SortOptions
|
||||
|
||||
$scope.initialise = ->
|
||||
$scope.q = ProductFiltersUrl.loadFromUrl($location.search())
|
||||
$scope.fetchProducts()
|
||||
|
||||
$scope.$watchCollection '[q.query, q.producerFilter, q.categoryFilter, q.importDateFilter, per_page]', ->
|
||||
$scope.page = 1 # Reset page when changing filters for new search
|
||||
|
||||
$scope.changePage = (newPage) ->
|
||||
$scope.page = newPage
|
||||
$scope.fetchProducts()
|
||||
|
||||
$scope.fetchProducts = ->
|
||||
removeClearedValues()
|
||||
params = {
|
||||
'q[name_cont]': $scope.q.query,
|
||||
'q[variants_supplier_id_eq]': $scope.q.producerFilter,
|
||||
'q[variants_primary_taxon_id_eq]': $scope.q.categoryFilter,
|
||||
'q[s]': $scope.sorting,
|
||||
import_date: $scope.q.importDateFilter,
|
||||
page: $scope.page,
|
||||
per_page: $scope.per_page
|
||||
}
|
||||
RequestMonitor.load(BulkProducts.fetch(params).$promise).then ->
|
||||
# update url with the filters used
|
||||
$location.search(ProductFiltersUrl.generate($scope.q))
|
||||
$scope.resetProducts()
|
||||
|
||||
removeClearedValues = ->
|
||||
delete $scope.q.producerFilter if $scope.q.producerFilter == "0"
|
||||
delete $scope.q.categoryFilter if $scope.q.categoryFilter == "0"
|
||||
delete $scope.q.importDateFilter if $scope.q.importDateFilter == "0"
|
||||
|
||||
$timeout ->
|
||||
if $scope.showLatestImport
|
||||
$scope.q.importDateFilter = $scope.importDates[1].id
|
||||
|
||||
$scope.resetProducts = ->
|
||||
DirtyProducts.clear()
|
||||
StatusMessage.clear()
|
||||
|
||||
$scope.updateOnHand = (product) ->
|
||||
on_demand_variants = []
|
||||
if product.variants
|
||||
on_demand_variants = (variant for id, variant of product.variants when variant.on_demand)
|
||||
|
||||
unless product.on_demand || on_demand_variants.length > 0
|
||||
product.on_hand = $scope.onHand(product)
|
||||
|
||||
|
||||
$scope.onHand = (product) ->
|
||||
onHand = 0
|
||||
if product.hasOwnProperty("variants") and product.variants instanceof Object
|
||||
for id, variant of product.variants
|
||||
onHand = onHand + parseInt(if variant.on_hand > 0 then variant.on_hand else 0)
|
||||
else
|
||||
onHand = "error"
|
||||
onHand
|
||||
|
||||
$scope.shiftTab = (tab) ->
|
||||
$scope.visibleTab.visible = false unless $scope.visibleTab == tab || $scope.visibleTab == undefined
|
||||
tab.visible = !tab.visible
|
||||
$scope.visibleTab = tab
|
||||
|
||||
$scope.resetSelectFilters = ->
|
||||
$scope.q.query = ""
|
||||
$scope.q.producerFilter = "0"
|
||||
$scope.q.categoryFilter = "0"
|
||||
$scope.q.importDateFilter = "0"
|
||||
$scope.fetchProducts()
|
||||
|
||||
$scope.$watch 'sortOptions', (sort) ->
|
||||
return unless sort && sort.predicate != ""
|
||||
|
||||
$scope.sorting = sort.getSortingExpr(defaultDirection: "asc")
|
||||
$scope.fetchProducts()
|
||||
, true
|
||||
|
||||
confirm_unsaved_changes = () ->
|
||||
(DirtyProducts.count() > 0 and confirm(t("unsaved_changes_confirmation"))) or (DirtyProducts.count() == 0)
|
||||
|
||||
editProductUrl = (product, variant) ->
|
||||
"/admin/products/" + product.id + ((if variant then "/variants/" + variant.id else "")) + "/edit"
|
||||
|
||||
$scope.editWarn = (product, variant) ->
|
||||
if confirm_unsaved_changes()
|
||||
$window.location.href = ProductFiltersUrl.buildUrl(editProductUrl(product, variant), $scope.q)
|
||||
|
||||
$scope.toggleShowAllVariants = ->
|
||||
showVariants = !DisplayProperties.showVariants 0
|
||||
$scope.products.forEach (product) ->
|
||||
DisplayProperties.setShowVariants product.id, showVariants
|
||||
DisplayProperties.setShowVariants 0, showVariants
|
||||
|
||||
$scope.addVariant = (product) ->
|
||||
# Set new variant category to same as last product variant category to keep compactibility with deleted variant callback to set new variant category
|
||||
newVariantId = $scope.nextVariantId();
|
||||
newVariantCategoryId = product.variants[product.variants.length - 1]?.category_id
|
||||
product.variants.push
|
||||
id: newVariantId
|
||||
unit_value: null
|
||||
unit_description: null
|
||||
on_demand: false
|
||||
display_as: null
|
||||
display_name: null
|
||||
on_hand: null
|
||||
price: null
|
||||
tax_category_id: null
|
||||
category_id: newVariantCategoryId
|
||||
DisplayProperties.setShowVariants product.id, true
|
||||
DirtyProducts.addVariantProperty(product.id, newVariantId, 'category_id', newVariantCategoryId)
|
||||
|
||||
|
||||
$scope.nextVariantId = ->
|
||||
$scope.variantIdCounter = 0 unless $scope.variantIdCounter?
|
||||
$scope.variantIdCounter -= 1
|
||||
$scope.variantIdCounter
|
||||
|
||||
$scope.deleteProduct = (product) ->
|
||||
if confirm(t('are_you_sure'))
|
||||
$http(
|
||||
method: "DELETE"
|
||||
url: "/api/v0/products/" + product.id
|
||||
).then (response) ->
|
||||
$scope.products.splice $scope.products.indexOf(product), 1
|
||||
DirtyProducts.deleteProduct product.id
|
||||
$scope.displayDirtyProducts()
|
||||
|
||||
|
||||
$scope.deleteVariant = (product, variant) ->
|
||||
if product.variants.length > 1
|
||||
if !$scope.variantSaved(variant)
|
||||
$scope.removeVariant(product, variant)
|
||||
else
|
||||
if confirm(t("are_you_sure"))
|
||||
$http(
|
||||
method: "DELETE"
|
||||
url: "/api/v0/products/" + product.id + "/variants/" + variant.id
|
||||
).then (response) ->
|
||||
$scope.removeVariant(product, variant)
|
||||
else
|
||||
alert(t("delete_product_variant"))
|
||||
|
||||
$scope.removeVariant = (product, variant) ->
|
||||
product.variants.splice product.variants.indexOf(variant), 1
|
||||
DirtyProducts.deleteVariant product.id, variant.id
|
||||
$scope.displayDirtyProducts()
|
||||
|
||||
|
||||
$scope.cloneProduct = (product) ->
|
||||
BulkProducts.cloneProduct product
|
||||
|
||||
$scope.hasVariants = (product) ->
|
||||
product.variants.length > 0
|
||||
|
||||
|
||||
$scope.hasUnit = (variant) ->
|
||||
variant.variant_unit_with_scale?
|
||||
|
||||
$scope.variantSaved = (variant) ->
|
||||
variant.hasOwnProperty('id') && variant.id > 0
|
||||
|
||||
|
||||
$scope.hasOnDemandVariants = (product) ->
|
||||
(variant for id, variant of product.variants when variant.on_demand).length > 0
|
||||
|
||||
|
||||
$scope.submitProducts = ->
|
||||
# Pack pack $scope.products, so they will match the list returned from the server,
|
||||
# then pack $scope.dirtyProducts, ensuring that the correct product info is sent to the server.
|
||||
$scope.packProduct product for id, product of $scope.products
|
||||
$scope.packProduct product for id, product of DirtyProducts.all()
|
||||
|
||||
productsToSubmit = filterSubmitProducts(DirtyProducts.all())
|
||||
if productsToSubmit.length > 0
|
||||
$scope.updateProducts productsToSubmit # Don't submit an empty list
|
||||
else
|
||||
StatusMessage.display 'alert', t("products_change")
|
||||
|
||||
|
||||
$scope.updateProducts = (productsToSubmit) ->
|
||||
$scope.displayUpdating()
|
||||
$http(
|
||||
method: "POST"
|
||||
url: "/admin/products/bulk_update"
|
||||
data:
|
||||
products: productsToSubmit
|
||||
filters:
|
||||
'q[name_cont]': $scope.q.query
|
||||
'q[variants_supplier_id_eq]': $scope.q.producerFilter
|
||||
'q[variants_primary_taxon_id_eq]': $scope.q.categoryFilter
|
||||
'q[s]': $scope.sorting
|
||||
import_date: $scope.q.importDateFilter
|
||||
page: $scope.page
|
||||
per_page: $scope.per_page
|
||||
).then((response) ->
|
||||
DirtyProducts.clear()
|
||||
BulkProducts.updateVariantLists(response.data.products || [])
|
||||
$timeout -> $scope.displaySuccess()
|
||||
).catch (response) ->
|
||||
if response.status == 400 && response.data.errors?
|
||||
errorsString = ErrorsParser.toString(response.data.errors, response.status)
|
||||
$scope.displayFailure t("products_update_error") + "\n" + errorsString
|
||||
else
|
||||
$scope.displayFailure t("products_update_error_data") + response.status
|
||||
|
||||
$scope.cancel = (destination) ->
|
||||
$window.location = destination
|
||||
|
||||
$scope.packProduct = (product) ->
|
||||
if product.variants
|
||||
for id, variant of product.variants
|
||||
$scope.packVariant variant
|
||||
|
||||
|
||||
$scope.packVariant = (variant) ->
|
||||
if variant.variant_unit_with_scale
|
||||
match = variant.variant_unit_with_scale.match(/^([^_]+)_([\d\.]+)$/)
|
||||
if match
|
||||
variant.variant_unit = match[1]
|
||||
variant.variant_unit_scale = parseFloat(match[2])
|
||||
else
|
||||
variant.variant_unit = variant.variant_unit_with_scale
|
||||
variant.variant_unit_scale = null
|
||||
|
||||
if variant.hasOwnProperty("unit_value_with_description")
|
||||
match = variant.unit_value_with_description.match(/^([\d\.\,]+(?= |$)|)( |)(.*)$/)
|
||||
if match
|
||||
variant.unit_value = parseFloat(match[1].replace(",", "."))
|
||||
variant.unit_value = null if isNaN(variant.unit_value)
|
||||
if variant.unit_value && variant.variant_unit_scale
|
||||
variant.unit_value = parseFloat(window.bigDecimal.multiply(variant.unit_value, variant.variant_unit_scale, 2))
|
||||
variant.unit_description = match[3]
|
||||
|
||||
$scope.incrementLimit = ->
|
||||
if $scope.limit < $scope.products.length
|
||||
$scope.limit = $scope.limit + 5
|
||||
|
||||
|
||||
$scope.displayUpdating = ->
|
||||
StatusMessage.display 'progress', t("saving")
|
||||
|
||||
|
||||
$scope.displaySuccess = ->
|
||||
StatusMessage.display 'success',t("products_changes_saved")
|
||||
$scope.bulk_product_form.$setPristine()
|
||||
|
||||
|
||||
$scope.displayFailure = (failMessage) ->
|
||||
StatusMessage.display 'failure', t("products_update_error_msg") + " #{failMessage}"
|
||||
|
||||
|
||||
$scope.displayDirtyProducts = ->
|
||||
count = DirtyProducts.count()
|
||||
switch count
|
||||
when 0 then StatusMessage.clear()
|
||||
when 1 then StatusMessage.display 'notice', t("one_product_unsaved")
|
||||
else StatusMessage.display 'notice', t("products_unsaved", n: count)
|
||||
|
||||
|
||||
filterSubmitProducts = (productsToFilter) ->
|
||||
filteredProducts = []
|
||||
if productsToFilter instanceof Object
|
||||
angular.forEach productsToFilter, (product) ->
|
||||
if product.hasOwnProperty("id")
|
||||
filteredProduct = {id: product.id}
|
||||
filteredVariants = []
|
||||
hasUpdatableProperty = false
|
||||
|
||||
if product.hasOwnProperty("variants")
|
||||
angular.forEach product.variants, (variant) ->
|
||||
result = filterSubmitVariant variant
|
||||
filteredVariant = result.filteredVariant
|
||||
variantHasUpdatableProperty = result.hasUpdatableProperty
|
||||
filteredVariants.push filteredVariant if variantHasUpdatableProperty
|
||||
|
||||
if product.hasOwnProperty("name")
|
||||
filteredProduct.name = product.name
|
||||
hasUpdatableProperty = true
|
||||
if product.hasOwnProperty("price")
|
||||
filteredProduct.price = product.price
|
||||
hasUpdatableProperty = true
|
||||
if product.hasOwnProperty("on_hand") and filteredVariants.length == 0 #only update if no variants present
|
||||
filteredProduct.on_hand = product.on_hand
|
||||
hasUpdatableProperty = true
|
||||
if product.hasOwnProperty("on_demand") and filteredVariants.length == 0 #only update if no variants present
|
||||
filteredProduct.on_demand = product.on_demand
|
||||
hasUpdatableProperty = true
|
||||
if product.hasOwnProperty("inherits_properties")
|
||||
filteredProduct.inherits_properties = product.inherits_properties
|
||||
hasUpdatableProperty = true
|
||||
if filteredVariants.length > 0 # Note that the name of the property changes to enable mass assignment of variants attributes with rails
|
||||
filteredProduct.variants_attributes = filteredVariants
|
||||
hasUpdatableProperty = true
|
||||
filteredProducts.push filteredProduct if hasUpdatableProperty
|
||||
|
||||
filteredProducts
|
||||
|
||||
|
||||
filterSubmitVariant = (variant) ->
|
||||
hasUpdatableProperty = false
|
||||
filteredVariant = {}
|
||||
if not variant.deleted_at? and variant.hasOwnProperty("id")
|
||||
filteredVariant.id = variant.id unless variant.id <= 0
|
||||
if variant.hasOwnProperty("sku")
|
||||
filteredVariant.sku = variant.sku
|
||||
hasUpdatableProperty = true
|
||||
if variant.hasOwnProperty("on_hand")
|
||||
filteredVariant.on_hand = variant.on_hand
|
||||
hasUpdatableProperty = true
|
||||
if variant.hasOwnProperty("on_demand")
|
||||
filteredVariant.on_demand = variant.on_demand
|
||||
hasUpdatableProperty = true
|
||||
if variant.hasOwnProperty("price")
|
||||
filteredVariant.price = variant.price
|
||||
hasUpdatableProperty = true
|
||||
if variant.hasOwnProperty("unit_value")
|
||||
filteredVariant.unit_value = variant.unit_value
|
||||
hasUpdatableProperty = true
|
||||
if variant.hasOwnProperty("unit_description")
|
||||
filteredVariant.unit_description = variant.unit_description
|
||||
hasUpdatableProperty = true
|
||||
if variant.hasOwnProperty("display_name")
|
||||
filteredVariant.display_name = variant.display_name
|
||||
hasUpdatableProperty = true
|
||||
if variant.hasOwnProperty("tax_category_id")
|
||||
filteredVariant.tax_category_id = variant.tax_category_id
|
||||
hasUpdatableProperty = true
|
||||
if variant.hasOwnProperty("category_id")
|
||||
filteredVariant.primary_taxon_id = variant.category_id
|
||||
hasUpdatableProperty = true
|
||||
if variant.hasOwnProperty("display_as")
|
||||
filteredVariant.display_as = variant.display_as
|
||||
hasUpdatableProperty = true
|
||||
if variant.hasOwnProperty("producer_id")
|
||||
filteredVariant.supplier_id = variant.producer_id
|
||||
hasUpdatableProperty = true
|
||||
if variant.hasOwnProperty("variant_unit_with_scale")
|
||||
filteredVariant.variant_unit = variant.variant_unit
|
||||
filteredVariant.variant_unit_scale = variant.variant_unit_scale
|
||||
hasUpdatableProperty = true
|
||||
if variant.hasOwnProperty("variant_unit_name")
|
||||
filteredVariant.variant_unit_name = variant.variant_unit_name
|
||||
hasUpdatableProperty = true
|
||||
|
||||
{filteredVariant: filteredVariant, hasUpdatableProperty: hasUpdatableProperty}
|
||||
|
||||
|
||||
toObjectWithIDKeys = (array) ->
|
||||
object = {}
|
||||
|
||||
for i of array
|
||||
if array[i] instanceof Object and array[i].hasOwnProperty("id")
|
||||
object[array[i].id] = angular.copy(array[i])
|
||||
object[array[i].id].variants = toObjectWithIDKeys(array[i].variants) if array[i].hasOwnProperty("variants") and array[i].variants instanceof Array
|
||||
|
||||
object
|
||||
@@ -55,12 +55,6 @@ 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,18 +19,6 @@ 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"))
|
||||
@@ -75,11 +63,10 @@ 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,
|
||||
@@ -87,7 +74,8 @@ 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
|
||||
"per_page": $scope.per_page,
|
||||
"search_query": $scope.query
|
||||
)
|
||||
|
||||
$scope.formatDates = (startDate, endDate) ->
|
||||
@@ -97,7 +85,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(90,'days').format()}")
|
||||
RequestMonitor.load $scope.orderCycles = OrderCycles.index(ams_prefix: "basic", as: "distributor", "q[orders_close_at_gt]": "#{moment().subtract(1,'year').format()}")
|
||||
RequestMonitor.load $scope.suppliers = Enterprises.index(action: "visible", ams_prefix: "basic", "q[is_primary_producer_eq]": "true")
|
||||
|
||||
$scope.dereferenceLoadedData = ->
|
||||
|
||||
@@ -5,6 +5,8 @@ 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)
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
angular.module("ofn.admin").controller "ProductImageCtrl", ($scope, ProductImageService) ->
|
||||
$scope.imageUploader = ProductImageService.imageUploader
|
||||
$scope.imagePreview = ProductImageService.imagePreview
|
||||
|
||||
$scope.$watch 'product.image_url', (newValue, oldValue) ->
|
||||
if newValue != oldValue
|
||||
$scope.imagePreview = newValue
|
||||
$scope.uploadModal.close()
|
||||
@@ -1,6 +0,0 @@
|
||||
angular.module("ofn.admin").directive "imageModal", ($modal, ProductImageService) ->
|
||||
restrict: 'C'
|
||||
link: (scope, elem, attrs, ctrl) ->
|
||||
elem.on "click", (ev) =>
|
||||
scope.uploadModal = $modal.open(templateUrl: 'admin/modals/image_upload.html', controller: ctrl, scope: scope, windowClass: 'simple-modal')
|
||||
ProductImageService.configure(scope.product)
|
||||
@@ -8,10 +8,4 @@ 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'
|
||||
})
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
angular.module("admin.resources").factory 'ProductResource', ($resource) ->
|
||||
$resource('/admin/product/:id/:action.json', {}, {
|
||||
'index':
|
||||
url: '/api/v0/products/bulk_products.json'
|
||||
method: 'GET'
|
||||
})
|
||||
@@ -39,17 +39,6 @@ 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]
|
||||
|
||||
@@ -61,5 +50,3 @@ angular.module("admin.resources").factory 'Enterprises', ($q, $filter, Enterpris
|
||||
$filter('filter')(enterprises, term)
|
||||
|
||||
|
||||
removeLogo: performActionOnEnterpriseResource(EnterpriseResource.removeLogo)
|
||||
removePromoImage: performActionOnEnterpriseResource(EnterpriseResource.removePromoImage)
|
||||
|
||||
@@ -1,76 +0,0 @@
|
||||
angular.module("ofn.admin").factory "BulkProducts", (ProductResource, dataFetcher, $http) ->
|
||||
new class BulkProducts
|
||||
products: []
|
||||
pagination: {}
|
||||
|
||||
fetch: (params) ->
|
||||
ProductResource.index params, (data) =>
|
||||
@products.length = 0
|
||||
@addProducts data.products
|
||||
angular.extend(@pagination, data.pagination)
|
||||
|
||||
cloneProduct: (product) ->
|
||||
$http.post("/api/v0/products/" + product.id + "/clone").then (response) =>
|
||||
dataFetcher("/api/v0/products/" + response.data.id + "?template=bulk_show").then (newProduct) =>
|
||||
@unpackProduct newProduct
|
||||
@insertProductAfter(product, newProduct)
|
||||
|
||||
updateVariantLists: (serverProducts) ->
|
||||
for server_product in serverProducts
|
||||
product = @findProductInList(server_product.id, @products)
|
||||
product.variants = server_product.variants
|
||||
@loadVariantUnitValues product.variants
|
||||
|
||||
find: (id) ->
|
||||
@findProductInList id, @products
|
||||
|
||||
findProductInList: (id, product_list) ->
|
||||
products = (product for product in product_list when product.id == id)
|
||||
if products.length == 0 then null else products[0]
|
||||
|
||||
addProducts: (products) ->
|
||||
for product in products
|
||||
@unpackProduct product
|
||||
@products.push product
|
||||
|
||||
insertProductAfter: (product, newProduct) ->
|
||||
index = @products.indexOf(product)
|
||||
@products.splice(index + 1, 0, newProduct)
|
||||
|
||||
unpackProduct: (product) ->
|
||||
@loadVariantUnit product
|
||||
|
||||
loadVariantUnit: (product) ->
|
||||
@loadVariantUnitValues product.variants if product.variants
|
||||
|
||||
loadVariantUnitValues: (variants) ->
|
||||
for variant in variants
|
||||
@loadVariantUnitValue variant
|
||||
|
||||
loadVariantUnitValue: (variant) ->
|
||||
variant.variant_unit_with_scale =
|
||||
if variant.variant_unit && variant.variant_unit_scale && variant.variant_unit != 'items'
|
||||
"#{variant.variant_unit}_#{variant.variant_unit_scale}"
|
||||
else if variant.variant_unit
|
||||
variant.variant_unit
|
||||
else
|
||||
null
|
||||
|
||||
unit_value = @variantUnitValue variant
|
||||
unit_value = if unit_value? then unit_value else ''
|
||||
variant.unit_value_with_description = "#{unit_value} #{variant.unit_description || ''}".trim()
|
||||
|
||||
variantUnitValue: (variant) ->
|
||||
if variant.unit_value?
|
||||
if variant.variant_unit_scale
|
||||
variant_unit_value = @divideAsInteger variant.unit_value, variant.variant_unit_scale
|
||||
parseFloat(window.bigDecimal.round(variant_unit_value, 2))
|
||||
else
|
||||
variant.unit_value
|
||||
else
|
||||
null
|
||||
|
||||
# forces integer division to avoid javascript floating point imprecision
|
||||
# using one billion as the multiplier so that it works for numbers with up to 9 decimal places
|
||||
divideAsInteger: (a, b) ->
|
||||
(a * 1000000000) / (b * 1000000000)
|
||||
@@ -1,4 +1,4 @@
|
||||
angular.module("admin.tagRules").directive 'newTagRuleDialog', ($rootScope, $compile, $templateCache, DialogDefaults) ->
|
||||
angular.module("admin.tagRules").directive 'newTagRuleDialog', ($rootScope, $compile, $templateCache, DialogDefaults, ruleTypes) ->
|
||||
restrict: 'A'
|
||||
scope:
|
||||
tagGroup: '='
|
||||
@@ -7,12 +7,7 @@ angular.module("admin.tagRules").directive 'newTagRuleDialog', ($rootScope, $com
|
||||
# Compile modal template
|
||||
template = $compile($templateCache.get('admin/new_tag_rule_dialog.html'))(scope)
|
||||
|
||||
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.ruleTypes = ruleTypes
|
||||
|
||||
scope.ruleType = scope.ruleTypes[0].id
|
||||
|
||||
|
||||
@@ -26,6 +26,8 @@ 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
|
||||
|
||||
@@ -3,12 +3,14 @@
|
||||
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"))
|
||||
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
|
||||
attr_reader :f, :method, :tags, :placeholder, :aria_label_option
|
||||
end
|
||||
|
||||
@@ -9,11 +9,11 @@
|
||||
.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"
|
||||
×
|
||||
= 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
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
li.tag-item {
|
||||
border-radius: 3px;
|
||||
margin: 2px 0 2px 3px;
|
||||
padding: 0 5px;
|
||||
padding: 0 0 0 5px;
|
||||
display: inline-block;
|
||||
float: left;
|
||||
font-size: 14px;
|
||||
@@ -42,16 +42,18 @@
|
||||
background-color: $teal;
|
||||
|
||||
.remove-button {
|
||||
margin: 0 0 0 5px;
|
||||
padding: 0;
|
||||
border: none;
|
||||
border-left: 1px solid darken($teal, 5);
|
||||
margin-left: 2px;
|
||||
padding: 0 6px;
|
||||
background: 0 0;
|
||||
cursor: pointer;
|
||||
vertical-align: middle;
|
||||
font:
|
||||
700 16px Arial,
|
||||
sans-serif;
|
||||
font-size: 14px;
|
||||
color: white;
|
||||
|
||||
&:hover {
|
||||
background: rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ module Admin
|
||||
@line_items = order_permissions.
|
||||
editable_line_items.where(order_id: orders).
|
||||
includes(:variant).
|
||||
ransack(params[:q]).result.order(:id)
|
||||
ransack(line_items_search_query).result.order(:id)
|
||||
|
||||
@pagy, @line_items = pagy(@line_items) if pagination_required?
|
||||
|
||||
@@ -88,5 +88,27 @@ 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 = Hash[permitted_params[:column_preferences].
|
||||
each_with_index.map { |cp, i| [i, cp] }]
|
||||
collection_attributes = permitted_params[:column_preferences].
|
||||
each_with_index.to_h { |cp, i| [i, cp] }
|
||||
collection_attributes.select!{ |_i, cp|
|
||||
cp[:action_name] == permitted_params[:action_name]
|
||||
}
|
||||
|
||||
@@ -48,6 +48,9 @@ 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]
|
||||
@@ -69,13 +72,15 @@ module Admin
|
||||
delete_custom_tab if params[:custom_tab] == 'false'
|
||||
|
||||
if @object.update(enterprise_params)
|
||||
flash[:success] = flash_message_for(@object, :successfully_updated)
|
||||
flash[:success] = flash_success_message
|
||||
|
||||
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|
|
||||
@@ -164,6 +169,25 @@ 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?
|
||||
|
||||
@@ -254,7 +278,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 do |_i, attrs|
|
||||
tag_rules_attributes.select{ |_i, attrs| attrs[:type].present? }.each_value do |attrs|
|
||||
rule = @object.tag_rules.find_by(id: attrs.delete(:id)) ||
|
||||
attrs[:type].constantize.new(enterprise: @object)
|
||||
|
||||
@@ -293,7 +317,7 @@ module Admin
|
||||
def check_can_change_bulk_sells
|
||||
return if spree_current_user.admin?
|
||||
|
||||
params[:sets_enterprise_set][:collection_attributes].each do |_i, enterprise_params|
|
||||
params[:sets_enterprise_set][:collection_attributes].each_value do |enterprise_params|
|
||||
unless spree_current_user == Enterprise.find_by(id: enterprise_params[:id]).owner
|
||||
enterprise_params.delete :sells
|
||||
end
|
||||
@@ -327,7 +351,7 @@ module Admin
|
||||
def check_can_change_bulk_owner
|
||||
return if spree_current_user.admin?
|
||||
|
||||
bulk_params[:collection_attributes].each do |_i, enterprise_params|
|
||||
bulk_params[:collection_attributes].each_value do |enterprise_params|
|
||||
enterprise_params.delete :owner_id
|
||||
end
|
||||
end
|
||||
@@ -354,6 +378,19 @@ 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,7 +17,10 @@ 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)
|
||||
@@ -36,7 +39,22 @@ module Admin
|
||||
def save_data
|
||||
return unless process_data('save')
|
||||
|
||||
render json: @importer.save_results
|
||||
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:
|
||||
end
|
||||
|
||||
def reset_absent_products
|
||||
@@ -154,5 +172,15 @@ 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,7 +10,8 @@ module Admin
|
||||
|
||||
def index
|
||||
fetch_products
|
||||
render "index", locals: { producers:, categories:, tax_category_options:, flash: }
|
||||
render "index",
|
||||
locals: { producers:, categories:, tax_category_options:, available_tags:, flash: }
|
||||
|
||||
session[:products_return_to_url] = request.url
|
||||
end
|
||||
@@ -30,7 +31,9 @@ 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:, flash: }
|
||||
locals: {
|
||||
producers:, categories:, tax_category_options:, available_tags:, flash:
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
@@ -112,6 +115,7 @@ 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
|
||||
@@ -135,9 +139,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).ransack(ransack_query).result
|
||||
.editable_products.merge(product_scope_with_includes).ransack(ransack_query).result
|
||||
|
||||
@pagy, @products = pagy(product_query.order(:name), limit: @per_page, page: @page,
|
||||
size: [1, 2, 2, 1])
|
||||
end
|
||||
@@ -150,7 +167,11 @@ module Admin
|
||||
Spree::Product.active
|
||||
end
|
||||
|
||||
scope.includes(product_query_includes).distinct
|
||||
scope.distinct
|
||||
end
|
||||
|
||||
def product_scope_with_includes
|
||||
product_scope.includes(product_query_includes)
|
||||
end
|
||||
|
||||
def ransack_query
|
||||
@@ -160,6 +181,7 @@ 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
|
||||
@@ -176,6 +198,7 @@ module Admin
|
||||
:stock_items,
|
||||
:tax_category,
|
||||
:supplier,
|
||||
:taggings,
|
||||
] },
|
||||
]
|
||||
end
|
||||
|
||||
@@ -53,7 +53,9 @@ 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
|
||||
prepend_before_action :load_data, if: :spree_current_user
|
||||
before_action :load_collection, only: [:bulk_update]
|
||||
before_action :load_spree_api_key, only: :index
|
||||
|
||||
@@ -70,7 +70,7 @@ module Admin
|
||||
end
|
||||
|
||||
def load_collection
|
||||
collection_hash = Hash[variant_overrides_params.each_with_index.map { |vo, i| [i, vo] }]
|
||||
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|
|
||||
|
||||
@@ -22,7 +22,8 @@ module Api
|
||||
distributor,
|
||||
order_cycle,
|
||||
customer,
|
||||
search_params
|
||||
search_params,
|
||||
inventory_enabled:
|
||||
).products_json
|
||||
|
||||
render plain: products
|
||||
@@ -95,9 +96,13 @@ module Api
|
||||
|
||||
def distributed_products
|
||||
OrderCycles::DistributedProductsService.new(
|
||||
distributor, order_cycle, customer
|
||||
distributor, order_cycle, customer, inventory_enabled:
|
||||
).products_relation.pluck(:id)
|
||||
end
|
||||
|
||||
def inventory_enabled
|
||||
OpenFoodNetwork::FeatureToggle.enabled?(:inventory, distributor)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -112,7 +112,9 @@ module Api
|
||||
|
||||
def scoped_variant(variant_id)
|
||||
variant = Spree::Variant.find(variant_id)
|
||||
|
||||
OpenFoodNetwork::ScopeVariantToHub.new(@order.distributor).scope(variant)
|
||||
|
||||
variant
|
||||
end
|
||||
|
||||
|
||||
@@ -54,7 +54,7 @@ module Api
|
||||
def error_during_processing(exception)
|
||||
Alert.raise(exception)
|
||||
|
||||
if Rails.env.development? || Rails.env.test?
|
||||
if Rails.env.local?
|
||||
render status: :unprocessable_entity,
|
||||
json: json_api_error(exception.message, meta: exception.backtrace)
|
||||
else
|
||||
|
||||
@@ -80,8 +80,6 @@ class CheckoutController < BaseController
|
||||
|
||||
@order.customer.touch :terms_and_conditions_accepted_at
|
||||
|
||||
return true if redirect_to_payment_gateway
|
||||
|
||||
# Redeem VINE voucher
|
||||
vine_voucher_redeemer = Vine::VoucherRedeemerService.new(order: @order)
|
||||
unless vine_voucher_redeemer.redeem
|
||||
@@ -94,6 +92,9 @@ class CheckoutController < BaseController
|
||||
return false
|
||||
# rubocop:enable Rails/DeprecatedActiveModelErrorsMethods
|
||||
end
|
||||
|
||||
return true if redirect_to_payment_gateway
|
||||
|
||||
@order.process_payments!
|
||||
@order.confirm!
|
||||
BackorderJob.check_stock(@order)
|
||||
|
||||
@@ -48,7 +48,8 @@ module CheckoutCallbacks
|
||||
end
|
||||
|
||||
def load_saved_addresses
|
||||
finder = OpenFoodNetwork::AddressFinder.new(@order.email, @order.customer, spree_current_user)
|
||||
finder = OpenFoodNetwork::AddressFinder.new(email: @order.email, customer: @order.customer,
|
||||
user: spree_current_user)
|
||||
|
||||
@order.bill_address ||= finder.bill_address
|
||||
@order.ship_address ||= finder.ship_address
|
||||
|
||||
@@ -24,7 +24,7 @@ module PaymentGateways
|
||||
|
||||
result = ProcessPaymentIntent.new(params["payment_intent"], @order).call!
|
||||
|
||||
unless result.ok?
|
||||
unless result.success?
|
||||
flash.now[:error] = "#{I18n.t('payment_could_not_process')}. #{result.error}"
|
||||
end
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ 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
|
||||
@@ -161,6 +162,13 @@ 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?
|
||||
|
||||
|
||||
@@ -19,11 +19,6 @@ module Spree
|
||||
before_action :load_spree_api_key, only: [:index, :variant_overrides]
|
||||
before_action :strip_new_properties, only: [:create, :update]
|
||||
|
||||
def index
|
||||
@current_user = spree_current_user
|
||||
@show_latest_import = params[:latest_import] || false
|
||||
end
|
||||
|
||||
def show
|
||||
session[:return_to] ||= request.referer
|
||||
redirect_to( action: :edit )
|
||||
@@ -65,28 +60,6 @@ module Spree
|
||||
end
|
||||
end
|
||||
|
||||
def bulk_update
|
||||
product_set = product_set_from_params
|
||||
|
||||
product_set.collection.each { |p| authorize! :update, p }
|
||||
|
||||
if product_set.save
|
||||
redirect_to main_app.bulk_products_api_v0_products_path(bulk_index_query)
|
||||
elsif product_set.errors.present?
|
||||
render json: { errors: product_set.errors }, status: :bad_request
|
||||
else
|
||||
render body: nil, status: :internal_server_error
|
||||
end
|
||||
end
|
||||
|
||||
def clone
|
||||
@new = @product.duplicate
|
||||
raise "Clone failed" unless @new.save
|
||||
|
||||
flash[:success] = t('.success')
|
||||
redirect_to spree.admin_products_url
|
||||
end
|
||||
|
||||
def group_buy_options
|
||||
@url_filters = ::ProductFilters.new.extract(request.query_parameters)
|
||||
end
|
||||
@@ -134,9 +107,9 @@ module Spree
|
||||
end
|
||||
|
||||
def product_set_from_params
|
||||
collection_hash = Hash[products_bulk_params[:products].each_with_index.map { |p, i|
|
||||
[i, p]
|
||||
} ]
|
||||
collection_hash = products_bulk_params[:products].each_with_index.to_h { |p, i|
|
||||
[i, p]
|
||||
}
|
||||
Sets::ProductSet.new(collection_attributes: collection_hash)
|
||||
end
|
||||
|
||||
|
||||
@@ -104,7 +104,7 @@ module Spree
|
||||
|
||||
return unless shipping_fees
|
||||
|
||||
shipping_fees.each do |_, shipping_amount|
|
||||
shipping_fees.each_value 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
|
||||
|
||||
@@ -117,7 +117,7 @@ module Spree
|
||||
def variant_search_params
|
||||
params.permit(
|
||||
:q, :distributor_id, :order_cycle_id, :schedule_id, :eligible_for_subscriptions,
|
||||
:include_out_of_stock
|
||||
:include_out_of_stock, :search_variants_as, :order_id
|
||||
).to_h.with_indifferent_access
|
||||
end
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ module Spree
|
||||
|
||||
layout 'darkswarm'
|
||||
|
||||
rescue_from ActiveRecord::RecordNotFound, with: :render_404
|
||||
rescue_from ActiveRecord::RecordNotFound, with: :render404
|
||||
helper 'spree/orders'
|
||||
|
||||
respond_to :html, :json
|
||||
|
||||
@@ -5,7 +5,7 @@ class VoucherAdjustmentsController < BaseController
|
||||
|
||||
def create
|
||||
if voucher_params[:voucher_code].blank?
|
||||
@order.errors.add(:voucher_code, I18n.t('checkout.errors.voucher_not_found'))
|
||||
@order.errors.add(:voucher_code, I18n.t('checkout.errors.voucher_code_blank'))
|
||||
return render_error
|
||||
end
|
||||
|
||||
@@ -43,7 +43,7 @@ class VoucherAdjustmentsController < BaseController
|
||||
return false if @order.errors.present?
|
||||
|
||||
if voucher.nil?
|
||||
@order.errors.add(:voucher_code, I18n.t('checkout.errors.voucher_not_found'))
|
||||
@order.errors.add(:voucher_code, I18n.t('checkout.errors.voucher_code_not_found'))
|
||||
return false
|
||||
end
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ class EnterpriseFeesBulkUpdate
|
||||
private
|
||||
|
||||
def check_enterprise_fee_input
|
||||
enterprise_fee_bulk_params['collection_attributes'].each do |_, fee_row|
|
||||
enterprise_fee_bulk_params['collection_attributes'].each_value 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 do |_, enterprise_amount|
|
||||
enterprise_fees.each_value 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 do |_, enterprise_fee|
|
||||
enterprise_fee_bulk_params['collection_attributes'].each_value do |enterprise_fee|
|
||||
next unless enterprise_fee['inherits_tax_category'] == "true"
|
||||
next unless EnterpriseFee::PER_ORDER_CALCULATORS.include?(enterprise_fee['calculator_type'])
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ module Admin
|
||||
enterprise.in?(spree_current_user.enterprises)
|
||||
end
|
||||
|
||||
def enterprise_side_menu_items(enterprise)
|
||||
def enterprise_side_menu_items(enterprise) # rubocop:disable Metrics/CyclomaticComplexity
|
||||
is_shop = enterprise.sells != "none"
|
||||
show_properties = !!enterprise.is_primary_producer
|
||||
show_shipping_methods = can?(:manage_shipping_methods, enterprise) && is_shop
|
||||
@@ -26,34 +26,54 @@ module Admin
|
||||
show_enterprise_fees = can?(:manage_enterprise_fees,
|
||||
enterprise) && (is_shop || enterprise.is_primary_producer)
|
||||
show_connected_apps = can?(:manage_connected_apps, enterprise) &&
|
||||
feature?(:connected_apps, spree_current_user, enterprise) &&
|
||||
Spree::Config.connected_apps_enabled.present?
|
||||
(connected_apps_enabled(enterprise).present? ||
|
||||
dfc_platforms_available?)
|
||||
show_inventory_settings = feature?(:inventory, spree_current_user.enterprises) && is_shop
|
||||
|
||||
build_enterprise_side_menu_items(
|
||||
is_shop:,
|
||||
show_options = {
|
||||
show_properties:,
|
||||
show_shipping_methods:,
|
||||
show_payment_methods:,
|
||||
show_enterprise_fees:,
|
||||
show_connected_apps:,
|
||||
)
|
||||
show_inventory_settings:,
|
||||
}
|
||||
|
||||
build_enterprise_side_menu_items(is_shop:, show_options:)
|
||||
end
|
||||
|
||||
def connected_apps_enabled
|
||||
def connected_apps_enabled(enterprise)
|
||||
return [] unless feature?(:connected_apps, spree_current_user, enterprise)
|
||||
|
||||
connected_apps_enabled = Spree::Config.connected_apps_enabled&.split(',') || []
|
||||
ConnectedApp::TYPES & connected_apps_enabled
|
||||
end
|
||||
|
||||
def dfc_platforms_available?
|
||||
DfcProvider::PlatformsController::PLATFORM_IDS.keys.any? do |id|
|
||||
feature?(id, spree_current_user)
|
||||
end
|
||||
end
|
||||
|
||||
def enterprise_attachment_removal_modal_id
|
||||
attachment_removal_parameter # remove_logo|remove_promo_image|remove_white_label_logo
|
||||
end
|
||||
|
||||
def enterprise_attachment_removal_panel
|
||||
if attachment_removal_parameter == "remove_white_label_logo"
|
||||
"white_label"
|
||||
elsif ["remove_logo", "remove_promo_image"].include?(attachment_removal_parameter)
|
||||
"images"
|
||||
end
|
||||
end
|
||||
|
||||
def enterprise_attachment_removal_panel_id
|
||||
"#{enterprise_attachment_removal_panel}_panel"
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def build_enterprise_side_menu_items(
|
||||
is_shop:,
|
||||
show_properties:,
|
||||
show_shipping_methods:,
|
||||
show_payment_methods:,
|
||||
show_enterprise_fees:,
|
||||
show_connected_apps:
|
||||
)
|
||||
def build_enterprise_side_menu_items(is_shop:, show_options: ) # rubocop:disable Metrics/MethodLength
|
||||
[
|
||||
{ name: 'primary_details', icon_class: "icon-home", show: true, selected: 'selected' },
|
||||
{ name: 'address', icon_class: "icon-map-marker", show: true },
|
||||
@@ -62,19 +82,24 @@ module Admin
|
||||
{ name: 'about', icon_class: "icon-pencil", show: true, form_name: "about_us" },
|
||||
{ name: 'business_details', icon_class: "icon-briefcase", show: true },
|
||||
{ name: 'images', icon_class: "icon-picture", show: true },
|
||||
{ name: 'properties', icon_class: "icon-tags", show: show_properties },
|
||||
{ name: 'shipping_methods', icon_class: "icon-truck", show: show_shipping_methods },
|
||||
{ name: 'payment_methods', icon_class: "icon-money", show: show_payment_methods },
|
||||
{ name: 'enterprise_fees', icon_class: "icon-tasks", show: show_enterprise_fees },
|
||||
{ name: 'properties', icon_class: "icon-tags", show: show_options[:show_properties] },
|
||||
{ name: 'shipping_methods', icon_class: "icon-truck",
|
||||
show: show_options[:show_shipping_methods] },
|
||||
{ name: 'payment_methods', icon_class: "icon-money",
|
||||
show: show_options[:show_payment_methods] },
|
||||
{ name: 'enterprise_fees', icon_class: "icon-tasks",
|
||||
show: show_options[:show_enterprise_fees] },
|
||||
{ name: 'vouchers', icon_class: "icon-ticket", show: is_shop },
|
||||
{ name: 'enterprise_permissions', icon_class: "icon-plug", show: true,
|
||||
href: admin_enterprise_relationships_path },
|
||||
{ name: 'inventory_settings', icon_class: "icon-list-ol", show: is_shop },
|
||||
{ name: 'inventory_settings', icon_class: "icon-list-ol",
|
||||
show: show_options[:show_inventory_settings] },
|
||||
{ name: 'tag_rules', icon_class: "icon-random", show: is_shop },
|
||||
{ name: 'shop_preferences', icon_class: "icon-shopping-cart", show: is_shop },
|
||||
{ name: 'white_label', icon_class: "icon-leaf", show: true },
|
||||
{ name: 'users', icon_class: "icon-user", show: true },
|
||||
{ name: 'connected_apps', icon_class: "icon-puzzle-piece", show: show_connected_apps },
|
||||
{ name: 'connected_apps', icon_class: "icon-puzzle-piece",
|
||||
show: show_options[:show_connected_apps] },
|
||||
]
|
||||
end
|
||||
end
|
||||
|
||||
@@ -32,12 +32,8 @@ module Admin
|
||||
[precised_unit_value, variant.unit_description].compact_blank.join(" ")
|
||||
end
|
||||
|
||||
def products_return_to_url(url_filters)
|
||||
if feature?(:admin_style_v3, spree_current_user)
|
||||
return session[:products_return_to_url] || admin_products_url
|
||||
end
|
||||
|
||||
"#{admin_products_path}#{url_filters.empty? ? '' : "#?#{url_filters.to_query}"}"
|
||||
def products_return_to_url
|
||||
session[:products_return_to_url] || admin_products_url
|
||||
end
|
||||
|
||||
# if user hasn't saved any preferences on products page and there's only one producer;
|
||||
|
||||
@@ -45,6 +45,11 @@ module ApplicationHelper
|
||||
form_for(name, *(args << options.merge(builder: AngularFormBuilder)), &)
|
||||
end
|
||||
|
||||
def respond_to_missing?(method_name, include_private = false)
|
||||
(method_name.to_s.end_with?('_path',
|
||||
'_url') && spree.respond_to?(method_name, include_private)) || super
|
||||
end
|
||||
|
||||
# Pass URL helper calls on to spree where applicable so that we don't need to use
|
||||
# spree.foo_path in any view rendered from non-spree-namespaced controllers.
|
||||
def method_missing(method, *args, &)
|
||||
|
||||
@@ -5,10 +5,6 @@ module CheckoutHelper
|
||||
order.ship_address == order.bill_address
|
||||
end
|
||||
|
||||
def guest_checkout_allowed?
|
||||
current_order.distributor.allow_guest_orders?
|
||||
end
|
||||
|
||||
def checkout_adjustments_for(order, opts = {})
|
||||
exclude = opts[:exclude] || {}
|
||||
reject_zero_amount = opts.fetch(:reject_zero_amount, true)
|
||||
|
||||
@@ -29,13 +29,7 @@ module Spree
|
||||
scope: [:admin, :tab]).capitalize
|
||||
|
||||
css_classes = []
|
||||
|
||||
if options[:icon] && !feature?(:admin_style_v3, spree_current_user)
|
||||
link = link_to_with_icon(options[:icon], titleized_label, destination_url)
|
||||
css_classes << 'tab-with-icon'
|
||||
else
|
||||
link = link_to(titleized_label, destination_url)
|
||||
end
|
||||
link = link_to(titleized_label, destination_url)
|
||||
|
||||
selected = if options[:match_path]
|
||||
PathChecker
|
||||
|
||||
@@ -155,8 +155,7 @@ module Spree
|
||||
end
|
||||
|
||||
def filter_by_supplier?(order)
|
||||
order.distributor&.enable_producers_to_edit_orders &&
|
||||
spree_current_user.can_manage_line_items_in_orders_only?
|
||||
can? :edit_as_producer_only, order
|
||||
end
|
||||
|
||||
def display_value_for_producer(order, value)
|
||||
|
||||
@@ -45,5 +45,9 @@ module Spree
|
||||
shop: current_distributor.name,
|
||||
oc_close: l(current_order_cycle.orders_close_at, format: "%A, %b %d, %Y @ %H:%M"))
|
||||
end
|
||||
|
||||
def format_unit_price(unit_price)
|
||||
"#{Spree::Money.new(unit_price[:amount]).to_html} / #{unit_price[:unit]}".html_safe # rubocop:disable Rails/OutputSafety
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -5,7 +5,7 @@ class OrderCycleNotificationJob < ApplicationJob
|
||||
def perform(order_cycle_id)
|
||||
order_cycle = OrderCycle.find(order_cycle_id)
|
||||
order_cycle.suppliers.each do |supplier|
|
||||
ProducerMailer.order_cycle_report(supplier, order_cycle).deliver_now
|
||||
ProducerMailer.order_cycle_report(supplier, order_cycle).deliver_later
|
||||
end
|
||||
order_cycle.update_columns mails_sent: true
|
||||
end
|
||||
|
||||
@@ -59,7 +59,7 @@ class ProducerMailer < ApplicationMailer
|
||||
end
|
||||
|
||||
def line_items_from(order_cycle, producer)
|
||||
@line_items ||= Spree::LineItem.
|
||||
@line_items_from ||= Spree::LineItem.
|
||||
includes(variant: :product).
|
||||
joins(variant: :product).
|
||||
from_order_cycle(order_cycle).
|
||||
@@ -92,6 +92,8 @@ class ProducerMailer < ApplicationMailer
|
||||
quantity: line_item.quantity,
|
||||
first_name: order.billing_address.first_name,
|
||||
last_name: order.billing_address.last_name,
|
||||
phone: order.billing_address.phone,
|
||||
email: order.customer&.email,
|
||||
business_name: customer_code,
|
||||
order_number: order.number
|
||||
}
|
||||
|
||||
@@ -20,6 +20,10 @@ class ApplicationRecord < ActiveRecord::Base
|
||||
if ENV["S3_BUCKET"].present? && variant.service.public?
|
||||
variant.processed.url
|
||||
else
|
||||
unless variant.blob.persisted?
|
||||
raise "ActiveStorage blob for variant is not persisted. Cannot generate URL."
|
||||
end
|
||||
|
||||
url_for(variant)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -9,7 +9,7 @@ module Balance
|
||||
|
||||
# Branches by the OrderBalance abstraction
|
||||
def outstanding_balance
|
||||
@order_balance ||= OrderBalance.new(self)
|
||||
@outstanding_balance ||= OrderBalance.new(self)
|
||||
end
|
||||
|
||||
# Returns the order balance by considering the total as money owed to the order distributor aka.
|
||||
|
||||
@@ -108,13 +108,12 @@ module VariantStock
|
||||
# only one stock item per variant
|
||||
#
|
||||
# This enables us to override this behaviour for variant overrides
|
||||
def move(quantity, originator = nil)
|
||||
def move(quantity)
|
||||
return if deleted_at
|
||||
|
||||
raise_error_if_no_stock_item_available
|
||||
|
||||
# Creates a stock movement: it updates stock_item.count_on_hand and fills backorders
|
||||
stock_item.stock_movements.create!(quantity:, originator:)
|
||||
stock_item.adjust_count_on_hand(quantity)
|
||||
end
|
||||
|
||||
# There shouldn't be any other stock items, because we should
|
||||
@@ -141,10 +140,6 @@ module VariantStock
|
||||
end
|
||||
|
||||
# Overwrites stock_item.count_on_hand
|
||||
#
|
||||
# Calling stock_item.adjust_count_on_hand will bypass filling backorders
|
||||
# and creating stock movements
|
||||
# If that was required we could call self.move
|
||||
def overwrite_stock_levels(new_level)
|
||||
stock_item.adjust_count_on_hand(new_level.to_i - stock_item.count_on_hand)
|
||||
end
|
||||
|
||||
15
app/models/dfc_permission.rb
Normal file
15
app/models/dfc_permission.rb
Normal file
@@ -0,0 +1,15 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
# Authorisations of a user allowing a platform to access to data.
|
||||
class DfcPermission < ApplicationRecord
|
||||
SCOPES = %w[
|
||||
ReadEnterprise ReadProducts ReadOrders
|
||||
WriteEnterprise WriteProducts WriteOrders
|
||||
].freeze
|
||||
|
||||
belongs_to :user, class_name: "Spree::User"
|
||||
belongs_to :enterprise
|
||||
|
||||
validates :grantee, presence: true
|
||||
validates :scope, presence: true, inclusion: { in: SCOPES }
|
||||
end
|
||||
@@ -269,6 +269,21 @@ class Enterprise < ApplicationRecord
|
||||
HtmlSanitizer.sanitize_and_enforce_link_target_blank(html)
|
||||
end
|
||||
|
||||
def remove_logo=(value)
|
||||
self.logo = nil if value == "1"
|
||||
end
|
||||
|
||||
def remove_promo_image=(value)
|
||||
self.promo_image = nil if value == "1"
|
||||
end
|
||||
|
||||
def remove_white_label_logo=(value)
|
||||
return unless value == "1"
|
||||
|
||||
self.white_label_logo = nil
|
||||
self.white_label_logo_link = nil # Link not needed if there's no logo
|
||||
end
|
||||
|
||||
def contact
|
||||
contact = users.where(enterprise_roles: { receives_notifications: true }).first
|
||||
contact || owner
|
||||
|
||||
@@ -4,7 +4,7 @@ class Invoice
|
||||
class DataPresenter
|
||||
class LineItem < Invoice::DataPresenter::Base
|
||||
attributes :id, :added_tax, :currency, :included_tax, :price_with_adjustments, :quantity,
|
||||
:variant_id, :unit_price_price_and_unit, :unit_presentation,
|
||||
:variant_id, :unit_price, :unit_presentation,
|
||||
:enterprise_fee_additional_tax, :enterprise_fee_included_tax
|
||||
attributes_with_presenter :variant
|
||||
invoice_generation_attributes :added_tax, :included_tax, :price_with_adjustments,
|
||||
|
||||
@@ -286,9 +286,13 @@ class OrderCycle < ApplicationRecord
|
||||
user_id: user,
|
||||
distributor_id: distributor,
|
||||
order_cycle_id: self)
|
||||
|
||||
items = Spree::LineItem.includes(:variant).joins(:order).merge(orders)
|
||||
|
||||
scoper = OpenFoodNetwork::ScopeVariantToHub.new(distributor)
|
||||
items = Spree::LineItem.includes(:variant).joins(:order).merge(orders).to_a
|
||||
items.each { |li| scoper.scope(li.variant) }
|
||||
|
||||
items
|
||||
end
|
||||
|
||||
def distributor_payment_methods
|
||||
@@ -345,8 +349,8 @@ class OrderCycle < ApplicationRecord
|
||||
end
|
||||
|
||||
def orders_close_at_after_orders_open_at?
|
||||
return if orders_open_at.blank? || orders_close_at.blank?
|
||||
return if orders_close_at > orders_open_at
|
||||
return false if orders_open_at.blank? || orders_close_at.blank?
|
||||
return false if orders_close_at > orders_open_at
|
||||
|
||||
errors.add(:orders_close_at, :after_orders_open_at)
|
||||
end
|
||||
|
||||
@@ -46,7 +46,7 @@ module ProductImport
|
||||
end
|
||||
|
||||
def count_existing_items
|
||||
@spreadsheet_data.enterprises_index.each do |_enterprise_name, attrs|
|
||||
@spreadsheet_data.enterprises_index.each_value do |attrs|
|
||||
enterprise_id = attrs[:id]
|
||||
next unless enterprise_id && permission_by_id?(enterprise_id)
|
||||
|
||||
|
||||
@@ -142,20 +142,6 @@ module ProductImport
|
||||
{ entries: entries_json, reset_counts: }
|
||||
end
|
||||
|
||||
def save_results
|
||||
{
|
||||
results: {
|
||||
products_created: products_created_count,
|
||||
products_updated: products_updated_count,
|
||||
inventory_created: inventory_created_count,
|
||||
inventory_updated: inventory_updated_count,
|
||||
products_reset: products_reset_count,
|
||||
},
|
||||
updated_ids:,
|
||||
errors: errors.full_messages
|
||||
}
|
||||
end
|
||||
|
||||
def validate_entries
|
||||
@validator.validate_all(@entries)
|
||||
end
|
||||
@@ -207,6 +193,8 @@ module ProductImport
|
||||
order('is_primary_producer ASC, name').
|
||||
map { |e| @editable_enterprises[e.name] = e.id }
|
||||
|
||||
return unless OpenFoodNetwork::FeatureToggle.enabled?(:inventory, @current_user.enterprises)
|
||||
|
||||
@inventory_permissions = permissions.variant_override_enterprises_per_hub
|
||||
end
|
||||
|
||||
@@ -292,7 +280,7 @@ module ProductImport
|
||||
|
||||
def build_entries_from_rows(rows, offset = 0)
|
||||
rows.each_with_index.inject([]) do |entries, (row, i)|
|
||||
row_data = Hash[[headers, row].transpose]
|
||||
row_data = [headers, row].transpose.to_h
|
||||
entry = SpreadsheetEntry.new(row_data)
|
||||
entry.line_number = offset + i + 2
|
||||
entries.push entry
|
||||
|
||||
@@ -20,6 +20,10 @@ module Spree
|
||||
|
||||
if user.try(:admin?)
|
||||
can :manage, :all
|
||||
|
||||
# this action was needed for restrictions for distributors and suppliers
|
||||
# however, admins don't need to be restricted, so, bypassing it for admins
|
||||
cannot :edit_as_producer_only, Spree::Order
|
||||
else
|
||||
can [:index, :read], Country
|
||||
can :create, Order
|
||||
@@ -35,7 +39,6 @@ module Spree
|
||||
can [:read, :update, :destroy], Spree::User, id: user.id
|
||||
can [:index, :read], State
|
||||
can [:index, :read], StockItem
|
||||
can [:index, :read], StockMovement
|
||||
can [:index, :read], Taxon
|
||||
can [:index, :read], Variant
|
||||
can [:index, :read], Zone
|
||||
@@ -210,18 +213,20 @@ module Spree
|
||||
managed_product_enterprises.include? variant.supplier
|
||||
end
|
||||
|
||||
can [:admin, :index, :read, :update, :bulk_update, :bulk_reset], VariantOverride do |vo|
|
||||
next false unless vo.hub.present? && vo.variant&.supplier.present?
|
||||
if OpenFoodNetwork::FeatureToggle.enabled?(:inventory, user.enterprises)
|
||||
can [:admin, :index, :read, :update, :bulk_update, :bulk_reset], VariantOverride do |vo|
|
||||
next false unless vo.hub.present? && vo.variant&.supplier.present?
|
||||
|
||||
hub_auth = OpenFoodNetwork::Permissions.new(user).
|
||||
variant_override_hubs.
|
||||
include? vo.hub
|
||||
hub_auth = OpenFoodNetwork::Permissions.new(user).
|
||||
variant_override_hubs.
|
||||
include? vo.hub
|
||||
|
||||
producer_auth = OpenFoodNetwork::Permissions.new(user).
|
||||
variant_override_producers.
|
||||
include? vo.variant.supplier
|
||||
producer_auth = OpenFoodNetwork::Permissions.new(user).
|
||||
variant_override_producers.
|
||||
include? vo.variant.supplier
|
||||
|
||||
hub_auth && producer_auth
|
||||
hub_auth && producer_auth
|
||||
end
|
||||
end
|
||||
|
||||
can [:admin, :create, :update], InventoryItem do |ii|
|
||||
@@ -258,8 +263,13 @@ module Spree
|
||||
end
|
||||
|
||||
def add_order_cycle_management_abilities(user)
|
||||
can [:admin, :index], OrderCycle do |order_cycle|
|
||||
OrderCycle.visible_by(user).include?(order_cycle) ||
|
||||
order_cycle.orders.editable_by_producers(user.enterprises).exists?
|
||||
end
|
||||
|
||||
can [
|
||||
:admin, :index, :read, :edit, :update, :incoming, :outgoing, :checkout_options
|
||||
:read, :edit, :update, :incoming, :outgoing, :checkout_options
|
||||
], OrderCycle do |order_cycle|
|
||||
OrderCycle.visible_by(user).include? order_cycle
|
||||
end
|
||||
@@ -275,8 +285,37 @@ module Spree
|
||||
end
|
||||
|
||||
def add_order_management_abilities(user)
|
||||
can [:index, :create], Spree::Order
|
||||
can [:read, :update, :fire, :resend, :invoice, :print], Spree::Order do |order|
|
||||
can [:manage_order_sections], Spree::Order do |order|
|
||||
user.admin? ||
|
||||
order.distributor.nil? ||
|
||||
user.enterprises.include?(order.distributor) ||
|
||||
order.order_cycle&.coordinated_by?(user)
|
||||
end
|
||||
|
||||
can [:edit_as_producer_only], Spree::Order do |order|
|
||||
cannot?(:manage_order_sections, order) && can_edit_as_producer(order, user)
|
||||
end
|
||||
|
||||
can [:index], Spree::Order do
|
||||
user.admin? ||
|
||||
user.enterprises.any?(&:is_distributor) ||
|
||||
user.enterprises.distributors.where(enable_producers_to_edit_orders: true).exist?
|
||||
end
|
||||
|
||||
can [:create], Spree::Order
|
||||
|
||||
can [:read, :update], Spree::Order do |order|
|
||||
# We allow editing orders with a nil distributor as this state occurs
|
||||
# during the order creation process from the admin backend
|
||||
order.distributor.nil? ||
|
||||
# Enterprise User can access orders that they are a distributor for
|
||||
user.enterprises.include?(order.distributor) ||
|
||||
# Enterprise User can access orders that are placed inside a OC they coordinate
|
||||
order.order_cycle&.coordinated_by?(user) ||
|
||||
can_edit_as_producer(order, user)
|
||||
end
|
||||
|
||||
can [:fire, :resend, :invoice, :print], Spree::Order do |order|
|
||||
# We allow editing orders with a nil distributor as this state occurs
|
||||
# during the order creation process from the admin backend
|
||||
order.distributor.nil? ||
|
||||
@@ -285,22 +324,39 @@ module Spree
|
||||
# Enterprise User can access orders that are placed inside a OC they coordinate
|
||||
order.order_cycle&.coordinated_by?(user)
|
||||
end
|
||||
can [:admin, :bulk_management, :managed, :distribution], Spree::Order do
|
||||
|
||||
can [:admin, :bulk_management], Spree::Order do |order|
|
||||
user.admin? ||
|
||||
user.enterprises.any?(&:is_distributor) ||
|
||||
can_edit_as_producer(order, user)
|
||||
end
|
||||
|
||||
can [:managed, :distribution], Spree::Order do
|
||||
user.admin? || user.enterprises.any?(&:is_distributor)
|
||||
end
|
||||
can [:admin, :index, :create, :show, :poll, :generate], :invoice
|
||||
can [:admin, :visible], Enterprise
|
||||
can [:admin, :index, :create, :update, :destroy], :line_item
|
||||
can [:admin, :index, :create], Spree::LineItem
|
||||
can [:admin, :index, :create], Spree::LineItem do |item|
|
||||
user.admin? ||
|
||||
user.enterprises.any?(&:is_distributor) ||
|
||||
can_edit_as_producer(item.order, user)
|
||||
end
|
||||
can [:destroy, :update], Spree::LineItem do |item|
|
||||
order = item.order
|
||||
user.admin? ||
|
||||
user.enterprises.include?(order.distributor) ||
|
||||
order.order_cycle&.coordinated_by?(user)
|
||||
order.order_cycle&.coordinated_by?(user) ||
|
||||
can_edit_as_producer(order, user)
|
||||
end
|
||||
|
||||
can [:admin, :index, :read, :create, :edit, :update, :fire], Spree::Shipment do |shipment|
|
||||
user.admin? ||
|
||||
user.enterprises.any?(&:is_distributor) ||
|
||||
can_edit_as_producer(shipment.order, user)
|
||||
end
|
||||
|
||||
can [:admin, :index, :read, :create, :edit, :update, :fire], Spree::Payment
|
||||
can [:admin, :index, :read, :create, :edit, :update, :fire], Spree::Shipment
|
||||
can [:admin, :index, :read, :create, :edit, :update, :fire], Spree::Adjustment
|
||||
can [:admin, :index, :read, :create, :edit, :update, :fire], Spree::ReturnAuthorization
|
||||
can [:destroy], Spree::Adjustment do |adjustment|
|
||||
@@ -351,26 +407,35 @@ module Spree
|
||||
can [:admin, :edit, :cancel, :resume], ProxyOrder do |proxy_order|
|
||||
user.enterprises.include?(proxy_order.subscription.shop)
|
||||
end
|
||||
can [:visible], Enterprise
|
||||
end
|
||||
|
||||
def can_edit_order(order, user)
|
||||
def can_edit_as_producer(order, user)
|
||||
return unless order.distributor&.enable_producers_to_edit_orders
|
||||
|
||||
order.variants.any? { |variant| user.enterprises.ids.include?(variant.supplier_id) }
|
||||
end
|
||||
|
||||
def add_manage_line_items_abilities(user)
|
||||
can [:admin, :read, :index, :edit, :update, :bulk_management], Spree::Order do |order|
|
||||
can_edit_order(order, user)
|
||||
can [
|
||||
:admin,
|
||||
:read,
|
||||
:index,
|
||||
:edit,
|
||||
:update,
|
||||
:bulk_management,
|
||||
:edit_as_producer_only
|
||||
], Spree::Order do |order|
|
||||
can_edit_as_producer(order, user)
|
||||
end
|
||||
can [:admin, :index, :create, :destroy, :update], Spree::LineItem do |item|
|
||||
can_edit_order(item.order, user)
|
||||
can_edit_as_producer(item.order, user)
|
||||
end
|
||||
can [:index, :create, :add, :read, :edit, :update], Spree::Shipment do |shipment|
|
||||
can_edit_order(shipment.order, user)
|
||||
can_edit_as_producer(shipment.order, user)
|
||||
end
|
||||
can [:admin, :index], OrderCycle do |order_cycle|
|
||||
can_edit_order(order_cycle.order, user)
|
||||
can_edit_as_producer(order_cycle.order, user)
|
||||
end
|
||||
can [:visible], Enterprise
|
||||
end
|
||||
|
||||
@@ -30,6 +30,10 @@ module Spree
|
||||
preferences.transform_keys(&:to_sym)
|
||||
end
|
||||
|
||||
def respond_to_missing?(method_name, include_private = false)
|
||||
@provider.respond_to?(method_name, include_private) || super
|
||||
end
|
||||
|
||||
def method_missing(method, *args)
|
||||
if @provider.nil? || !@provider.respond_to?(method)
|
||||
super
|
||||
|
||||
@@ -109,7 +109,7 @@ module Spree
|
||||
}
|
||||
|
||||
scope :editable_by_producers, ->(enterprises_ids) {
|
||||
joins(:variant, order: :distributor).where(
|
||||
joins(variant: :supplier, order: :distributor).where(
|
||||
distributor: { enable_producers_to_edit_orders: true },
|
||||
spree_variants: { supplier_id: enterprises_ids }
|
||||
)
|
||||
@@ -234,10 +234,12 @@ module Spree
|
||||
final_weight_volume / quantity
|
||||
end
|
||||
|
||||
def unit_price_price_and_unit
|
||||
def unit_price
|
||||
unit_price = UnitPrice.new(variant)
|
||||
Spree::Money.new(price_with_adjustments / unit_price.denominator).to_html +
|
||||
" / ".html_safe + unit_price.unit
|
||||
{
|
||||
amount: price_with_adjustments / unit_price.denominator,
|
||||
unit: unit_price.unit,
|
||||
}
|
||||
end
|
||||
|
||||
def scoper
|
||||
|
||||
@@ -9,7 +9,7 @@ module Spree
|
||||
include SetUnusedAddressFields
|
||||
|
||||
searchable_attributes :number, :state, :shipment_state, :payment_state, :distributor_id,
|
||||
:order_cycle_id, :email, :total, :customer_id
|
||||
:order_cycle_id, :email, :total, :customer_id, :distributor_name_alias
|
||||
searchable_associations :shipping_method, :bill_address, :distributor
|
||||
searchable_scopes :complete, :incomplete, :sort_by_billing_address_name_asc,
|
||||
:sort_by_billing_address_name_desc
|
||||
@@ -181,6 +181,11 @@ module Spree
|
||||
scope :by_state, lambda { |state| where(state:) }
|
||||
scope :not_state, lambda { |state| where.not(state:) }
|
||||
|
||||
# This is used to filter line items by the distributor name on BOM page
|
||||
ransacker :distributor_name_alias do
|
||||
Arel.sql("distributor.name")
|
||||
end
|
||||
|
||||
def initialize(*_args)
|
||||
@checkout_processing = nil
|
||||
@manual_shipping_selection = nil
|
||||
|
||||
@@ -77,7 +77,7 @@ module Spree
|
||||
back_order.times { shipment.set_up_inventory('backordered', variant, order) }
|
||||
|
||||
if order.completed?
|
||||
variant.move(-quantity, shipment)
|
||||
variant.move(-quantity)
|
||||
end
|
||||
|
||||
quantity
|
||||
@@ -101,7 +101,7 @@ module Spree
|
||||
shipment.destroy if shipment.inventory_units.reload.count == 0
|
||||
|
||||
if order.completed? && restock_item
|
||||
variant.move(removed_quantity, shipment)
|
||||
variant.move(removed_quantity)
|
||||
end
|
||||
|
||||
removed_quantity
|
||||
|
||||
@@ -27,6 +27,20 @@ module Spree
|
||||
class Configuration
|
||||
include Spree::Preferences::Preferable
|
||||
|
||||
class << self
|
||||
def preference(name, type, *args)
|
||||
super
|
||||
|
||||
define_method(name) do
|
||||
get_preference(name)
|
||||
end
|
||||
|
||||
define_method("#{name}=") do |value|
|
||||
set_preference(name, value)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def configure
|
||||
yield(self) if block_given?
|
||||
end
|
||||
@@ -36,7 +50,7 @@ module Spree
|
||||
end
|
||||
|
||||
def reset
|
||||
preferences.each do |name, _value|
|
||||
preferences.each_key do |name|
|
||||
set_preference name, preference_default(name)
|
||||
end
|
||||
end
|
||||
@@ -56,19 +70,6 @@ module Spree
|
||||
|
||||
set_preference args[0], args[1]
|
||||
end
|
||||
|
||||
def method_missing(method, *args)
|
||||
name = method.to_s.gsub('=', '')
|
||||
if has_preference? name
|
||||
if method.to_s =~ /=$/
|
||||
set_preference(name, args.first)
|
||||
else
|
||||
get_preference name
|
||||
end
|
||||
else
|
||||
super
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -92,7 +92,7 @@ module Spree
|
||||
def process_return
|
||||
inventory_units.each do |iu|
|
||||
iu.return!
|
||||
Spree::StockMovement.create!(stock_item_id: iu.find_stock_item.id, quantity: 1)
|
||||
iu.find_stock_item.adjust_count_on_hand(1)
|
||||
end
|
||||
|
||||
Adjustment.create(
|
||||
|
||||
@@ -194,7 +194,9 @@ module Spree
|
||||
inventory_units.group_by(&:variant).map do |variant, units|
|
||||
states = {}
|
||||
units.group_by(&:state).each { |state, iu| states[state] = iu.count }
|
||||
|
||||
scoper.scope(variant)
|
||||
|
||||
OpenStruct.new(variant:, quantity: units.length, states:)
|
||||
end
|
||||
end
|
||||
@@ -313,11 +315,11 @@ module Spree
|
||||
end
|
||||
|
||||
def manifest_unstock(item)
|
||||
item.variant.move(-1 * item.quantity, self)
|
||||
item.variant.move(-1 * item.quantity)
|
||||
end
|
||||
|
||||
def manifest_restock(item)
|
||||
item.variant.move(item.quantity, self)
|
||||
item.variant.move(item.quantity)
|
||||
end
|
||||
|
||||
def generate_shipment_number
|
||||
|
||||
@@ -7,7 +7,6 @@ module Spree
|
||||
acts_as_paranoid
|
||||
|
||||
belongs_to :variant, -> { with_deleted }, class_name: 'Spree::Variant', inverse_of: :stock_items
|
||||
has_many :stock_movements, dependent: :destroy
|
||||
|
||||
validates :variant_id, uniqueness: { scope: [:deleted_at] }
|
||||
validates :count_on_hand, numericality: { greater_than_or_equal_to: 0, unless: :backorderable? }
|
||||
@@ -37,10 +36,6 @@ module Spree
|
||||
in_stock? || backorderable?
|
||||
end
|
||||
|
||||
def count_on_hand=(value)
|
||||
self[:count_on_hand] = value
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def process_backorders
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Spree
|
||||
class StockMovement < ApplicationRecord
|
||||
belongs_to :stock_item, class_name: 'Spree::StockItem'
|
||||
belongs_to :originator, polymorphic: true, optional: true
|
||||
|
||||
after_create :update_stock_item_quantity
|
||||
|
||||
validates :quantity, presence: true
|
||||
|
||||
scope :recent, -> { order('created_at DESC') }
|
||||
|
||||
private
|
||||
|
||||
def update_stock_item_quantity
|
||||
stock_item.adjust_count_on_hand quantity
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -21,7 +21,7 @@ module Spree
|
||||
acts_as_taggable
|
||||
|
||||
searchable_attributes :sku, :display_as, :display_name, :primary_taxon_id, :supplier_id
|
||||
searchable_associations :product, :default_price, :primary_taxon, :supplier
|
||||
searchable_associations :product, :default_price, :primary_taxon, :supplier, :tags
|
||||
searchable_scopes :active, :deleted
|
||||
|
||||
NAME_FIELDS = ["display_name", "display_as", "weight", "unit_value", "unit_description"].freeze
|
||||
|
||||
@@ -7,7 +7,7 @@ class TagRule::FilterOrderCycles < TagRule
|
||||
def tags_match?(order_cycle)
|
||||
exchange_tags = exchange_for(order_cycle)&.tag_list || []
|
||||
preferred_tags = preferred_exchange_tags.split(",")
|
||||
( exchange_tags & preferred_tags ).any?
|
||||
exchange_tags.intersect?(preferred_tags)
|
||||
end
|
||||
|
||||
def reject_matched?
|
||||
|
||||
@@ -7,7 +7,7 @@ class TagRule::FilterPaymentMethods < TagRule
|
||||
def tags_match?(payment_method)
|
||||
payment_method_tags = payment_method&.tag_list || []
|
||||
preferred_tags = preferred_payment_method_tags.split(",")
|
||||
( payment_method_tags & preferred_tags ).any?
|
||||
payment_method_tags.intersect?(preferred_tags)
|
||||
end
|
||||
|
||||
def reject_matched?
|
||||
|
||||
@@ -12,7 +12,7 @@ class TagRule
|
||||
def tags_match?(variant)
|
||||
variant_tags = variant&.[]("tag_list") || []
|
||||
preferred_tags = preferred_variant_tags.split(",")
|
||||
(variant_tags & preferred_tags).any?
|
||||
variant_tags.intersect?(preferred_tags)
|
||||
end
|
||||
|
||||
def reject_matched?
|
||||
|
||||
@@ -11,6 +11,6 @@ class TagRule::FilterShippingMethods < TagRule
|
||||
def tags_match?(shipping_method)
|
||||
shipping_method_tags = shipping_method&.tag_list || []
|
||||
preferred_tags = preferred_shipping_method_tags.split(",")
|
||||
( shipping_method_tags & preferred_tags ).any?
|
||||
shipping_method_tags.intersect?(preferred_tags)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module EnterpriseConcern
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
before_reflex do
|
||||
@enterprise = Enterprise.find_by(permalink: params[:id])
|
||||
authorize! :update, @enterprise
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,22 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class WhiteLabelReflex < ApplicationReflex
|
||||
include EnterpriseConcern
|
||||
delegate :view_context, to: :controller
|
||||
|
||||
def remove_logo
|
||||
@enterprise.update!(white_label_logo: nil)
|
||||
# delete the white_label_logo_link attribute as well since it has no meaning without the logo
|
||||
@enterprise.update!(white_label_logo_link: "")
|
||||
|
||||
f = ActionView::Helpers::FormBuilder.new(:enterprise, @enterprise, view_context, {})
|
||||
|
||||
html = render(partial: "admin/enterprises/form/white_label",
|
||||
locals: { f:, enterprise: @enterprise })
|
||||
morph "#white_label_panel", html
|
||||
|
||||
flash[:success] = I18n.t("admin.enterprises.form.white_label.remove_logo_success")
|
||||
cable_ready.dispatch_event(name: "modal:close")
|
||||
morph_admin_flashes
|
||||
end
|
||||
end
|
||||
@@ -25,7 +25,7 @@ module Api
|
||||
end
|
||||
|
||||
def default_card_present?
|
||||
return unless object.user
|
||||
return false unless object.user
|
||||
|
||||
object.user.default_card.present?
|
||||
end
|
||||
|
||||
@@ -11,7 +11,7 @@ module Api
|
||||
|
||||
def variants
|
||||
variants = object.incoming? ? visible_incoming_variants : visible_outgoing_variants
|
||||
Hash[object.variants.merge(variants).map { |v| [v.id, true] }]
|
||||
object.variants.merge(variants).to_h { |v| [v.id, true] }
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
@@ -102,9 +102,8 @@ module Api
|
||||
end
|
||||
|
||||
def display_value_for_producer(order, value)
|
||||
filter_by_supplier =
|
||||
order.distributor&.enable_producers_to_edit_orders &&
|
||||
options[:current_user]&.can_manage_line_items_in_orders_only?
|
||||
@ability ||= Spree::Ability.new(options[:current_user])
|
||||
filter_by_supplier = @ability.can?(:edit_as_producer_only, order)
|
||||
return value unless filter_by_supplier
|
||||
|
||||
if order.distributor&.show_customer_names_to_suppliers
|
||||
|
||||
@@ -10,7 +10,7 @@ module Api
|
||||
delegate :ship_address, to: :finder
|
||||
|
||||
def finder
|
||||
@finder ||= OpenFoodNetwork::AddressFinder.new(object, object.email)
|
||||
@finder ||= OpenFoodNetwork::AddressFinder.new(customer: object, email: object.email)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -11,11 +11,11 @@ module Api
|
||||
has_one :bill_address, serializer: Api::AddressSerializer
|
||||
|
||||
def ship_address
|
||||
OpenFoodNetwork::AddressFinder.new(object.email, object).ship_address
|
||||
OpenFoodNetwork::AddressFinder.new(email: object.email, user: object).ship_address
|
||||
end
|
||||
|
||||
def bill_address
|
||||
OpenFoodNetwork::AddressFinder.new(object.email, object).bill_address
|
||||
OpenFoodNetwork::AddressFinder.new(email: object.email, user: object).bill_address
|
||||
end
|
||||
|
||||
def confirmed
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
class Invoice
|
||||
class LineItemSerializer < ActiveModel::Serializer
|
||||
attributes :id, :added_tax, :currency, :included_tax, :price_with_adjustments, :quantity,
|
||||
:variant_id, :unit_price_price_and_unit, :unit_presentation,
|
||||
:variant_id, :unit_price, :unit_presentation,
|
||||
:enterprise_fee_additional_tax, :enterprise_fee_included_tax
|
||||
has_one :variant, serializer: Invoice::VariantSerializer
|
||||
|
||||
|
||||
@@ -60,6 +60,7 @@ class CartService
|
||||
|
||||
def attempt_cart_add(variant, quantity, max_quantity = nil)
|
||||
scoper.scope(variant)
|
||||
|
||||
return unless valid_variant?(variant)
|
||||
|
||||
cart_add(variant, quantity, max_quantity)
|
||||
|
||||
@@ -1,15 +1,23 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "private_address_check"
|
||||
require "private_address_check/tcpsocket_ext"
|
||||
|
||||
class ImageImporter
|
||||
def import(url, product)
|
||||
valid_url = URI.parse(url)
|
||||
file = open(valid_url.to_s)
|
||||
filename = File.basename(valid_url.path)
|
||||
metadata = { custom: { origin: url } }
|
||||
|
||||
Spree::Image.create(
|
||||
attachment: { io: file, filename: },
|
||||
viewable_id: product.id,
|
||||
viewable_type: Spree::Product,
|
||||
)
|
||||
image = Spree::Image.create do |img|
|
||||
PrivateAddressCheck.only_public_connections do
|
||||
img.attachment.attach(io: valid_url.open, filename:, metadata:)
|
||||
end
|
||||
end
|
||||
product.image = image if image
|
||||
rescue StandardError
|
||||
# Any URL parsing or network error shouldn't impact the product import
|
||||
# at all. Maybe we'll add UX for error handling later.
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
@@ -5,10 +5,11 @@
|
||||
|
||||
module OrderCycles
|
||||
class DistributedProductsService # rubocop:disable Metrics/ClassLength
|
||||
def initialize(distributor, order_cycle, customer)
|
||||
def initialize(distributor, order_cycle, customer, **options)
|
||||
@distributor = distributor
|
||||
@order_cycle = order_cycle
|
||||
@customer = customer
|
||||
@options = options
|
||||
end
|
||||
|
||||
def products_relation
|
||||
@@ -26,13 +27,13 @@ module OrderCycles
|
||||
def variants_relation
|
||||
order_cycle.
|
||||
variants_distributed_by(distributor).
|
||||
merge(stocked_variants_and_overrides).
|
||||
merge(variants).
|
||||
select("DISTINCT spree_variants.*")
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
attr_reader :distributor, :order_cycle, :customer
|
||||
attr_reader :distributor, :order_cycle, :customer, :options
|
||||
|
||||
def relation_by_sorting
|
||||
query = Spree::Product.where(id: stocked_products)
|
||||
@@ -112,10 +113,18 @@ module OrderCycles
|
||||
def stocked_products
|
||||
order_cycle.
|
||||
variants_distributed_by(distributor).
|
||||
merge(stocked_variants_and_overrides).
|
||||
merge(variants).
|
||||
select("DISTINCT spree_variants.product_id")
|
||||
end
|
||||
|
||||
def variants
|
||||
options[:inventory_enabled] ? stocked_variants_and_overrides : stocked_variants
|
||||
end
|
||||
|
||||
def stocked_variants
|
||||
Spree::Variant.joins(:stock_items).where(query_stock)
|
||||
end
|
||||
|
||||
def stocked_variants_and_overrides
|
||||
stocked_variants = Spree::Variant.
|
||||
joins("LEFT OUTER JOIN variant_overrides ON variant_overrides.variant_id = spree_variants.id
|
||||
@@ -126,6 +135,10 @@ module OrderCycles
|
||||
ProductTagRulesFilterer.new(distributor, customer, stocked_variants).call
|
||||
end
|
||||
|
||||
def query_stock
|
||||
"( #{variant_on_demand} OR #{variant_in_stock} )"
|
||||
end
|
||||
|
||||
def query_stock_with_overrides
|
||||
"( #{variant_not_overriden} AND ( #{variant_on_demand} OR #{variant_in_stock} ) )
|
||||
OR ( #{variant_overriden} AND ( #{override_on_demand} OR #{override_in_stock} ) )
|
||||
|
||||
@@ -52,6 +52,7 @@ module Orders
|
||||
next unless variant = Spree::Variant.find_by(id: li[:variant_id])
|
||||
|
||||
scoper.scope(variant)
|
||||
|
||||
li[:quantity] = stock_limited_quantity(variant.on_demand, variant.on_hand, li[:quantity])
|
||||
li[:price] = variant.price
|
||||
build_item_from(li)
|
||||
|
||||
@@ -21,16 +21,23 @@ module Permissions
|
||||
filtered_orders(orders)
|
||||
end
|
||||
|
||||
def managed_or_coordinated_orders_where_clause
|
||||
Spree::Order.where(
|
||||
managed_orders_where_values.or(coordinated_orders_where_values)
|
||||
)
|
||||
end
|
||||
|
||||
# Any orders that the user can edit
|
||||
def editable_orders
|
||||
orders = if @user.can_manage_line_items_in_orders_only?
|
||||
orders = if @user.admin?
|
||||
# It returns all orders if the user is an admin
|
||||
managed_or_coordinated_orders_where_clause
|
||||
else
|
||||
Spree::Order.joins(:distributor).where(
|
||||
id: produced_orders.select(:id),
|
||||
distributor: { enable_producers_to_edit_orders: true }
|
||||
)
|
||||
else
|
||||
Spree::Order.where(
|
||||
managed_orders_where_values.or(coordinated_orders_where_values)
|
||||
).or(
|
||||
managed_or_coordinated_orders_where_clause
|
||||
)
|
||||
end
|
||||
|
||||
@@ -43,12 +50,19 @@ module Permissions
|
||||
|
||||
# Any line items that I can edit
|
||||
def editable_line_items
|
||||
if @user.can_manage_line_items_in_orders_only?
|
||||
managed_or_coordinated_line_items_where_clause = Spree::LineItem.where(
|
||||
order_id: filtered_orders(managed_or_coordinated_orders_where_clause).select(:id)
|
||||
)
|
||||
|
||||
if @user.admin?
|
||||
# It returns all line_items if the user is an admin
|
||||
managed_or_coordinated_line_items_where_clause
|
||||
else
|
||||
Spree::LineItem.editable_by_producers(
|
||||
@permissions.managed_enterprises.select("enterprises.id")
|
||||
).or(
|
||||
managed_or_coordinated_line_items_where_clause
|
||||
)
|
||||
else
|
||||
Spree::LineItem.where(order_id: editable_orders.select(:id))
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -39,7 +39,8 @@ module PermittedAttributes
|
||||
:preferred_product_low_stock_display,
|
||||
:hide_ofn_navigation, :white_label_logo, :white_label_logo_link,
|
||||
:hide_groups_tab, :external_billing_id,
|
||||
:enable_producers_to_edit_orders
|
||||
:enable_producers_to_edit_orders,
|
||||
:remove_logo, :remove_promo_image, :remove_white_label_logo
|
||||
]
|
||||
end
|
||||
end
|
||||
|
||||
@@ -13,13 +13,13 @@ class ProcessPaymentIntent
|
||||
class Result
|
||||
attr_reader :error
|
||||
|
||||
def initialize(ok:, error: "")
|
||||
@ok = ok
|
||||
def initialize(success:, error: "")
|
||||
@success = success
|
||||
@error = error
|
||||
end
|
||||
|
||||
def ok?
|
||||
@ok
|
||||
def success?
|
||||
@success
|
||||
end
|
||||
end
|
||||
|
||||
@@ -30,8 +30,8 @@ class ProcessPaymentIntent
|
||||
end
|
||||
|
||||
def call!
|
||||
return Result.new(ok: false) unless payment.present? && ready_for_capture?
|
||||
return Result.new(ok: true) if already_processed?
|
||||
return Result.new(success: false) unless payment.present? && ready_for_capture?
|
||||
return Result.new(success: true) if already_processed?
|
||||
|
||||
process_payment
|
||||
|
||||
@@ -39,16 +39,16 @@ class ProcessPaymentIntent
|
||||
payment.complete_authorization
|
||||
payment.clear_authorization_url
|
||||
|
||||
Result.new(ok: true)
|
||||
Result.new(success: true)
|
||||
else
|
||||
payment.fail_authorization
|
||||
payment.clear_authorization_url
|
||||
Result.new(ok: false, error: I18n.t("payment_could_not_complete"))
|
||||
Result.new(success: false, error: I18n.t("payment_could_not_complete"))
|
||||
end
|
||||
rescue Stripe::StripeError => e
|
||||
payment.fail_authorization
|
||||
payment.clear_authorization_url
|
||||
Result.new(ok: false, error: e.message)
|
||||
Result.new(success: false, error: e.message)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
@@ -8,11 +8,12 @@ class ProductsRenderer
|
||||
class NoProducts < RuntimeError; end
|
||||
DEFAULT_PER_PAGE = 10
|
||||
|
||||
def initialize(distributor, order_cycle, customer, args = {})
|
||||
def initialize(distributor, order_cycle, customer, args = {}, **options)
|
||||
@distributor = distributor
|
||||
@order_cycle = order_cycle
|
||||
@customer = customer
|
||||
@args = args
|
||||
@options = options
|
||||
end
|
||||
|
||||
def products_json
|
||||
@@ -28,7 +29,7 @@ class ProductsRenderer
|
||||
|
||||
private
|
||||
|
||||
attr_reader :order_cycle, :distributor, :customer, :args
|
||||
attr_reader :order_cycle, :distributor, :customer, :args, :options
|
||||
|
||||
def products
|
||||
return unless order_cycle
|
||||
@@ -40,8 +41,15 @@ class ProductsRenderer
|
||||
distributed_products.products_relation
|
||||
end
|
||||
results = filter(results)
|
||||
# Scope results with variant_overrides
|
||||
paginate(results).each { |product| product_scoper.scope(product) }
|
||||
|
||||
paginated_products = paginate(results)
|
||||
|
||||
if options[:inventory_enabled]
|
||||
# Scope results with variant_overrides
|
||||
paginated_products.each { |product| product_scoper.scope(product) }
|
||||
end
|
||||
|
||||
paginated_products
|
||||
end
|
||||
end
|
||||
|
||||
@@ -106,19 +114,22 @@ class ProductsRenderer
|
||||
end
|
||||
|
||||
def distributed_products
|
||||
OrderCycles::DistributedProductsService.new(distributor, order_cycle, customer)
|
||||
OrderCycles::DistributedProductsService.new(distributor, order_cycle, customer, **options)
|
||||
end
|
||||
|
||||
def variants_for_shop
|
||||
@variants_for_shop ||= begin
|
||||
scoper = OpenFoodNetwork::ScopeVariantToHub.new(distributor)
|
||||
|
||||
# rubocop:disable Rails/FindEach # .each returns an array, .find_each returns nil
|
||||
distributed_products.variants_relation.
|
||||
variants = distributed_products.variants_relation.
|
||||
includes(:default_price, :product).
|
||||
where(product_id: products).
|
||||
each { |v| scoper.scope(v) } # Scope results with variant_overrides
|
||||
# rubocop:enable Rails/FindEach
|
||||
where(product_id: products)
|
||||
|
||||
if options[:inventory_enabled]
|
||||
# Scope results with variant_overrides
|
||||
scoper = OpenFoodNetwork::ScopeVariantToHub.new(distributor)
|
||||
variants = variants.each { |v| scoper.scope(v) }
|
||||
end
|
||||
|
||||
variants
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ module Sets
|
||||
end
|
||||
|
||||
def collection_attributes=(collection_attributes)
|
||||
collection_attributes.each do |_k, attributes|
|
||||
collection_attributes.each_value do |attributes|
|
||||
# attributes == {:id => 123, :next_collection_at => '...'}
|
||||
found_element = @collection.detect do |element|
|
||||
element.id.to_s == attributes[:id].to_s && !element.id.nil?
|
||||
|
||||
@@ -25,17 +25,15 @@ class VariantsStockLevels
|
||||
private
|
||||
|
||||
def variant_stock_levels(line_items)
|
||||
Hash[
|
||||
line_items.map do |line_item|
|
||||
variant = scoped_variant(line_item.order.distributor, line_item.variant)
|
||||
line_items.to_h do |line_item|
|
||||
variant = scoped_variant(line_item.order.distributor, line_item.variant)
|
||||
|
||||
[variant.id,
|
||||
{ quantity: line_item.quantity,
|
||||
max_quantity: line_item.max_quantity,
|
||||
on_hand: variant.on_hand,
|
||||
on_demand: variant.on_demand }]
|
||||
end
|
||||
]
|
||||
[variant.id,
|
||||
{ quantity: line_item.quantity,
|
||||
max_quantity: line_item.max_quantity,
|
||||
on_hand: variant.on_hand,
|
||||
on_demand: variant.on_demand }]
|
||||
end
|
||||
end
|
||||
|
||||
def scoped_variant(distributor, variant)
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
- connected_apps_enabled.each do |type|
|
||||
- connected_apps_enabled(enterprise).each do |type|
|
||||
= render partial: "/admin/enterprises/form/connected_apps/#{type}",
|
||||
locals: { enterprise:, connected_app: enterprise.connected_apps.public_send(type).first }
|
||||
|
||||
= render partial: "/admin/enterprises/form/dfc_permissions" if dfc_platforms_available?
|
||||
|
||||
30
app/views/admin/enterprises/form/_dfc_permissions.html.haml
Normal file
30
app/views/admin/enterprises/form/_dfc_permissions.html.haml
Normal file
@@ -0,0 +1,30 @@
|
||||
%script{type: "module", src: "https://cdn.jsdelivr.net/npm/@startinblox/core@latest/dist/index.js"}
|
||||
%script{type: "module"}
|
||||
:plain
|
||||
window.orbit = {
|
||||
client: {
|
||||
name: "Orbit",
|
||||
logo: "https://cdn.startinblox.com/logos/ACME.svg",
|
||||
},
|
||||
components: [],
|
||||
getRoute: (route) => route,
|
||||
getDefaultRoute: () => "",
|
||||
getComponent: () => undefined,
|
||||
getComponentFromRoute: () => undefined,
|
||||
Swal: () => {},
|
||||
defaultRoute: "",
|
||||
federations: {},
|
||||
componentSet: new Set(["routing", "menu", "menu-top", "autoLogin", "solid-permissioning"]),
|
||||
};
|
||||
|
||||
:plain
|
||||
<solid-permissioning
|
||||
data-src="#{DfcProvider::Engine.routes.url_helpers.enterprise_platforms_url(@enterprise.id)}"
|
||||
scopes-uri="https://cdn.startinblox.com/owl/dfc/taxonomies/scopes.jsonld"
|
||||
noRouter
|
||||
auto-lang
|
||||
lang="en"
|
||||
auth-token="#{form_authenticity_token}">
|
||||
</solid-permissioning>
|
||||
|
||||
%script{type: "module", src: "https://cdn.jsdelivr.net/npm/@startinblox/solid-data-permissioning@latest/dist/index.js"}
|
||||
@@ -1,27 +1,11 @@
|
||||
.row.page-admin-enterprises-form__logo-field-group.image-field-group
|
||||
.alpha.three.columns
|
||||
= f.label :logo
|
||||
%br
|
||||
= t('.logo_size')
|
||||
.omega.eight.columns
|
||||
%img{ class: 'image-field-group__preview-image', "ng-src": '{{ Enterprise.logo.thumb }}', "ng-if": 'Enterprise.logo' }
|
||||
%br
|
||||
= f.file_field :logo
|
||||
%a.button.red{ href: '', "ng-click": 'removeLogo()', "ng-if": 'Enterprise.logo' }
|
||||
= t('.remove_logo')
|
||||
= render "admin/shared/attachment_field", attachment_url: @enterprise.logo_url(:thumb), attachment_name: :logo, f: f
|
||||
|
||||
.row.page-admin-enterprises-form__promo-image-field-group.image-field-group
|
||||
.alpha.three.columns
|
||||
= f.label :promo_image, 'ofn-with-tip' => t('.promo_image_placeholder')
|
||||
%br/
|
||||
%span{ style: 'font-weight:bold' }= t('.promo_image_note1')
|
||||
%br
|
||||
= t('.promo_image_note2')
|
||||
%br
|
||||
= t('.promo_image_note3')
|
||||
|
||||
.omega.eight.columns
|
||||
%img{ class: 'image-field-group__preview-image', "ng-src": '{{ Enterprise.promo_image.large }}', "ng-if": 'Enterprise.promo_image' }
|
||||
= f.file_field :promo_image
|
||||
%a.button.red{ href: '', "ng-click": 'removePromoImage()', "ng-if": 'Enterprise.promo_image' }
|
||||
= t('.remove_promo_image')
|
||||
= render "admin/shared/attachment_field", attachment_url: @enterprise.promo_image_url(:large), attachment_name: :promo_image, f: f do
|
||||
%br/
|
||||
= t('.promo_image_placeholder')
|
||||
%br
|
||||
%span{ style: 'font-weight:bold' }= t('.promo_image_note1')
|
||||
%br
|
||||
= t('.promo_image_note2')
|
||||
%br
|
||||
= t('.promo_image_note3')
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user