mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-03-26 05:55:15 +00:00
Compare commits
464 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d33cabd6b2 | ||
|
|
7b21a9d30f | ||
|
|
c00e7eeecf | ||
|
|
afdb044386 | ||
|
|
b98552003c | ||
|
|
38f1754738 | ||
|
|
ad23735384 | ||
|
|
6fd78d4647 | ||
|
|
cd3a80c502 | ||
|
|
f8c88ea8c7 | ||
|
|
4ba55c4067 | ||
|
|
813249bad7 | ||
|
|
9f2c35d407 | ||
|
|
79af9efd29 | ||
|
|
b731f9b9e4 | ||
|
|
da90cdd9f6 | ||
|
|
f86c925209 | ||
|
|
0040e4d454 | ||
|
|
876d37d19a | ||
|
|
36d617bceb | ||
|
|
7c0528ad83 | ||
|
|
f25d51e772 | ||
|
|
7b559e2f83 | ||
|
|
a94ccd4493 | ||
|
|
fc6ed9ab4b | ||
|
|
c115ab7a0d | ||
|
|
f3428494fc | ||
|
|
d748972fca | ||
|
|
b9c7925008 | ||
|
|
c11b93a4dc | ||
|
|
61e0688392 | ||
|
|
5971cdc6e2 | ||
|
|
b3a1d1269a | ||
|
|
a0011bd2e9 | ||
|
|
2219513c93 | ||
|
|
fb713d8721 | ||
|
|
90761e0766 | ||
|
|
6fb4048bfd | ||
|
|
c3def926f1 | ||
|
|
d6cde5c793 | ||
|
|
756e876f61 | ||
|
|
5e57325ce2 | ||
|
|
cd956dadda | ||
|
|
2a3b076170 | ||
|
|
e6d556c809 | ||
|
|
f35b2be228 | ||
|
|
cc9cb966b5 | ||
|
|
34f9e08824 | ||
|
|
7d5db81017 | ||
|
|
1b03528aca | ||
|
|
9a90e46b78 | ||
|
|
7e4886ad67 | ||
|
|
9297dbfa63 | ||
|
|
7bfe51d067 | ||
|
|
6ad49cc080 | ||
|
|
2a7e8816c0 | ||
|
|
988f903164 | ||
|
|
108e313e48 | ||
|
|
e502aad7c9 | ||
|
|
9af57e1fc4 | ||
|
|
a0c23825b8 | ||
|
|
4e5238d1bb | ||
|
|
26b8f62325 | ||
|
|
ee087f9eff | ||
|
|
3152362b9d | ||
|
|
601c921b4b | ||
|
|
39fbf01e98 | ||
|
|
69586ae5ae | ||
|
|
c87eb05c0e | ||
|
|
a1f363c53b | ||
|
|
76c6362db0 | ||
|
|
5c3308de36 | ||
|
|
a82b2c2799 | ||
|
|
4895010fe0 | ||
|
|
962097f237 | ||
|
|
941707a0df | ||
|
|
85439b4b54 | ||
|
|
30804da259 | ||
|
|
35724bec81 | ||
|
|
1e2b8bad3f | ||
|
|
6cbc6fbca3 | ||
|
|
88a0737916 | ||
|
|
b0b03cbb5f | ||
|
|
f5823bd618 | ||
|
|
d9453979b1 | ||
|
|
2cde74b91a | ||
|
|
3fd007fa3d | ||
|
|
e3431c7954 | ||
|
|
9fa715c709 | ||
|
|
f7e119d06f | ||
|
|
52ee5929cf | ||
|
|
1e58882217 | ||
|
|
ca23f12451 | ||
|
|
cce37aa915 | ||
|
|
f808fe9685 | ||
|
|
dd5db396b4 | ||
|
|
e121a799ed | ||
|
|
5dfef4a3ae | ||
|
|
8236603f76 | ||
|
|
315d52961a | ||
|
|
dcb6f4676d | ||
|
|
3455ceb722 | ||
|
|
7361b2da0b | ||
|
|
3ebacbc31a | ||
|
|
c0bcf177e7 | ||
|
|
8dfede11c6 | ||
|
|
bac123f223 | ||
|
|
fdc775ae6d | ||
|
|
26b39d6626 | ||
|
|
8953e8481d | ||
|
|
1ce76a3166 | ||
|
|
1c703905fe | ||
|
|
feed223ab4 | ||
|
|
90f962a886 | ||
|
|
82f6484031 | ||
|
|
282fb44da4 | ||
|
|
82f40d2e93 | ||
|
|
cae1655ec3 | ||
|
|
e8e48f7c64 | ||
|
|
26702e6f0d | ||
|
|
8cd9e94148 | ||
|
|
a934b60f67 | ||
|
|
7fc9a6bf93 | ||
|
|
781bf940f6 | ||
|
|
92382ca473 | ||
|
|
76a3e913df | ||
|
|
23ab6bb489 | ||
|
|
fd3c1c1343 | ||
|
|
368da19993 | ||
|
|
419f4490d6 | ||
|
|
39245d55e2 | ||
|
|
fe8200b7e8 | ||
|
|
c799f15067 | ||
|
|
54f1047dcb | ||
|
|
c1e599deef | ||
|
|
f3c60148c1 | ||
|
|
2e08c9c44e | ||
|
|
93f2af7e7d | ||
|
|
cb7a4b67ce | ||
|
|
41a8d06326 | ||
|
|
a957df1205 | ||
|
|
a1bdfa0a20 | ||
|
|
1adf94093e | ||
|
|
476daf0d30 | ||
|
|
18ef5cc69a | ||
|
|
a69528c432 | ||
|
|
9dfecde6a7 | ||
|
|
c73f28b434 | ||
|
|
0cd9fa91a8 | ||
|
|
252943e9de | ||
|
|
cab4b2fb28 | ||
|
|
80bd6defcb | ||
|
|
bd367cb154 | ||
|
|
d0f48687e2 | ||
|
|
25063d2c4d | ||
|
|
bad04b70a9 | ||
|
|
5479572a08 | ||
|
|
79a9dbcf68 | ||
|
|
61c7c26822 | ||
|
|
969dcae8d0 | ||
|
|
ce5a95ff4f | ||
|
|
0d5330d388 | ||
|
|
3676acf244 | ||
|
|
caf6b087c1 | ||
|
|
24d6c1e386 | ||
|
|
a120e390d0 | ||
|
|
98a2bf5d47 | ||
|
|
bb0c1e7a0f | ||
|
|
55a15b914c | ||
|
|
8ce14a55c8 | ||
|
|
d1f47f6956 | ||
|
|
2d50dace20 | ||
|
|
bbbbe71bc4 | ||
|
|
b3dc76b8cf | ||
|
|
ad4b26e86d | ||
|
|
c2a7a89381 | ||
|
|
68e3623861 | ||
|
|
577aa55f98 | ||
|
|
b8e62b3d84 | ||
|
|
dbb8e07b9a | ||
|
|
19550ed4fe | ||
|
|
4d0c710e3b | ||
|
|
fccde70690 | ||
|
|
b8de75b1ef | ||
|
|
06bfd07fec | ||
|
|
e98cf78b4c | ||
|
|
13229cc0c1 | ||
|
|
0f59333cd9 | ||
|
|
ad4ce14486 | ||
|
|
3173c79e8f | ||
|
|
ca14d557c1 | ||
|
|
59a3a5bd92 | ||
|
|
a226088f5c | ||
|
|
e91fab5702 | ||
|
|
e09853af0c | ||
|
|
c65fcc1072 | ||
|
|
3bb68ec07e | ||
|
|
2c97638aa1 | ||
|
|
ceee9671d9 | ||
|
|
6b494be7ff | ||
|
|
a6855e6bc1 | ||
|
|
7ca43eb4a1 | ||
|
|
74b5ac559f | ||
|
|
07c236497c | ||
|
|
caf2ff9bb4 | ||
|
|
1b2a17d7e4 | ||
|
|
ce46115139 | ||
|
|
9fd2ff7620 | ||
|
|
98a25c1c7f | ||
|
|
6b78f8b855 | ||
|
|
1e2b28c559 | ||
|
|
12b86a35af | ||
|
|
4577bde692 | ||
|
|
af6be02ba4 | ||
|
|
0dabca583f | ||
|
|
d7603755bf | ||
|
|
f9d255a266 | ||
|
|
bcf4507795 | ||
|
|
9967ba2d06 | ||
|
|
f90f71cf68 | ||
|
|
fe8a0a908e | ||
|
|
bf6176c883 | ||
|
|
ffdfb7d450 | ||
|
|
3aa4c2a25f | ||
|
|
3331aaa382 | ||
|
|
b302dcfbec | ||
|
|
7dfc4d21ca | ||
|
|
f332a6934b | ||
|
|
baad0135f9 | ||
|
|
1973e36634 | ||
|
|
2e62531232 | ||
|
|
d811103a71 | ||
|
|
e1f4210aa8 | ||
|
|
f3efed7aeb | ||
|
|
584b976dff | ||
|
|
4073238654 | ||
|
|
d7505bcef4 | ||
|
|
f6a7225c47 | ||
|
|
377f33b64f | ||
|
|
73b27f14ab | ||
|
|
0b497fbb77 | ||
|
|
5e4df41ec8 | ||
|
|
72085be896 | ||
|
|
e0bc8f9cdc | ||
|
|
efcb442a80 | ||
|
|
a38023475c | ||
|
|
4a6ba29b99 | ||
|
|
7f961d90c2 | ||
|
|
0ac4021729 | ||
|
|
ac662de789 | ||
|
|
23c57cb354 | ||
|
|
d6ef56af6e | ||
|
|
059e36318e | ||
|
|
7a72121b1b | ||
|
|
01278c3ee6 | ||
|
|
c01cca33c7 | ||
|
|
631306cfb3 | ||
|
|
da7f46de1f | ||
|
|
20107986a6 | ||
|
|
f4d59305d7 | ||
|
|
dbd0100044 | ||
|
|
7f108353e3 | ||
|
|
e1775eaad8 | ||
|
|
ad9ebc2f92 | ||
|
|
fa4351599f | ||
|
|
e5ba0843d8 | ||
|
|
71fe5bc107 | ||
|
|
3c3b591655 | ||
|
|
39c7fbef46 | ||
|
|
cff52beb06 | ||
|
|
c4fec2ee76 | ||
|
|
952fc15a64 | ||
|
|
2cbd5b5255 | ||
|
|
9f77c5912f | ||
|
|
1e4c0cb2cc | ||
|
|
ded139458d | ||
|
|
e5f9c39352 | ||
|
|
f0554d8ae2 | ||
|
|
e37caf7a96 | ||
|
|
03653bee60 | ||
|
|
43cf6e4147 | ||
|
|
7f01658f47 | ||
|
|
7701561755 | ||
|
|
0bdee785bb | ||
|
|
1029b61bb0 | ||
|
|
065e7a420b | ||
|
|
fe4b6accb0 | ||
|
|
1049ec277c | ||
|
|
b3314d7441 | ||
|
|
c526e72539 | ||
|
|
e217a6fca8 | ||
|
|
6aa7ef3c21 | ||
|
|
77121dfacf | ||
|
|
04323388ad | ||
|
|
bf0e5c0d44 | ||
|
|
6bd2f5af8d | ||
|
|
7bf54088a6 | ||
|
|
4792040240 | ||
|
|
700be792e5 | ||
|
|
9f2ece379a | ||
|
|
2662371507 | ||
|
|
172647f1cd | ||
|
|
24fc3e9e86 | ||
|
|
b064173b7a | ||
|
|
f95581cd1f | ||
|
|
b113fe08e1 | ||
|
|
93d73f4763 | ||
|
|
154d17969c | ||
|
|
e32dcd53b5 | ||
|
|
dc631026d4 | ||
|
|
44c4a66970 | ||
|
|
d05834b896 | ||
|
|
854e136d09 | ||
|
|
7f3fc4ff91 | ||
|
|
c05532c166 | ||
|
|
62ae62db5a | ||
|
|
a6fc49abce | ||
|
|
528c5a3593 | ||
|
|
81165cd82b | ||
|
|
faf50a1922 | ||
|
|
5f237adda2 | ||
|
|
2e09a96c4b | ||
|
|
6ae47c208a | ||
|
|
82139a9ac0 | ||
|
|
6d9946c3c6 | ||
|
|
f58b6bcada | ||
|
|
dc13ef4162 | ||
|
|
dcb48272f5 | ||
|
|
08bc374576 | ||
|
|
afbf0a5d0e | ||
|
|
7e034a3037 | ||
|
|
2db2fb2f11 | ||
|
|
74d2a94181 | ||
|
|
7a5b273e71 | ||
|
|
0b6e7593db | ||
|
|
6d0d91c56a | ||
|
|
a509d49ec6 | ||
|
|
dddc945c42 | ||
|
|
12c0363b7e | ||
|
|
bb0903cd4a | ||
|
|
e93cb485a1 | ||
|
|
fbce264dd7 | ||
|
|
3c1313bfa0 | ||
|
|
4ca420bd84 | ||
|
|
134ea28249 | ||
|
|
78cfc0db65 | ||
|
|
816e06d37c | ||
|
|
2e80b7d92f | ||
|
|
753173e2be | ||
|
|
c9954f0823 | ||
|
|
80f5fa30c4 | ||
|
|
9194d0ba2b | ||
|
|
e00c993a98 | ||
|
|
800333f65b | ||
|
|
64df7cc9bc | ||
|
|
b23fec268e | ||
|
|
7b7a7d3418 | ||
|
|
6fa99b187d | ||
|
|
a009dacd41 | ||
|
|
472ba98ec2 | ||
|
|
91cd3356b0 | ||
|
|
67ef142546 | ||
|
|
0aa4993a4d | ||
|
|
98176bd5de | ||
|
|
dde0e23a79 | ||
|
|
d1021210e6 | ||
|
|
bfa472a293 | ||
|
|
9d14c1026c | ||
|
|
c653743a56 | ||
|
|
28af42371b | ||
|
|
acfe180e1d | ||
|
|
7d20eb4fea | ||
|
|
a1ee1eac4c | ||
|
|
84b351e076 | ||
|
|
9f7faac842 | ||
|
|
02c1b309f3 | ||
|
|
58028df3b7 | ||
|
|
638c139bca | ||
|
|
5adfdf11fb | ||
|
|
152a7b7fe9 | ||
|
|
5c998bfc77 | ||
|
|
97ca8702d4 | ||
|
|
e194ebf0f3 | ||
|
|
f6fc8a6993 | ||
|
|
cbf6b4462e | ||
|
|
c03580180a | ||
|
|
77b72134d8 | ||
|
|
c638e2e65e | ||
|
|
25ac714cc6 | ||
|
|
475e6c33f1 | ||
|
|
ae70a1372b | ||
|
|
6eb6bf634f | ||
|
|
a82209af85 | ||
|
|
ecf0d53f0a | ||
|
|
fc047e3f7c | ||
|
|
d9e3076a3b | ||
|
|
271e895486 | ||
|
|
3e02a03312 | ||
|
|
ec31ff418d | ||
|
|
22f3577b0d | ||
|
|
9c9773f493 | ||
|
|
33cea470ad | ||
|
|
17ac3507a6 | ||
|
|
763655f0e5 | ||
|
|
7cf0a95688 | ||
|
|
c641fae2b9 | ||
|
|
526df1cb9c | ||
|
|
f4e9daec80 | ||
|
|
3e2cd839cc | ||
|
|
b9a790ba20 | ||
|
|
aaad1bc0b3 | ||
|
|
d7f4a5c874 | ||
|
|
f8ca8ae942 | ||
|
|
2805ea4926 | ||
|
|
36ac5dc44e | ||
|
|
49a976810b | ||
|
|
f6d605a3aa | ||
|
|
6901323827 | ||
|
|
186fe0503f | ||
|
|
e990e5ffd5 | ||
|
|
3d7207d8c5 | ||
|
|
4b31352e4f | ||
|
|
278a8b1ec2 | ||
|
|
b96a0875f3 | ||
|
|
4e62e20fa8 | ||
|
|
2729fb14d6 | ||
|
|
5dab6f67f2 | ||
|
|
3aa48fcd18 | ||
|
|
e5fd5a0d4c | ||
|
|
ad5a22a69b | ||
|
|
43b3114237 | ||
|
|
a83109cb05 | ||
|
|
72327a352e | ||
|
|
35ef895cff | ||
|
|
52e4293e90 | ||
|
|
460d109bd2 | ||
|
|
7d0f17fe1a | ||
|
|
cff6fcf52e | ||
|
|
4083aa82b8 | ||
|
|
ac61ef1f81 | ||
|
|
924c421b75 | ||
|
|
71262d18a0 | ||
|
|
9645660d87 | ||
|
|
13a955d45a | ||
|
|
7a06c72534 | ||
|
|
cdb572f347 | ||
|
|
8f44b06244 | ||
|
|
e8b81c1ff6 | ||
|
|
ab443fa50f | ||
|
|
25d55fec24 | ||
|
|
61f8b5c7f4 | ||
|
|
6596afc562 | ||
|
|
3e8a34c5f3 | ||
|
|
1101310845 | ||
|
|
0745028c06 | ||
|
|
915d03a66a | ||
|
|
e07ebc21b9 | ||
|
|
9566075dee | ||
|
|
7076afecfb | ||
|
|
526f8be676 | ||
|
|
c01818f57b | ||
|
|
f5e3d104e2 | ||
|
|
ba9dca4b05 | ||
|
|
efb7da316a |
@@ -1,2 +0,0 @@
|
|||||||
defaults
|
|
||||||
IE 11
|
|
||||||
1
.gitattributes
vendored
1
.gitattributes
vendored
@@ -8,4 +8,3 @@
|
|||||||
# Same thing for following files, but they don't have an sh extension
|
# Same thing for following files, but they don't have an sh extension
|
||||||
pre-commit eol=lf
|
pre-commit eol=lf
|
||||||
webpack-dev-server eol=lf
|
webpack-dev-server eol=lf
|
||||||
install-bundler eol=lf
|
|
||||||
10
.github/PULL_REQUEST_TEMPLATE.md
vendored
10
.github/PULL_REQUEST_TEMPLATE.md
vendored
@@ -1,4 +1,4 @@
|
|||||||
#### What? Why?
|
## What? Why?
|
||||||
|
|
||||||
- Closes # <!-- Insert issue number here. -->
|
- Closes # <!-- Insert issue number here. -->
|
||||||
|
|
||||||
@@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
#### What should we test?
|
## What should we test?
|
||||||
<!-- List which features should be tested and how.
|
<!-- List which features should be tested and how.
|
||||||
This can be similar to the Steps to Reproduce in the issue.
|
This can be similar to the Steps to Reproduce in the issue.
|
||||||
Also think of other parts of the app which could be affected
|
Also think of other parts of the app which could be affected
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
- Visit ... page.
|
- Visit ... page.
|
||||||
-
|
-
|
||||||
|
|
||||||
#### Release notes
|
## Release notes
|
||||||
|
|
||||||
<!-- Please select one for your PR and delete the other. -->
|
<!-- Please select one for your PR and delete the other. -->
|
||||||
|
|
||||||
@@ -33,12 +33,12 @@ Changelog Category (reviewers may add a label for the release notes):
|
|||||||
The title of the pull request will be included in the release notes.
|
The title of the pull request will be included in the release notes.
|
||||||
|
|
||||||
|
|
||||||
#### Dependencies
|
## Dependencies
|
||||||
<!-- Does this PR depend on another one?
|
<!-- Does this PR depend on another one?
|
||||||
Add the link or remove this section. -->
|
Add the link or remove this section. -->
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#### Documentation updates
|
## Documentation updates
|
||||||
<!-- Are there any wiki pages that need updating after merging this PR?
|
<!-- Are there any wiki pages that need updating after merging this PR?
|
||||||
List them here or remove this section. -->
|
List them here or remove this section. -->
|
||||||
|
|||||||
29
.github/dependabot.yml
vendored
29
.github/dependabot.yml
vendored
@@ -4,12 +4,35 @@
|
|||||||
# Most of the configuration here is not used for security updates though.
|
# Most of the configuration here is not used for security updates though.
|
||||||
|
|
||||||
version: 2
|
version: 2
|
||||||
|
|
||||||
|
multi-ecosystem-groups:
|
||||||
|
turbo_power:
|
||||||
|
schedule:
|
||||||
|
interval: "daily"
|
||||||
|
|
||||||
updates:
|
updates:
|
||||||
|
- package-ecosystem: "bundler"
|
||||||
|
directory: "/"
|
||||||
|
patterns: ["turbo_power"]
|
||||||
|
multi-ecosystem-group: "turbo_power"
|
||||||
|
|
||||||
|
# Only specific requirements are specified in Gemfile, so don't touch it.
|
||||||
|
versioning-strategy: lockfile-only
|
||||||
|
|
||||||
|
- package-ecosystem: "npm"
|
||||||
|
directory: "/"
|
||||||
|
patterns: ["turbo_power"]
|
||||||
|
multi-ecosystem-group: "turbo_power"
|
||||||
|
|
||||||
|
# Only specific requirements are specified in package.json, so don't touch it.
|
||||||
|
versioning-strategy: lockfile-only
|
||||||
|
|
||||||
- package-ecosystem: "bundler"
|
- package-ecosystem: "bundler"
|
||||||
directory: "/"
|
directory: "/"
|
||||||
schedule:
|
schedule:
|
||||||
interval: "daily"
|
interval: "daily"
|
||||||
|
cooldown:
|
||||||
|
default-days: 7
|
||||||
|
|
||||||
# Only specific requirements are specified in Gemfile, so don't touch it.
|
# Only specific requirements are specified in Gemfile, so don't touch it.
|
||||||
versioning-strategy: lockfile-only
|
versioning-strategy: lockfile-only
|
||||||
@@ -18,6 +41,8 @@ updates:
|
|||||||
directory: "/"
|
directory: "/"
|
||||||
schedule:
|
schedule:
|
||||||
interval: "daily"
|
interval: "daily"
|
||||||
|
cooldown:
|
||||||
|
default-days: 7
|
||||||
|
|
||||||
# All versions are specified in package.json, so please update them.
|
# Only specific requirements are specified in package.json, so don't touch it.
|
||||||
versioning-strategy: increase
|
versioning-strategy: lockfile-only
|
||||||
|
|||||||
1
.github/workflows/linters.yml
vendored
1
.github/workflows/linters.yml
vendored
@@ -2,7 +2,6 @@ name: Linters
|
|||||||
on: [pull_request]
|
on: [pull_request]
|
||||||
permissions:
|
permissions:
|
||||||
contents: read # to fetch code (actions/checkout)
|
contents: read # to fetch code (actions/checkout)
|
||||||
checks: write # to post check annotations
|
|
||||||
jobs:
|
jobs:
|
||||||
lint:
|
lint:
|
||||||
name: reviewdog
|
name: reviewdog
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# This configuration was generated by
|
# This configuration was generated by
|
||||||
# `rubocop --auto-gen-config --auto-gen-only-exclude --exclude-limit 1400 --no-auto-gen-timestamp`
|
# `rubocop --auto-gen-config --auto-gen-only-exclude --exclude-limit 1400 --no-auto-gen-timestamp`
|
||||||
# using RuboCop version 1.81.6.
|
# using RuboCop version 1.81.7.
|
||||||
# The point is for the user to remove these configuration records
|
# The point is for the user to remove these configuration records
|
||||||
# one by one as the offenses are removed from the code base.
|
# one by one as the offenses are removed from the code base.
|
||||||
# Note that changes in the inspected code, or installation of new
|
# Note that changes in the inspected code, or installation of new
|
||||||
@@ -80,7 +80,7 @@ Metrics/BlockNesting:
|
|||||||
Exclude:
|
Exclude:
|
||||||
- 'app/models/spree/payment/processing.rb'
|
- 'app/models/spree/payment/processing.rb'
|
||||||
|
|
||||||
# Offense count: 48
|
# Offense count: 49
|
||||||
# Configuration parameters: CountComments, Max, CountAsOne.
|
# Configuration parameters: CountComments, Max, CountAsOne.
|
||||||
Metrics/ClassLength:
|
Metrics/ClassLength:
|
||||||
Exclude:
|
Exclude:
|
||||||
@@ -122,6 +122,7 @@ Metrics/ClassLength:
|
|||||||
- 'app/services/order_cycles/form_service.rb'
|
- 'app/services/order_cycles/form_service.rb'
|
||||||
- 'app/services/orders/sync_service.rb'
|
- 'app/services/orders/sync_service.rb'
|
||||||
- 'app/services/permissions/order.rb'
|
- 'app/services/permissions/order.rb'
|
||||||
|
- 'app/services/products_renderer.rb'
|
||||||
- 'app/services/sets/product_set.rb'
|
- 'app/services/sets/product_set.rb'
|
||||||
- 'engines/order_management/app/services/order_management/order/updater.rb'
|
- 'engines/order_management/app/services/order_management/order/updater.rb'
|
||||||
- 'lib/open_food_network/enterprise_fee_calculator.rb'
|
- 'lib/open_food_network/enterprise_fee_calculator.rb'
|
||||||
@@ -133,7 +134,7 @@ Metrics/ClassLength:
|
|||||||
- 'lib/reporting/reports/enterprise_fee_summary/scope.rb'
|
- 'lib/reporting/reports/enterprise_fee_summary/scope.rb'
|
||||||
- 'lib/reporting/reports/xero_invoices/base.rb'
|
- 'lib/reporting/reports/xero_invoices/base.rb'
|
||||||
|
|
||||||
# Offense count: 35
|
# Offense count: 37
|
||||||
# Configuration parameters: AllowedMethods, AllowedPatterns, Max.
|
# Configuration parameters: AllowedMethods, AllowedPatterns, Max.
|
||||||
Metrics/CyclomaticComplexity:
|
Metrics/CyclomaticComplexity:
|
||||||
Exclude:
|
Exclude:
|
||||||
@@ -234,7 +235,7 @@ Naming/MethodParameterName:
|
|||||||
Exclude:
|
Exclude:
|
||||||
- 'engines/dfc_provider/lib/dfc_provider/catalog_item.rb'
|
- 'engines/dfc_provider/lib/dfc_provider/catalog_item.rb'
|
||||||
|
|
||||||
# Offense count: 59
|
# Offense count: 60
|
||||||
# Configuration parameters: Mode, AllowedMethods, AllowedPatterns, AllowBangMethods, WaywardPredicates.
|
# Configuration parameters: Mode, AllowedMethods, AllowedPatterns, AllowBangMethods, WaywardPredicates.
|
||||||
# AllowedMethods: call
|
# AllowedMethods: call
|
||||||
# WaywardPredicates: nonzero?
|
# WaywardPredicates: nonzero?
|
||||||
@@ -335,6 +336,24 @@ Rails/OrderArguments:
|
|||||||
- 'spec/services/orders/generate_invoice_service_spec.rb'
|
- 'spec/services/orders/generate_invoice_service_spec.rb'
|
||||||
- 'spec/system/admin/order_cycles/simple_spec.rb'
|
- 'spec/system/admin/order_cycles/simple_spec.rb'
|
||||||
|
|
||||||
|
# Offense count: 3
|
||||||
|
# This cop supports safe autocorrection (--autocorrect).
|
||||||
|
Rails/Presence:
|
||||||
|
Exclude:
|
||||||
|
- 'app/controllers/admin/enterprises_controller.rb'
|
||||||
|
- 'app/models/spree/product.rb'
|
||||||
|
|
||||||
|
# Offense count: 6
|
||||||
|
# This cop supports safe autocorrection (--autocorrect).
|
||||||
|
# Configuration parameters: Severity.
|
||||||
|
Rails/RedirectBackOrTo:
|
||||||
|
Exclude:
|
||||||
|
- 'app/controllers/admin/order_cycles_controller.rb'
|
||||||
|
- 'app/controllers/locales_controller.rb'
|
||||||
|
- 'app/controllers/spree/admin/invoices_controller.rb'
|
||||||
|
- 'app/controllers/spree/admin/orders_controller.rb'
|
||||||
|
- 'app/controllers/spree/admin/return_authorizations_controller.rb'
|
||||||
|
|
||||||
# Offense count: 1
|
# Offense count: 1
|
||||||
# Configuration parameters: TransactionMethods.
|
# Configuration parameters: TransactionMethods.
|
||||||
Rails/TransactionExitStatement:
|
Rails/TransactionExitStatement:
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
3.2.9
|
3.4.8
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
FROM ruby:3.2.9-alpine3.19 AS base
|
FROM ruby:3.4.8-alpine3.19 AS base
|
||||||
ENV LANG=C.UTF-8 \
|
ENV LANG=C.UTF-8 \
|
||||||
LC_ALL=C.UTF-8 \
|
LC_ALL=C.UTF-8 \
|
||||||
TZ=Europe/London \
|
TZ=Europe/London \
|
||||||
@@ -31,4 +31,4 @@ FROM development-base
|
|||||||
COPY . $RAILS_ROOT
|
COPY . $RAILS_ROOT
|
||||||
COPY Gemfile Gemfile.lock ./
|
COPY Gemfile Gemfile.lock ./
|
||||||
RUN bundle install --jobs "$(nproc)"
|
RUN bundle install --jobs "$(nproc)"
|
||||||
COPY --from=yarn-dependencies $RAILS_ROOT/node_modules ./node_modules
|
COPY --from=yarn-dependencies $RAILS_ROOT/node_modules ./node_modules
|
||||||
|
|||||||
@@ -83,11 +83,8 @@ RUN wget https://chromedriver.storage.googleapis.com/2.41/chromedriver_linux64.z
|
|||||||
# Copy code and install app dependencies
|
# Copy code and install app dependencies
|
||||||
COPY . /usr/src/app/
|
COPY . /usr/src/app/
|
||||||
|
|
||||||
# Install Bundler
|
|
||||||
RUN ./script/install-bundler
|
|
||||||
|
|
||||||
# Install front-end dependencies
|
# Install front-end dependencies
|
||||||
RUN yarn install
|
RUN yarn install
|
||||||
|
|
||||||
# Run bundler install in parallel with the amount of available CPUs
|
# Run bundler install in parallel with the amount of available CPUs
|
||||||
RUN bundle install --jobs="$(nproc)"
|
RUN bundle install --jobs="$(nproc)"
|
||||||
|
|||||||
18
Gemfile
18
Gemfile
@@ -1,6 +1,6 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
source 'https://rubygems.org'
|
source 'https://gem.coop'
|
||||||
git_source(:github) { |repo_name| "https://github.com/#{repo_name}.git" }
|
git_source(:github) { |repo_name| "https://github.com/#{repo_name}.git" }
|
||||||
|
|
||||||
ruby File.read('.ruby-version').chomp
|
ruby File.read('.ruby-version').chomp
|
||||||
@@ -14,11 +14,11 @@ gem "active_storage_validations"
|
|||||||
gem "aws-sdk-s3", require: false
|
gem "aws-sdk-s3", require: false
|
||||||
gem "image_processing"
|
gem "image_processing"
|
||||||
|
|
||||||
gem 'activemerchant', '>= 1.78.0'
|
gem 'activemerchant'
|
||||||
gem 'angular-rails-templates', '>= 0.3.0'
|
gem 'angular-rails-templates'
|
||||||
gem 'ransack', '~> 4.1.0'
|
gem 'ransack', '~> 4.1.0'
|
||||||
gem 'responders'
|
gem 'responders'
|
||||||
gem 'webpacker', '~> 5'
|
gem 'shakapacker', '8.4.0'
|
||||||
|
|
||||||
# Indirect dependency but we access it directly in JS specs.
|
# Indirect dependency but we access it directly in JS specs.
|
||||||
# It turns out to be hard to upgrade but please do if you can.
|
# It turns out to be hard to upgrade but please do if you can.
|
||||||
@@ -49,7 +49,7 @@ gem 'acts_as_list', '1.0.4'
|
|||||||
gem 'cancancan', '~> 1.15.0'
|
gem 'cancancan', '~> 1.15.0'
|
||||||
gem 'digest'
|
gem 'digest'
|
||||||
gem 'ffaker'
|
gem 'ffaker'
|
||||||
gem 'highline', '2.0.3' # Necessary for the install generator
|
gem 'highline'
|
||||||
gem 'json'
|
gem 'json'
|
||||||
gem 'monetize', '~> 1.11'
|
gem 'monetize', '~> 1.11'
|
||||||
gem 'paranoia', '~> 2.4'
|
gem 'paranoia', '~> 2.4'
|
||||||
@@ -57,7 +57,8 @@ gem 'state_machines-activerecord'
|
|||||||
gem 'stringex', '~> 2.8.5', require: false
|
gem 'stringex', '~> 2.8.5', require: false
|
||||||
|
|
||||||
gem 'paypal-sdk-merchant', '1.117.2'
|
gem 'paypal-sdk-merchant', '1.117.2'
|
||||||
gem 'stripe', '~> 13'
|
gem 'stripe', '~> 15'
|
||||||
|
gem "taler"
|
||||||
|
|
||||||
gem 'devise'
|
gem 'devise'
|
||||||
gem 'devise-encryptable'
|
gem 'devise-encryptable'
|
||||||
@@ -111,7 +112,7 @@ gem "turbo_power"
|
|||||||
gem "turbo-rails"
|
gem "turbo-rails"
|
||||||
|
|
||||||
gem 'combine_pdf'
|
gem 'combine_pdf'
|
||||||
gem 'wicked_pdf'
|
gem 'wicked_pdf', github: "openfoodfoundation/wicked_pdf", branch: "master"
|
||||||
gem 'wkhtmltopdf-binary'
|
gem 'wkhtmltopdf-binary'
|
||||||
|
|
||||||
gem 'immigrant'
|
gem 'immigrant'
|
||||||
@@ -126,7 +127,8 @@ gem 'angular_rails_csrf'
|
|||||||
|
|
||||||
gem 'jquery-rails', '4.4.0'
|
gem 'jquery-rails', '4.4.0'
|
||||||
gem 'jquery-ui-rails', '~> 4.2'
|
gem 'jquery-ui-rails', '~> 4.2'
|
||||||
gem "select2-rails", github: "openfoodfoundation/select2-rails", branch: "v349_with_thor_v1"
|
gem "select2-rails", github: "openfoodfoundation/select2-rails",
|
||||||
|
branch: "v349_with-relaxed-dependencies"
|
||||||
|
|
||||||
gem 'good_migrations'
|
gem 'good_migrations'
|
||||||
|
|
||||||
|
|||||||
470
Gemfile.lock
470
Gemfile.lock
@@ -10,13 +10,21 @@ GIT
|
|||||||
|
|
||||||
GIT
|
GIT
|
||||||
remote: https://github.com/openfoodfoundation/select2-rails.git
|
remote: https://github.com/openfoodfoundation/select2-rails.git
|
||||||
revision: fc240e85fbdf1878ff3c39d972c0cd9a312f5ed4
|
revision: 9693e0cc5b04938da46692d3fa83aa8934791981
|
||||||
branch: v349_with_thor_v1
|
branch: v349_with-relaxed-dependencies
|
||||||
specs:
|
specs:
|
||||||
select2-rails (3.4.9)
|
select2-rails (3.4.9)
|
||||||
sass-rails
|
|
||||||
thor (>= 0.14)
|
thor (>= 0.14)
|
||||||
|
|
||||||
|
GIT
|
||||||
|
remote: https://github.com/openfoodfoundation/wicked_pdf.git
|
||||||
|
revision: bce498de547cdf00d037fdbec29fae844d69ee8e
|
||||||
|
branch: master
|
||||||
|
specs:
|
||||||
|
wicked_pdf (2.8.1)
|
||||||
|
activesupport
|
||||||
|
ostruct
|
||||||
|
|
||||||
GIT
|
GIT
|
||||||
remote: https://github.com/podia/stimulus_reflex_testing.git
|
remote: https://github.com/podia/stimulus_reflex_testing.git
|
||||||
revision: abac2ee34de347c589795b4d1a8e83e0baafb201
|
revision: abac2ee34de347c589795b4d1a8e83e0baafb201
|
||||||
@@ -46,38 +54,39 @@ PATH
|
|||||||
web (0.0.1)
|
web (0.0.1)
|
||||||
|
|
||||||
GEM
|
GEM
|
||||||
remote: https://rubygems.org/
|
remote: https://gem.coop/
|
||||||
specs:
|
specs:
|
||||||
Ascii85 (2.0.1)
|
Ascii85 (2.0.1)
|
||||||
actioncable (7.1.5.2)
|
actioncable (7.1.6)
|
||||||
actionpack (= 7.1.5.2)
|
actionpack (= 7.1.6)
|
||||||
activesupport (= 7.1.5.2)
|
activesupport (= 7.1.6)
|
||||||
nio4r (~> 2.0)
|
nio4r (~> 2.0)
|
||||||
websocket-driver (>= 0.6.1)
|
websocket-driver (>= 0.6.1)
|
||||||
zeitwerk (~> 2.6)
|
zeitwerk (~> 2.6)
|
||||||
actionmailbox (7.1.5.2)
|
actionmailbox (7.1.6)
|
||||||
actionpack (= 7.1.5.2)
|
actionpack (= 7.1.6)
|
||||||
activejob (= 7.1.5.2)
|
activejob (= 7.1.6)
|
||||||
activerecord (= 7.1.5.2)
|
activerecord (= 7.1.6)
|
||||||
activestorage (= 7.1.5.2)
|
activestorage (= 7.1.6)
|
||||||
activesupport (= 7.1.5.2)
|
activesupport (= 7.1.6)
|
||||||
mail (>= 2.7.1)
|
mail (>= 2.7.1)
|
||||||
net-imap
|
net-imap
|
||||||
net-pop
|
net-pop
|
||||||
net-smtp
|
net-smtp
|
||||||
actionmailer (7.1.5.2)
|
actionmailer (7.1.6)
|
||||||
actionpack (= 7.1.5.2)
|
actionpack (= 7.1.6)
|
||||||
actionview (= 7.1.5.2)
|
actionview (= 7.1.6)
|
||||||
activejob (= 7.1.5.2)
|
activejob (= 7.1.6)
|
||||||
activesupport (= 7.1.5.2)
|
activesupport (= 7.1.6)
|
||||||
mail (~> 2.5, >= 2.5.4)
|
mail (~> 2.5, >= 2.5.4)
|
||||||
net-imap
|
net-imap
|
||||||
net-pop
|
net-pop
|
||||||
net-smtp
|
net-smtp
|
||||||
rails-dom-testing (~> 2.2)
|
rails-dom-testing (~> 2.2)
|
||||||
actionpack (7.1.5.2)
|
actionpack (7.1.6)
|
||||||
actionview (= 7.1.5.2)
|
actionview (= 7.1.6)
|
||||||
activesupport (= 7.1.5.2)
|
activesupport (= 7.1.6)
|
||||||
|
cgi
|
||||||
nokogiri (>= 1.8.5)
|
nokogiri (>= 1.8.5)
|
||||||
racc
|
racc
|
||||||
rack (>= 2.2.4)
|
rack (>= 2.2.4)
|
||||||
@@ -87,40 +96,42 @@ GEM
|
|||||||
rails-html-sanitizer (~> 1.6)
|
rails-html-sanitizer (~> 1.6)
|
||||||
actionpack-action_caching (1.2.2)
|
actionpack-action_caching (1.2.2)
|
||||||
actionpack (>= 4.0.0)
|
actionpack (>= 4.0.0)
|
||||||
actiontext (7.1.5.2)
|
actiontext (7.1.6)
|
||||||
actionpack (= 7.1.5.2)
|
actionpack (= 7.1.6)
|
||||||
activerecord (= 7.1.5.2)
|
activerecord (= 7.1.6)
|
||||||
activestorage (= 7.1.5.2)
|
activestorage (= 7.1.6)
|
||||||
activesupport (= 7.1.5.2)
|
activesupport (= 7.1.6)
|
||||||
globalid (>= 0.6.0)
|
globalid (>= 0.6.0)
|
||||||
nokogiri (>= 1.8.5)
|
nokogiri (>= 1.8.5)
|
||||||
actionview (7.1.5.2)
|
actionview (7.1.6)
|
||||||
activesupport (= 7.1.5.2)
|
activesupport (= 7.1.6)
|
||||||
builder (~> 3.1)
|
builder (~> 3.1)
|
||||||
|
cgi
|
||||||
erubi (~> 1.11)
|
erubi (~> 1.11)
|
||||||
rails-dom-testing (~> 2.2)
|
rails-dom-testing (~> 2.2)
|
||||||
rails-html-sanitizer (~> 1.6)
|
rails-html-sanitizer (~> 1.6)
|
||||||
active_model_serializers (0.8.4)
|
active_model_serializers (0.8.4)
|
||||||
activemodel (>= 3.0)
|
activemodel (>= 3.0)
|
||||||
active_storage_validations (1.1.4)
|
active_storage_validations (3.0.2)
|
||||||
activejob (>= 5.2.0)
|
activejob (>= 6.1.4)
|
||||||
activemodel (>= 5.2.0)
|
activemodel (>= 6.1.4)
|
||||||
activestorage (>= 5.2.0)
|
activestorage (>= 6.1.4)
|
||||||
activesupport (>= 5.2.0)
|
activesupport (>= 6.1.4)
|
||||||
activejob (7.1.5.2)
|
marcel (>= 1.0.3)
|
||||||
activesupport (= 7.1.5.2)
|
activejob (7.1.6)
|
||||||
|
activesupport (= 7.1.6)
|
||||||
globalid (>= 0.3.6)
|
globalid (>= 0.3.6)
|
||||||
activemerchant (1.133.0)
|
activemerchant (1.137.0)
|
||||||
activesupport (>= 4.2)
|
activesupport (>= 4.2)
|
||||||
builder (>= 2.1.2, < 4.0.0)
|
builder (>= 2.1.2, < 4.0.0)
|
||||||
i18n (>= 0.6.9)
|
i18n (>= 0.6.9)
|
||||||
nokogiri (~> 1.4)
|
nokogiri (~> 1.4)
|
||||||
rexml (~> 3.2.5)
|
rexml (~> 3.3, >= 3.3.4)
|
||||||
activemodel (7.1.5.2)
|
activemodel (7.1.6)
|
||||||
activesupport (= 7.1.5.2)
|
activesupport (= 7.1.6)
|
||||||
activerecord (7.1.5.2)
|
activerecord (7.1.6)
|
||||||
activemodel (= 7.1.5.2)
|
activemodel (= 7.1.6)
|
||||||
activesupport (= 7.1.5.2)
|
activesupport (= 7.1.6)
|
||||||
timeout (>= 0.4.0)
|
timeout (>= 0.4.0)
|
||||||
activerecord-import (2.2.0)
|
activerecord-import (2.2.0)
|
||||||
activerecord (>= 4.2)
|
activerecord (>= 4.2)
|
||||||
@@ -132,13 +143,13 @@ GEM
|
|||||||
cgi (>= 0.3.6)
|
cgi (>= 0.3.6)
|
||||||
rack (>= 2.0.8, < 4)
|
rack (>= 2.0.8, < 4)
|
||||||
railties (>= 7.0)
|
railties (>= 7.0)
|
||||||
activestorage (7.1.5.2)
|
activestorage (7.1.6)
|
||||||
actionpack (= 7.1.5.2)
|
actionpack (= 7.1.6)
|
||||||
activejob (= 7.1.5.2)
|
activejob (= 7.1.6)
|
||||||
activerecord (= 7.1.5.2)
|
activerecord (= 7.1.6)
|
||||||
activesupport (= 7.1.5.2)
|
activesupport (= 7.1.6)
|
||||||
marcel (~> 1.0)
|
marcel (~> 1.0)
|
||||||
activesupport (7.1.5.2)
|
activesupport (7.1.6)
|
||||||
base64
|
base64
|
||||||
benchmark (>= 0.3)
|
benchmark (>= 0.3)
|
||||||
bigdecimal
|
bigdecimal
|
||||||
@@ -151,42 +162,46 @@ GEM
|
|||||||
mutex_m
|
mutex_m
|
||||||
securerandom (>= 0.3)
|
securerandom (>= 0.3)
|
||||||
tzinfo (~> 2.0)
|
tzinfo (~> 2.0)
|
||||||
acts-as-taggable-on (10.0.0)
|
acts-as-taggable-on (13.0.0)
|
||||||
activerecord (>= 6.1, < 7.2)
|
activerecord (>= 7.1, < 8.2)
|
||||||
|
zeitwerk (>= 2.4, < 3.0)
|
||||||
acts_as_list (1.0.4)
|
acts_as_list (1.0.4)
|
||||||
activerecord (>= 4.2)
|
activerecord (>= 4.2)
|
||||||
addressable (2.8.7)
|
addressable (2.8.8)
|
||||||
public_suffix (>= 2.0.2, < 7.0)
|
public_suffix (>= 2.0.2, < 8.0)
|
||||||
aes_key_wrap (1.1.0)
|
aes_key_wrap (1.1.0)
|
||||||
afm (0.2.2)
|
afm (0.2.2)
|
||||||
angular-rails-templates (1.2.1)
|
angular-rails-templates (1.4.0)
|
||||||
railties (>= 5.0, < 7.2)
|
railties (>= 5.0, < 8.2)
|
||||||
sprockets (>= 3.0, < 5)
|
sprockets (>= 3.0, < 5)
|
||||||
sprockets-rails
|
sprockets-rails
|
||||||
tilt
|
tilt
|
||||||
angular_rails_csrf (6.0.0)
|
angular_rails_csrf (7.0.2)
|
||||||
railties (>= 3, < 8)
|
railties (>= 3, < 9)
|
||||||
angularjs-file-upload-rails (2.4.1)
|
angularjs-file-upload-rails (2.4.1)
|
||||||
angularjs-rails (1.8.0)
|
angularjs-rails (1.8.0)
|
||||||
arel-helpers (2.14.0)
|
arel-helpers (2.17.0)
|
||||||
activerecord (>= 3.1.0, < 8)
|
activerecord (>= 3.1.0)
|
||||||
ast (2.4.3)
|
ast (2.4.3)
|
||||||
attr_required (1.0.2)
|
attr_required (1.0.2)
|
||||||
aws-eventstream (1.3.0)
|
aws-eventstream (1.4.0)
|
||||||
aws-partitions (1.929.0)
|
aws-partitions (1.1196.0)
|
||||||
aws-sdk-core (3.196.1)
|
aws-sdk-core (3.240.0)
|
||||||
aws-eventstream (~> 1, >= 1.3.0)
|
aws-eventstream (~> 1, >= 1.3.0)
|
||||||
aws-partitions (~> 1, >= 1.651.0)
|
aws-partitions (~> 1, >= 1.992.0)
|
||||||
aws-sigv4 (~> 1.8)
|
aws-sigv4 (~> 1.9)
|
||||||
|
base64
|
||||||
|
bigdecimal
|
||||||
jmespath (~> 1, >= 1.6.1)
|
jmespath (~> 1, >= 1.6.1)
|
||||||
aws-sdk-kms (1.81.0)
|
logger
|
||||||
aws-sdk-core (~> 3, >= 3.193.0)
|
aws-sdk-kms (1.118.0)
|
||||||
aws-sigv4 (~> 1.1)
|
aws-sdk-core (~> 3, >= 3.239.1)
|
||||||
aws-sdk-s3 (1.151.0)
|
aws-sigv4 (~> 1.5)
|
||||||
aws-sdk-core (~> 3, >= 3.194.0)
|
aws-sdk-s3 (1.208.0)
|
||||||
|
aws-sdk-core (~> 3, >= 3.234.0)
|
||||||
aws-sdk-kms (~> 1)
|
aws-sdk-kms (~> 1)
|
||||||
aws-sigv4 (~> 1.8)
|
aws-sigv4 (~> 1.5)
|
||||||
aws-sigv4 (1.8.0)
|
aws-sigv4 (1.12.1)
|
||||||
aws-eventstream (~> 1, >= 1.0.2)
|
aws-eventstream (~> 1, >= 1.0.2)
|
||||||
base64 (0.3.0)
|
base64 (0.3.0)
|
||||||
bcp47_spec (0.2.1)
|
bcp47_spec (0.2.1)
|
||||||
@@ -195,9 +210,9 @@ GEM
|
|||||||
bigdecimal (3.3.1)
|
bigdecimal (3.3.1)
|
||||||
bindata (2.5.1)
|
bindata (2.5.1)
|
||||||
bindex (0.8.1)
|
bindex (0.8.1)
|
||||||
bootsnap (1.18.3)
|
bootsnap (1.19.0)
|
||||||
msgpack (~> 1.2)
|
msgpack (~> 1.2)
|
||||||
bugsnag (6.26.4)
|
bugsnag (6.28.0)
|
||||||
concurrent-ruby (~> 1.0)
|
concurrent-ruby (~> 1.0)
|
||||||
builder (3.3.0)
|
builder (3.3.0)
|
||||||
bullet (8.0.8)
|
bullet (8.0.8)
|
||||||
@@ -222,7 +237,7 @@ GEM
|
|||||||
xpath (~> 3.2)
|
xpath (~> 3.2)
|
||||||
capybara-shadowdom (0.3.0)
|
capybara-shadowdom (0.3.0)
|
||||||
capybara
|
capybara
|
||||||
caxlsx (3.3.0)
|
caxlsx (4.0.0)
|
||||||
htmlentities (~> 4.3, >= 4.3.4)
|
htmlentities (~> 4.3, >= 4.3.4)
|
||||||
marcel (~> 1.0)
|
marcel (~> 1.0)
|
||||||
nokogiri (~> 1.10, >= 1.10.4)
|
nokogiri (~> 1.10, >= 1.10.4)
|
||||||
@@ -239,32 +254,32 @@ GEM
|
|||||||
coffee-script-source
|
coffee-script-source
|
||||||
execjs
|
execjs
|
||||||
coffee-script-source (1.12.2)
|
coffee-script-source (1.12.2)
|
||||||
combine_pdf (1.0.26)
|
combine_pdf (1.0.31)
|
||||||
matrix
|
matrix
|
||||||
ruby-rc4 (>= 0.1.5)
|
ruby-rc4 (>= 0.1.5)
|
||||||
concurrent-ruby (1.3.5)
|
concurrent-ruby (1.3.5)
|
||||||
connection_pool (2.5.4)
|
connection_pool (2.5.5)
|
||||||
cookiejar (0.3.4)
|
cookiejar (0.3.4)
|
||||||
crack (1.0.0)
|
crack (1.0.1)
|
||||||
bigdecimal
|
bigdecimal
|
||||||
rexml
|
rexml
|
||||||
crass (1.0.6)
|
crass (1.0.6)
|
||||||
css_parser (1.17.1)
|
css_parser (1.21.1)
|
||||||
addressable
|
addressable
|
||||||
csv (3.3.0)
|
csv (3.3.5)
|
||||||
cuprite (0.15)
|
cuprite (0.15)
|
||||||
capybara (~> 3.0)
|
capybara (~> 3.0)
|
||||||
ferrum (~> 0.14.0)
|
ferrum (~> 0.14.0)
|
||||||
database_cleaner (2.0.2)
|
database_cleaner (2.1.0)
|
||||||
database_cleaner-active_record (>= 2, < 3)
|
database_cleaner-active_record (>= 2, < 3)
|
||||||
database_cleaner-active_record (2.1.0)
|
database_cleaner-active_record (2.2.2)
|
||||||
activerecord (>= 5.a)
|
activerecord (>= 5.a)
|
||||||
database_cleaner-core (~> 2.0.0)
|
database_cleaner-core (~> 2.0)
|
||||||
database_cleaner-core (2.0.1)
|
database_cleaner-core (2.0.1)
|
||||||
datafoodconsortium-connector (1.1.0)
|
datafoodconsortium-connector (1.2.0)
|
||||||
virtual_assembly-semantizer (~> 1.0, >= 1.0.5)
|
virtual_assembly-semantizer (~> 1.0, >= 1.0.5)
|
||||||
date (3.5.0)
|
date (3.5.0)
|
||||||
debug (1.9.2)
|
debug (1.11.0)
|
||||||
irb (~> 1.10)
|
irb (~> 1.10)
|
||||||
reline (>= 0.3.8)
|
reline (>= 0.3.8)
|
||||||
devise (4.9.4)
|
devise (4.9.4)
|
||||||
@@ -275,14 +290,15 @@ GEM
|
|||||||
warden (~> 1.2.3)
|
warden (~> 1.2.3)
|
||||||
devise-encryptable (0.2.0)
|
devise-encryptable (0.2.0)
|
||||||
devise (>= 2.1.0)
|
devise (>= 2.1.0)
|
||||||
devise-i18n (1.12.1)
|
devise-i18n (1.15.0)
|
||||||
devise (>= 4.9.0)
|
devise (>= 4.9.0)
|
||||||
|
rails-i18n
|
||||||
devise-token_authenticatable (1.1.0)
|
devise-token_authenticatable (1.1.0)
|
||||||
devise (>= 4.0.0, < 5.0.0)
|
devise (>= 4.0.0, < 5.0.0)
|
||||||
diff-lcs (1.6.2)
|
diff-lcs (1.6.2)
|
||||||
digest (3.2.0)
|
digest (3.2.1)
|
||||||
docile (1.4.1)
|
docile (1.4.1)
|
||||||
dotenv (3.1.2)
|
dotenv (3.2.0)
|
||||||
drb (2.2.3)
|
drb (2.2.3)
|
||||||
em-http-request (1.1.7)
|
em-http-request (1.1.7)
|
||||||
addressable (>= 2.3.4)
|
addressable (>= 2.3.4)
|
||||||
@@ -297,7 +313,7 @@ GEM
|
|||||||
eventmachine (>= 1.0.0.beta.1)
|
eventmachine (>= 1.0.0.beta.1)
|
||||||
email_validator (2.2.4)
|
email_validator (2.2.4)
|
||||||
activemodel
|
activemodel
|
||||||
erb (5.1.3)
|
erb (6.0.1)
|
||||||
erubi (1.13.1)
|
erubi (1.13.1)
|
||||||
et-orbi (1.3.0)
|
et-orbi (1.3.0)
|
||||||
tzinfo
|
tzinfo
|
||||||
@@ -321,13 +337,13 @@ GEM
|
|||||||
concurrent-ruby (~> 1.1)
|
concurrent-ruby (~> 1.1)
|
||||||
webrick (~> 1.7)
|
webrick (~> 1.7)
|
||||||
websocket-driver (>= 0.6, < 0.8)
|
websocket-driver (>= 0.6, < 0.8)
|
||||||
ffaker (2.23.0)
|
ffaker (2.25.0)
|
||||||
ffi (1.16.3)
|
ffi (1.17.2)
|
||||||
flipper (1.3.6)
|
flipper (1.3.6)
|
||||||
concurrent-ruby (< 2)
|
concurrent-ruby (< 2)
|
||||||
flipper-active_record (1.3.0)
|
flipper-active_record (1.3.6)
|
||||||
activerecord (>= 4.2, < 8)
|
activerecord (>= 4.2, < 9)
|
||||||
flipper (~> 1.3.0)
|
flipper (~> 1.3.6)
|
||||||
flipper-ui (1.3.6)
|
flipper-ui (1.3.6)
|
||||||
erubi (>= 1.0.0, < 2.0.0)
|
erubi (>= 1.0.0, < 2.0.0)
|
||||||
flipper (~> 1.3.6)
|
flipper (~> 1.3.6)
|
||||||
@@ -350,7 +366,8 @@ GEM
|
|||||||
fog-xml (0.1.3)
|
fog-xml (0.1.3)
|
||||||
fog-core
|
fog-core
|
||||||
nokogiri (>= 1.5.11, < 2.0.0)
|
nokogiri (>= 1.5.11, < 2.0.0)
|
||||||
foreman (0.88.1)
|
foreman (0.90.0)
|
||||||
|
thor (~> 1.4)
|
||||||
formatador (0.2.5)
|
formatador (0.2.5)
|
||||||
fugit (1.11.1)
|
fugit (1.11.1)
|
||||||
et-orbi (~> 1, >= 1.2.11)
|
et-orbi (~> 1, >= 1.2.11)
|
||||||
@@ -358,20 +375,20 @@ GEM
|
|||||||
fuubar (2.5.1)
|
fuubar (2.5.1)
|
||||||
rspec-core (~> 3.0)
|
rspec-core (~> 3.0)
|
||||||
ruby-progressbar (~> 1.4)
|
ruby-progressbar (~> 1.4)
|
||||||
geocoder (1.8.3)
|
geocoder (1.8.6)
|
||||||
base64 (>= 0.1.0)
|
base64 (>= 0.1.0)
|
||||||
csv (>= 3.0.0)
|
csv (>= 3.0.0)
|
||||||
globalid (1.3.0)
|
globalid (1.3.0)
|
||||||
activesupport (>= 6.1)
|
activesupport (>= 6.1)
|
||||||
gmaps4rails (2.1.2)
|
gmaps4rails (2.1.2)
|
||||||
good_migrations (0.2.1)
|
good_migrations (0.3.1)
|
||||||
activerecord (>= 3.1)
|
activerecord (>= 3.1)
|
||||||
railties (>= 3.1)
|
railties (>= 3.1)
|
||||||
haml (6.3.0)
|
haml (6.3.0)
|
||||||
temple (>= 0.8.2)
|
temple (>= 0.8.2)
|
||||||
thor
|
thor
|
||||||
tilt
|
tilt
|
||||||
haml_lint (0.67.0)
|
haml_lint (0.68.0)
|
||||||
haml (>= 5.0)
|
haml (>= 5.0)
|
||||||
parallel (~> 1.10)
|
parallel (~> 1.10)
|
||||||
rainbow
|
rainbow
|
||||||
@@ -380,8 +397,9 @@ GEM
|
|||||||
hashdiff (1.2.1)
|
hashdiff (1.2.1)
|
||||||
hashery (2.1.2)
|
hashery (2.1.2)
|
||||||
hashie (5.0.0)
|
hashie (5.0.0)
|
||||||
highline (2.0.3)
|
highline (3.1.2)
|
||||||
htmlentities (4.3.4)
|
reline
|
||||||
|
htmlentities (4.4.2)
|
||||||
http_parser.rb (0.8.0)
|
http_parser.rb (0.8.0)
|
||||||
i18n (1.14.7)
|
i18n (1.14.7)
|
||||||
concurrent-ruby (~> 1.0)
|
concurrent-ruby (~> 1.0)
|
||||||
@@ -398,8 +416,8 @@ GEM
|
|||||||
rainbow (>= 2.2.2, < 4.0)
|
rainbow (>= 2.2.2, < 4.0)
|
||||||
ruby-progressbar (~> 1.8, >= 1.8.1)
|
ruby-progressbar (~> 1.8, >= 1.8.1)
|
||||||
terminal-table (>= 1.5.1)
|
terminal-table (>= 1.5.1)
|
||||||
image_processing (1.12.2)
|
image_processing (1.14.0)
|
||||||
mini_magick (>= 4.9.5, < 5)
|
mini_magick (>= 4.9.5, < 6)
|
||||||
ruby-vips (>= 2.0.17, < 3)
|
ruby-vips (>= 2.0.17, < 3)
|
||||||
imagen (0.2.0)
|
imagen (0.2.0)
|
||||||
parser (>= 2.5, != 2.5.1.1)
|
parser (>= 2.5, != 2.5.1.1)
|
||||||
@@ -444,7 +462,7 @@ GEM
|
|||||||
rspec (>= 2.0, < 4.0)
|
rspec (>= 2.0, < 4.0)
|
||||||
jsonapi-serializer (2.2.0)
|
jsonapi-serializer (2.2.0)
|
||||||
activesupport (>= 4.2)
|
activesupport (>= 4.2)
|
||||||
jwt (2.8.1)
|
jwt (2.10.2)
|
||||||
base64
|
base64
|
||||||
knapsack_pro (8.4.0)
|
knapsack_pro (8.4.0)
|
||||||
rake
|
rake
|
||||||
@@ -469,8 +487,8 @@ GEM
|
|||||||
net-imap
|
net-imap
|
||||||
net-pop
|
net-pop
|
||||||
net-smtp
|
net-smtp
|
||||||
marcel (1.0.4)
|
marcel (1.1.0)
|
||||||
matrix (0.4.2)
|
matrix (0.4.3)
|
||||||
method_source (1.1.0)
|
method_source (1.1.0)
|
||||||
mime-types (3.7.0)
|
mime-types (3.7.0)
|
||||||
logger
|
logger
|
||||||
@@ -479,15 +497,16 @@ GEM
|
|||||||
mimemagic (0.4.3)
|
mimemagic (0.4.3)
|
||||||
nokogiri (~> 1)
|
nokogiri (~> 1)
|
||||||
rake
|
rake
|
||||||
mini_magick (4.13.2)
|
mini_magick (5.3.1)
|
||||||
|
logger
|
||||||
mini_mime (1.1.5)
|
mini_mime (1.1.5)
|
||||||
mini_portile2 (2.8.6)
|
mini_portile2 (2.8.6)
|
||||||
minitest (5.26.1)
|
minitest (5.26.2)
|
||||||
monetize (1.13.0)
|
monetize (1.13.0)
|
||||||
money (~> 6.12)
|
money (~> 6.12)
|
||||||
money (6.16.0)
|
money (6.16.0)
|
||||||
i18n (>= 0.6.4, <= 2)
|
i18n (>= 0.6.4, <= 2)
|
||||||
msgpack (1.7.2)
|
msgpack (1.8.0)
|
||||||
multi_json (1.17.0)
|
multi_json (1.17.0)
|
||||||
multi_xml (0.6.0)
|
multi_xml (0.6.0)
|
||||||
mutex_m (0.3.0)
|
mutex_m (0.3.0)
|
||||||
@@ -502,10 +521,9 @@ GEM
|
|||||||
timeout
|
timeout
|
||||||
net-smtp (0.5.1)
|
net-smtp (0.5.1)
|
||||||
net-protocol
|
net-protocol
|
||||||
newrelic_rpm (9.22.0)
|
newrelic_rpm (9.24.0)
|
||||||
nio4r (2.7.1)
|
nio4r (2.7.5)
|
||||||
nokogiri (1.18.10)
|
nokogiri (1.18.10)
|
||||||
mini_portile2 (~> 2.8.2)
|
|
||||||
racc (~> 1.4)
|
racc (~> 1.4)
|
||||||
nokogiri-html5-inference (0.3.0)
|
nokogiri-html5-inference (0.3.0)
|
||||||
nokogiri (~> 1.14)
|
nokogiri (~> 1.14)
|
||||||
@@ -542,9 +560,10 @@ GEM
|
|||||||
webfinger (~> 2.0)
|
webfinger (~> 2.0)
|
||||||
orm_adapter (0.5.0)
|
orm_adapter (0.5.0)
|
||||||
ostruct (0.6.1)
|
ostruct (0.6.1)
|
||||||
pagy (9.3.4)
|
package_json (0.2.0)
|
||||||
paper_trail (15.1.0)
|
pagy (9.4.0)
|
||||||
activerecord (>= 6.1)
|
paper_trail (17.0.0)
|
||||||
|
activerecord (>= 7.1)
|
||||||
request_store (~> 1.4)
|
request_store (~> 1.4)
|
||||||
parallel (1.27.0)
|
parallel (1.27.0)
|
||||||
paranoia (2.6.4)
|
paranoia (2.6.4)
|
||||||
@@ -567,15 +586,15 @@ GEM
|
|||||||
pp (0.6.3)
|
pp (0.6.3)
|
||||||
prettyprint
|
prettyprint
|
||||||
prettyprint (0.2.0)
|
prettyprint (0.2.0)
|
||||||
prism (1.6.0)
|
prism (1.7.0)
|
||||||
private_address_check (0.5.0)
|
private_address_check (0.5.0)
|
||||||
pry (0.15.2)
|
pry (0.15.2)
|
||||||
coderay (~> 1.1)
|
coderay (~> 1.1)
|
||||||
method_source (~> 1.0)
|
method_source (~> 1.0)
|
||||||
psych (5.2.6)
|
psych (5.3.1)
|
||||||
date
|
date
|
||||||
stringio
|
stringio
|
||||||
public_suffix (6.0.2)
|
public_suffix (7.0.0)
|
||||||
puffing-billy (4.0.2)
|
puffing-billy (4.0.2)
|
||||||
addressable (~> 2.5)
|
addressable (~> 2.5)
|
||||||
em-http-request (~> 1.1, >= 1.1.0)
|
em-http-request (~> 1.1, >= 1.1.0)
|
||||||
@@ -604,7 +623,7 @@ GEM
|
|||||||
rack-protection (3.2.0)
|
rack-protection (3.2.0)
|
||||||
base64 (>= 0.1.0)
|
base64 (>= 0.1.0)
|
||||||
rack (~> 2.2, >= 2.2.4)
|
rack (~> 2.2, >= 2.2.4)
|
||||||
rack-proxy (0.7.6)
|
rack-proxy (0.7.7)
|
||||||
rack
|
rack
|
||||||
rack-rewrite (1.5.1)
|
rack-rewrite (1.5.1)
|
||||||
rack-session (1.0.2)
|
rack-session (1.0.2)
|
||||||
@@ -615,20 +634,20 @@ GEM
|
|||||||
rackup (1.0.1)
|
rackup (1.0.1)
|
||||||
rack (< 3)
|
rack (< 3)
|
||||||
webrick
|
webrick
|
||||||
rails (7.1.5.2)
|
rails (7.1.6)
|
||||||
actioncable (= 7.1.5.2)
|
actioncable (= 7.1.6)
|
||||||
actionmailbox (= 7.1.5.2)
|
actionmailbox (= 7.1.6)
|
||||||
actionmailer (= 7.1.5.2)
|
actionmailer (= 7.1.6)
|
||||||
actionpack (= 7.1.5.2)
|
actionpack (= 7.1.6)
|
||||||
actiontext (= 7.1.5.2)
|
actiontext (= 7.1.6)
|
||||||
actionview (= 7.1.5.2)
|
actionview (= 7.1.6)
|
||||||
activejob (= 7.1.5.2)
|
activejob (= 7.1.6)
|
||||||
activemodel (= 7.1.5.2)
|
activemodel (= 7.1.6)
|
||||||
activerecord (= 7.1.5.2)
|
activerecord (= 7.1.6)
|
||||||
activestorage (= 7.1.5.2)
|
activestorage (= 7.1.6)
|
||||||
activesupport (= 7.1.5.2)
|
activesupport (= 7.1.6)
|
||||||
bundler (>= 1.15.0)
|
bundler (>= 1.15.0)
|
||||||
railties (= 7.1.5.2)
|
railties (= 7.1.6)
|
||||||
rails-controller-testing (1.0.5)
|
rails-controller-testing (1.0.5)
|
||||||
actionpack (>= 5.0.1.rc1)
|
actionpack (>= 5.0.1.rc1)
|
||||||
actionview (>= 5.0.1.rc1)
|
actionview (>= 5.0.1.rc1)
|
||||||
@@ -648,13 +667,15 @@ GEM
|
|||||||
rails-i18n (7.0.10)
|
rails-i18n (7.0.10)
|
||||||
i18n (>= 0.7, < 2)
|
i18n (>= 0.7, < 2)
|
||||||
railties (>= 6.0.0, < 8)
|
railties (>= 6.0.0, < 8)
|
||||||
railties (7.1.5.2)
|
railties (7.1.6)
|
||||||
actionpack (= 7.1.5.2)
|
actionpack (= 7.1.6)
|
||||||
activesupport (= 7.1.5.2)
|
activesupport (= 7.1.6)
|
||||||
|
cgi
|
||||||
irb
|
irb
|
||||||
rackup (>= 1.0.0)
|
rackup (>= 1.0.0)
|
||||||
rake (>= 12.2)
|
rake (>= 12.2)
|
||||||
thor (~> 1.0, >= 1.2.2)
|
thor (~> 1.0, >= 1.2.2)
|
||||||
|
tsort (>= 0.2)
|
||||||
zeitwerk (~> 2.6)
|
zeitwerk (~> 2.6)
|
||||||
rainbow (3.1.1)
|
rainbow (3.1.1)
|
||||||
rake (13.3.1)
|
rake (13.3.1)
|
||||||
@@ -665,34 +686,38 @@ GEM
|
|||||||
rb-fsevent (0.11.2)
|
rb-fsevent (0.11.2)
|
||||||
rb-inotify (0.10.1)
|
rb-inotify (0.10.1)
|
||||||
ffi (~> 1.0)
|
ffi (~> 1.0)
|
||||||
rdf (3.3.2)
|
rdf (3.3.4)
|
||||||
bcp47_spec (~> 0.2)
|
bcp47_spec (~> 0.2)
|
||||||
bigdecimal (~> 3.1, >= 3.1.5)
|
bigdecimal (~> 3.1, >= 3.1.5)
|
||||||
link_header (~> 0.0, >= 0.0.8)
|
link_header (~> 0.0, >= 0.0.8)
|
||||||
rdoc (6.15.1)
|
logger (~> 1.5)
|
||||||
|
ostruct (~> 0.6)
|
||||||
|
readline (~> 0.0)
|
||||||
|
rdoc (7.0.1)
|
||||||
erb
|
erb
|
||||||
psych (>= 4.0.0)
|
psych (>= 4.0.0)
|
||||||
tsort
|
tsort
|
||||||
redcarpet (3.6.0)
|
readline (0.0.4)
|
||||||
|
reline
|
||||||
|
redcarpet (3.6.1)
|
||||||
redis (5.4.1)
|
redis (5.4.1)
|
||||||
redis-client (>= 0.22.0)
|
redis-client (>= 0.22.0)
|
||||||
redis-client (0.26.1)
|
redis-client (0.26.1)
|
||||||
connection_pool
|
connection_pool
|
||||||
regexp_parser (2.11.3)
|
regexp_parser (2.11.3)
|
||||||
reline (0.6.2)
|
reline (0.6.3)
|
||||||
io-console (~> 0.5)
|
io-console (~> 0.5)
|
||||||
request_store (1.5.1)
|
request_store (1.7.0)
|
||||||
rack (>= 1.4)
|
rack (>= 1.4)
|
||||||
responders (3.1.1)
|
responders (3.1.1)
|
||||||
actionpack (>= 5.2)
|
actionpack (>= 5.2)
|
||||||
railties (>= 5.2)
|
railties (>= 5.2)
|
||||||
rexml (3.2.9)
|
rexml (3.4.4)
|
||||||
strscan
|
|
||||||
roadie (5.2.1)
|
roadie (5.2.1)
|
||||||
css_parser (~> 1.4)
|
css_parser (~> 1.4)
|
||||||
nokogiri (~> 1.15)
|
nokogiri (~> 1.15)
|
||||||
roadie-rails (3.2.0)
|
roadie-rails (3.4.0)
|
||||||
railties (>= 5.1, < 8.0)
|
railties (>= 5.1, < 8.2)
|
||||||
roadie (~> 5.0)
|
roadie (~> 5.0)
|
||||||
rodf (1.2.0)
|
rodf (1.2.0)
|
||||||
builder (>= 3.0)
|
builder (>= 3.0)
|
||||||
@@ -726,22 +751,22 @@ GEM
|
|||||||
activesupport
|
activesupport
|
||||||
rspec
|
rspec
|
||||||
rspec-support (3.13.6)
|
rspec-support (3.13.6)
|
||||||
rswag (2.16.0)
|
rswag (2.17.0)
|
||||||
rswag-api (= 2.16.0)
|
rswag-api (= 2.17.0)
|
||||||
rswag-specs (= 2.16.0)
|
rswag-specs (= 2.17.0)
|
||||||
rswag-ui (= 2.16.0)
|
rswag-ui (= 2.17.0)
|
||||||
rswag-api (2.16.0)
|
rswag-api (2.17.0)
|
||||||
activesupport (>= 5.2, < 8.1)
|
activesupport (>= 5.2, < 8.2)
|
||||||
railties (>= 5.2, < 8.1)
|
railties (>= 5.2, < 8.2)
|
||||||
rswag-specs (2.16.0)
|
rswag-specs (2.17.0)
|
||||||
activesupport (>= 5.2, < 8.1)
|
activesupport (>= 5.2, < 8.2)
|
||||||
json-schema (>= 2.2, < 6.0)
|
json-schema (>= 2.2, < 7.0)
|
||||||
railties (>= 5.2, < 8.1)
|
railties (>= 5.2, < 8.2)
|
||||||
rspec-core (>= 2.14)
|
rspec-core (>= 2.14)
|
||||||
rswag-ui (2.16.0)
|
rswag-ui (2.17.0)
|
||||||
actionpack (>= 5.2, < 8.1)
|
actionpack (>= 5.2, < 8.2)
|
||||||
railties (>= 5.2, < 8.1)
|
railties (>= 5.2, < 8.2)
|
||||||
rubocop (1.81.6)
|
rubocop (1.81.7)
|
||||||
json (~> 2.3)
|
json (~> 2.3)
|
||||||
language_server-protocol (~> 3.17.0.2)
|
language_server-protocol (~> 3.17.0.2)
|
||||||
lint_roller (~> 1.1.0)
|
lint_roller (~> 1.1.0)
|
||||||
@@ -752,25 +777,25 @@ GEM
|
|||||||
rubocop-ast (>= 1.47.1, < 2.0)
|
rubocop-ast (>= 1.47.1, < 2.0)
|
||||||
ruby-progressbar (~> 1.7)
|
ruby-progressbar (~> 1.7)
|
||||||
unicode-display_width (>= 2.4.0, < 4.0)
|
unicode-display_width (>= 2.4.0, < 4.0)
|
||||||
rubocop-ast (1.47.1)
|
rubocop-ast (1.48.0)
|
||||||
parser (>= 3.3.7.2)
|
parser (>= 3.3.7.2)
|
||||||
prism (~> 1.4)
|
prism (~> 1.4)
|
||||||
rubocop-capybara (2.22.1)
|
rubocop-capybara (2.22.1)
|
||||||
lint_roller (~> 1.1)
|
lint_roller (~> 1.1)
|
||||||
rubocop (~> 1.72, >= 1.72.1)
|
rubocop (~> 1.72, >= 1.72.1)
|
||||||
rubocop-factory_bot (2.27.1)
|
rubocop-factory_bot (2.28.0)
|
||||||
lint_roller (~> 1.1)
|
lint_roller (~> 1.1)
|
||||||
rubocop (~> 1.72, >= 1.72.1)
|
rubocop (~> 1.72, >= 1.72.1)
|
||||||
rubocop-rails (2.33.4)
|
rubocop-rails (2.34.2)
|
||||||
activesupport (>= 4.2.0)
|
activesupport (>= 4.2.0)
|
||||||
lint_roller (~> 1.1)
|
lint_roller (~> 1.1)
|
||||||
rack (>= 1.1)
|
rack (>= 1.1)
|
||||||
rubocop (>= 1.75.0, < 2.0)
|
rubocop (>= 1.75.0, < 2.0)
|
||||||
rubocop-ast (>= 1.44.0, < 2.0)
|
rubocop-ast (>= 1.44.0, < 2.0)
|
||||||
rubocop-rspec (3.7.0)
|
rubocop-rspec (3.8.0)
|
||||||
lint_roller (~> 1.1)
|
lint_roller (~> 1.1)
|
||||||
rubocop (~> 1.72, >= 1.72.1)
|
rubocop (~> 1.81)
|
||||||
rubocop-rspec_rails (2.31.0)
|
rubocop-rspec_rails (2.32.0)
|
||||||
lint_roller (~> 1.1)
|
lint_roller (~> 1.1)
|
||||||
rubocop (~> 1.72, >= 1.72.1)
|
rubocop (~> 1.72, >= 1.72.1)
|
||||||
rubocop-rspec (~> 3.5)
|
rubocop-rspec (~> 3.5)
|
||||||
@@ -778,32 +803,33 @@ GEM
|
|||||||
rexml
|
rexml
|
||||||
ruby-progressbar (1.13.0)
|
ruby-progressbar (1.13.0)
|
||||||
ruby-rc4 (0.1.5)
|
ruby-rc4 (0.1.5)
|
||||||
ruby-vips (2.1.4)
|
ruby-vips (2.2.5)
|
||||||
ffi (~> 1.12)
|
ffi (~> 1.12)
|
||||||
rubyzip (2.3.2)
|
logger
|
||||||
|
rubyzip (2.4.1)
|
||||||
rufus-scheduler (3.8.2)
|
rufus-scheduler (3.8.2)
|
||||||
fugit (~> 1.1, >= 1.1.6)
|
fugit (~> 1.1, >= 1.1.6)
|
||||||
rugged (1.9.0)
|
rugged (1.9.0)
|
||||||
sanitize (7.0.0)
|
sanitize (7.0.0)
|
||||||
crass (~> 1.0.2)
|
crass (~> 1.0.2)
|
||||||
nokogiri (>= 1.16.8)
|
nokogiri (>= 1.16.8)
|
||||||
sass (3.4.25)
|
|
||||||
sass-rails (5.0.8)
|
|
||||||
railties (>= 5.2.0)
|
|
||||||
sass (~> 3.1)
|
|
||||||
sprockets (>= 2.8, < 4.0)
|
|
||||||
sprockets-rails (>= 2.0, < 4.0)
|
|
||||||
tilt (>= 1.1, < 3)
|
|
||||||
sd_notify (0.1.1)
|
sd_notify (0.1.1)
|
||||||
securerandom (0.4.1)
|
securerandom (0.4.1)
|
||||||
semantic_range (3.0.0)
|
semantic_range (3.1.0)
|
||||||
shoulda-matchers (6.2.0)
|
shakapacker (8.4.0)
|
||||||
activesupport (>= 5.2.0)
|
activesupport (>= 5.2)
|
||||||
sidekiq (7.2.4)
|
package_json
|
||||||
concurrent-ruby (< 2)
|
rack-proxy (>= 0.6.1)
|
||||||
connection_pool (>= 2.3.0)
|
railties (>= 5.2)
|
||||||
rack (>= 2.2.4)
|
semantic_range (>= 2.3.0)
|
||||||
redis-client (>= 0.19.0)
|
shoulda-matchers (7.0.1)
|
||||||
|
activesupport (>= 7.1)
|
||||||
|
sidekiq (7.3.10)
|
||||||
|
base64
|
||||||
|
connection_pool (>= 2.3.0, < 3)
|
||||||
|
logger
|
||||||
|
rack (>= 2.2.4, < 3.3)
|
||||||
|
redis-client (>= 0.23.0, < 1)
|
||||||
sidekiq-scheduler (5.0.3)
|
sidekiq-scheduler (5.0.3)
|
||||||
rufus-scheduler (~> 3.2)
|
rufus-scheduler (~> 3.2)
|
||||||
sidekiq (>= 6, < 8)
|
sidekiq (>= 6, < 8)
|
||||||
@@ -814,9 +840,10 @@ GEM
|
|||||||
simplecov_json_formatter (~> 0.1)
|
simplecov_json_formatter (~> 0.1)
|
||||||
simplecov-html (0.13.2)
|
simplecov-html (0.13.2)
|
||||||
simplecov_json_formatter (0.1.4)
|
simplecov_json_formatter (0.1.4)
|
||||||
spreadsheet_architect (5.0.0)
|
spreadsheet_architect (5.1.0)
|
||||||
caxlsx (>= 3.3.0, < 4)
|
caxlsx (<= 4.0)
|
||||||
rodf (>= 1.0.0, < 2)
|
csv
|
||||||
|
rodf
|
||||||
spring (4.4.0)
|
spring (4.4.0)
|
||||||
spring-commands-rspec (1.0.4)
|
spring-commands-rspec (1.0.4)
|
||||||
spring (>= 0.9.1)
|
spring (>= 0.9.1)
|
||||||
@@ -826,14 +853,14 @@ GEM
|
|||||||
base64
|
base64
|
||||||
concurrent-ruby (~> 1.0)
|
concurrent-ruby (~> 1.0)
|
||||||
rack (> 1, < 3)
|
rack (> 1, < 3)
|
||||||
sprockets-rails (3.4.2)
|
sprockets-rails (3.5.2)
|
||||||
actionpack (>= 5.2)
|
actionpack (>= 6.1)
|
||||||
activesupport (>= 5.2)
|
activesupport (>= 6.1)
|
||||||
sprockets (>= 3.0.0)
|
sprockets (>= 3.0.0)
|
||||||
state_machines (0.20.0)
|
state_machines (0.100.4)
|
||||||
state_machines-activemodel (0.10.0)
|
state_machines-activemodel (0.31.0)
|
||||||
activemodel (>= 7.1)
|
activemodel (>= 7.1)
|
||||||
state_machines (>= 0.10.0)
|
state_machines (>= 0.31.0)
|
||||||
state_machines-activerecord (0.31.0)
|
state_machines-activerecord (0.31.0)
|
||||||
activerecord (>= 7.1)
|
activerecord (>= 7.1)
|
||||||
state_machines-activemodel (>= 0.10.0)
|
state_machines-activemodel (>= 0.10.0)
|
||||||
@@ -850,34 +877,33 @@ GEM
|
|||||||
railties (>= 5.2)
|
railties (>= 5.2)
|
||||||
redis (>= 4.0, < 6.0)
|
redis (>= 4.0, < 6.0)
|
||||||
stringex (2.8.6)
|
stringex (2.8.6)
|
||||||
stringio (3.1.7)
|
stringio (3.2.0)
|
||||||
stripe (13.5.1)
|
stripe (15.5.0)
|
||||||
strscan (3.1.5)
|
|
||||||
swd (2.0.3)
|
swd (2.0.3)
|
||||||
activesupport (>= 3)
|
activesupport (>= 3)
|
||||||
attr_required (>= 0.0.5)
|
attr_required (>= 0.0.5)
|
||||||
faraday (~> 2.0)
|
faraday (~> 2.0)
|
||||||
faraday-follow_redirects
|
faraday-follow_redirects
|
||||||
sysexits (1.2.0)
|
sysexits (1.2.0)
|
||||||
temple (0.8.2)
|
taler (0.1.0)
|
||||||
|
temple (0.10.4)
|
||||||
terminal-table (4.0.0)
|
terminal-table (4.0.0)
|
||||||
unicode-display_width (>= 1.1.1, < 4)
|
unicode-display_width (>= 1.1.1, < 4)
|
||||||
thor (1.4.0)
|
thor (1.4.0)
|
||||||
thread-local (1.1.0)
|
thread-local (1.1.0)
|
||||||
tilt (2.3.0)
|
tilt (2.6.1)
|
||||||
timeout (0.4.4)
|
timeout (0.4.4)
|
||||||
tsort (0.2.0)
|
tsort (0.2.0)
|
||||||
ttfunk (1.8.0)
|
ttfunk (1.8.0)
|
||||||
bigdecimal (~> 3.1)
|
bigdecimal (~> 3.1)
|
||||||
turbo-rails (2.0.5)
|
turbo-rails (2.0.20)
|
||||||
actionpack (>= 6.0.0)
|
actionpack (>= 7.1.0)
|
||||||
activejob (>= 6.0.0)
|
railties (>= 7.1.0)
|
||||||
railties (>= 6.0.0)
|
|
||||||
turbo_power (0.7.0)
|
turbo_power (0.7.0)
|
||||||
turbo-rails (>= 1.3.0)
|
turbo-rails (>= 1.3.0)
|
||||||
tzinfo (2.0.6)
|
tzinfo (2.0.6)
|
||||||
concurrent-ruby (~> 1.0)
|
concurrent-ruby (~> 1.0)
|
||||||
undercover (0.8.1)
|
undercover (0.8.3)
|
||||||
base64
|
base64
|
||||||
bigdecimal
|
bigdecimal
|
||||||
imagen (>= 0.2.0)
|
imagen (>= 0.2.0)
|
||||||
@@ -887,7 +913,7 @@ GEM
|
|||||||
simplecov_json_formatter
|
simplecov_json_formatter
|
||||||
unicode-display_width (3.2.0)
|
unicode-display_width (3.2.0)
|
||||||
unicode-emoji (~> 4.1)
|
unicode-emoji (~> 4.1)
|
||||||
unicode-emoji (4.1.0)
|
unicode-emoji (4.2.0)
|
||||||
uniform_notifier (1.17.0)
|
uniform_notifier (1.17.0)
|
||||||
uri (1.1.1)
|
uri (1.1.1)
|
||||||
valid_email2 (5.2.3)
|
valid_email2 (5.2.3)
|
||||||
@@ -898,11 +924,12 @@ GEM
|
|||||||
public_suffix
|
public_suffix
|
||||||
validates_lengths_from_database (0.8.0)
|
validates_lengths_from_database (0.8.0)
|
||||||
activerecord (>= 4)
|
activerecord (>= 4)
|
||||||
vcr (6.2.0)
|
vcr (6.3.1)
|
||||||
view_component (3.12.1)
|
base64
|
||||||
activesupport (>= 5.2.0, < 8.0)
|
view_component (4.1.1)
|
||||||
concurrent-ruby (~> 1.0)
|
actionview (>= 7.1.0, < 8.2)
|
||||||
method_source (~> 1.0)
|
activesupport (>= 7.1.0, < 8.2)
|
||||||
|
concurrent-ruby (~> 1)
|
||||||
view_component_reflex (3.1.14.pre9)
|
view_component_reflex (3.1.14.pre9)
|
||||||
rails (>= 5.2, < 8.0)
|
rails (>= 5.2, < 8.0)
|
||||||
stimulus_reflex (>= 3.5.0.pre2)
|
stimulus_reflex (>= 3.5.0.pre2)
|
||||||
@@ -920,28 +947,22 @@ GEM
|
|||||||
activesupport
|
activesupport
|
||||||
faraday (~> 2.0)
|
faraday (~> 2.0)
|
||||||
faraday-follow_redirects
|
faraday-follow_redirects
|
||||||
webmock (3.25.1)
|
webmock (3.26.1)
|
||||||
addressable (>= 2.8.0)
|
addressable (>= 2.8.0)
|
||||||
crack (>= 0.3.2)
|
crack (>= 0.3.2)
|
||||||
hashdiff (>= 0.4.0, < 2.0.0)
|
hashdiff (>= 0.4.0, < 2.0.0)
|
||||||
webpacker (5.4.4)
|
webrick (1.9.2)
|
||||||
activesupport (>= 5.2)
|
websocket-driver (0.7.7)
|
||||||
rack-proxy (>= 0.6.1)
|
base64
|
||||||
railties (>= 5.2)
|
|
||||||
semantic_range (>= 2.3.0)
|
|
||||||
webrick (1.9.1)
|
|
||||||
websocket-driver (0.7.6)
|
|
||||||
websocket-extensions (>= 0.1.0)
|
websocket-extensions (>= 0.1.0)
|
||||||
websocket-extensions (0.1.5)
|
websocket-extensions (0.1.5)
|
||||||
whenever (1.0.0)
|
whenever (1.1.0)
|
||||||
chronic (>= 0.6.3)
|
chronic (>= 0.6.3)
|
||||||
wicked_pdf (2.8.1)
|
|
||||||
activesupport
|
|
||||||
wkhtmltopdf-binary (0.12.6.10)
|
wkhtmltopdf-binary (0.12.6.10)
|
||||||
xml-simple (1.1.8)
|
xml-simple (1.1.8)
|
||||||
xpath (3.2.0)
|
xpath (3.2.0)
|
||||||
nokogiri (~> 1.8)
|
nokogiri (~> 1.8)
|
||||||
zeitwerk (2.7.3)
|
zeitwerk (2.7.4)
|
||||||
|
|
||||||
PLATFORMS
|
PLATFORMS
|
||||||
ruby
|
ruby
|
||||||
@@ -950,13 +971,13 @@ DEPENDENCIES
|
|||||||
actionpack-action_caching
|
actionpack-action_caching
|
||||||
active_model_serializers (= 0.8.4)
|
active_model_serializers (= 0.8.4)
|
||||||
active_storage_validations
|
active_storage_validations
|
||||||
activemerchant (>= 1.78.0)
|
activemerchant
|
||||||
activerecord-import
|
activerecord-import
|
||||||
activerecord-postgresql-adapter
|
activerecord-postgresql-adapter
|
||||||
activerecord-session_store
|
activerecord-session_store
|
||||||
acts-as-taggable-on
|
acts-as-taggable-on
|
||||||
acts_as_list (= 1.0.4)
|
acts_as_list (= 1.0.4)
|
||||||
angular-rails-templates (>= 0.3.0)
|
angular-rails-templates
|
||||||
angular_rails_csrf
|
angular_rails_csrf
|
||||||
angularjs-file-upload-rails (~> 2.4.1)
|
angularjs-file-upload-rails (~> 2.4.1)
|
||||||
angularjs-rails (= 1.8.0)
|
angularjs-rails (= 1.8.0)
|
||||||
@@ -999,7 +1020,7 @@ DEPENDENCIES
|
|||||||
good_migrations
|
good_migrations
|
||||||
haml
|
haml
|
||||||
haml_lint
|
haml_lint
|
||||||
highline (= 2.0.3)
|
highline
|
||||||
i18n
|
i18n
|
||||||
i18n-js (~> 3.9.0)
|
i18n-js (~> 3.9.0)
|
||||||
i18n-tasks
|
i18n-tasks
|
||||||
@@ -1063,6 +1084,7 @@ DEPENDENCIES
|
|||||||
rubocop-rspec_rails
|
rubocop-rspec_rails
|
||||||
sd_notify
|
sd_notify
|
||||||
select2-rails!
|
select2-rails!
|
||||||
|
shakapacker (= 8.4.0)
|
||||||
shoulda-matchers
|
shoulda-matchers
|
||||||
sidekiq
|
sidekiq
|
||||||
sidekiq-scheduler
|
sidekiq-scheduler
|
||||||
@@ -1076,7 +1098,8 @@ DEPENDENCIES
|
|||||||
stimulus_reflex
|
stimulus_reflex
|
||||||
stimulus_reflex_testing!
|
stimulus_reflex_testing!
|
||||||
stringex (~> 2.8.5)
|
stringex (~> 2.8.5)
|
||||||
stripe (~> 13)
|
stripe (~> 15)
|
||||||
|
taler
|
||||||
turbo-rails
|
turbo-rails
|
||||||
turbo_power
|
turbo_power
|
||||||
undercover
|
undercover
|
||||||
@@ -1088,13 +1111,12 @@ DEPENDENCIES
|
|||||||
web!
|
web!
|
||||||
web-console
|
web-console
|
||||||
webmock
|
webmock
|
||||||
webpacker (~> 5)
|
|
||||||
whenever
|
whenever
|
||||||
wicked_pdf
|
wicked_pdf!
|
||||||
wkhtmltopdf-binary
|
wkhtmltopdf-binary
|
||||||
|
|
||||||
RUBY VERSION
|
RUBY VERSION
|
||||||
ruby 3.2.9p265
|
ruby 3.4.8p72
|
||||||
|
|
||||||
BUNDLED WITH
|
BUNDLED WITH
|
||||||
2.4.19
|
4.0.3
|
||||||
|
|||||||
2
Procfile
2
Procfile
@@ -1,5 +1,5 @@
|
|||||||
# Foreman Procfile. Start all dev server processes with: `foreman start`
|
# Foreman Procfile. Start all dev server processes with: `foreman start`
|
||||||
|
|
||||||
rails: DEV_CACHING=true bundle exec rails s -p 3000
|
rails: DEV_CACHING=true bundle exec rails s -p 3000
|
||||||
webpack: ./bin/webpack-dev-server
|
webpack: ./bin/shakapacker-dev-server
|
||||||
sidekiq: DEV_CACHING=true bundle exec sidekiq -q mailers -q default
|
sidekiq: DEV_CACHING=true bundle exec sidekiq -q mailers -q default
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
# Foreman Procfile for Docker env. Start all dev server processes with: `bundle exec foreman start -f Procfile.docker`
|
# Foreman Procfile for Docker env. Start all dev server processes with: `bundle exec foreman start -f Procfile.docker`
|
||||||
|
|
||||||
webpack: WEBPACKER_DEV_SERVER_HOST=0.0.0.0 ./bin/webpack-dev-server
|
webpack: SHAKAPACKER_DEV_SERVER_HOST=0.0.0.0 ./bin/shakapacker-dev-server
|
||||||
sidekiq: DEV_CACHING=true bundle exec sidekiq -q mailers -q default
|
sidekiq: DEV_CACHING=true bundle exec sidekiq -q mailers -q default
|
||||||
rails: WEBPACKER_DEV_SERVER_HOST=0.0.0.0 DEV_CACHING=true bundle exec rails s -p 3000 -b 0.0.0.0
|
rails: SHAKAPACKER_DEV_SERVER_HOST=0.0.0.0 DEV_CACHING=true bundle exec rails s -p 3000 -b 0.0.0.0
|
||||||
|
|||||||
@@ -11,6 +11,9 @@ angular.module("admin.customers").controller "customersCtrl", ($scope, $q, $filt
|
|||||||
$scope.confirmRefresh = (event) ->
|
$scope.confirmRefresh = (event) ->
|
||||||
event.preventDefault() unless pendingChanges.unsavedCount() == 0 || confirm(t("unsaved_changes_warning"))
|
event.preventDefault() unless pendingChanges.unsavedCount() == 0 || confirm(t("unsaved_changes_warning"))
|
||||||
|
|
||||||
|
$scope.hasUnsavedChanges = ->
|
||||||
|
pendingChanges.yes()
|
||||||
|
|
||||||
$scope.$watch "shop_id", ->
|
$scope.$watch "shop_id", ->
|
||||||
if $scope.shop_id?
|
if $scope.shop_id?
|
||||||
CurrentShop.shop = $filter('filter')($scope.shops, {id: parseInt($scope.shop_id)}, true)[0]
|
CurrentShop.shop = $filter('filter')($scope.shops, {id: parseInt($scope.shop_id)}, true)[0]
|
||||||
|
|||||||
@@ -4,15 +4,16 @@ angular.module("admin.indexUtils").directive "objForUpdate", (switchClass, pendi
|
|||||||
type: "@objForUpdate"
|
type: "@objForUpdate"
|
||||||
attr: "@attrForUpdate"
|
attr: "@attrForUpdate"
|
||||||
link: (scope, element, attrs) ->
|
link: (scope, element, attrs) ->
|
||||||
scope.savedValue = scope.object()[scope.attr]
|
scope.savedValue = scope.object()[scope.attr] || ""
|
||||||
|
|
||||||
scope.$watch "object().#{scope.attr}", (value) ->
|
scope.$watch "object().#{scope.attr}", (value) ->
|
||||||
if value == scope.savedValue
|
strValue = value || ""
|
||||||
|
if strValue == scope.savedValue
|
||||||
pendingChanges.remove(scope.object().id, scope.attr)
|
pendingChanges.remove(scope.object().id, scope.attr)
|
||||||
scope.clear()
|
scope.clear()
|
||||||
else
|
else
|
||||||
scope.pending()
|
scope.pending()
|
||||||
addPendingChange(scope.attr, value ? "")
|
addPendingChange(scope.attr, strValue)
|
||||||
|
|
||||||
scope.reset = (value) ->
|
scope.reset = (value) ->
|
||||||
scope.savedValue = value
|
scope.savedValue = value
|
||||||
@@ -37,16 +38,13 @@ angular.module("admin.indexUtils").directive "objForUpdate", (switchClass, pendi
|
|||||||
# To ensure the customer is still updated, we check on the $destroy event to see if
|
# To ensure the customer is still updated, we check on the $destroy event to see if
|
||||||
# the attribute has changed, if so we queue up the change.
|
# the attribute has changed, if so we queue up the change.
|
||||||
scope.$on '$destroy', (value) ->
|
scope.$on '$destroy', (value) ->
|
||||||
# No update
|
currentValue = scope.object()[scope.attr] || ""
|
||||||
return if scope.object()[scope.attr] is scope.savedValue
|
|
||||||
|
|
||||||
# For some reason the code attribute is removed from the object when cleared, so we add
|
# No update
|
||||||
# an emptyvalue so it gets updated properly
|
return if currentValue is scope.savedValue
|
||||||
if scope.attr is "code" and scope.object()[scope.attr] is undefined
|
|
||||||
scope.object()["code"] = ""
|
|
||||||
|
|
||||||
# Queuing up change
|
# Queuing up change
|
||||||
addPendingChange(scope.attr, scope.object()[scope.attr])
|
addPendingChange(scope.attr, currentValue)
|
||||||
|
|
||||||
# private
|
# private
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,10 @@ angular.module("admin.indexUtils").factory "pendingChanges", ($q, resources, Sta
|
|||||||
remove: (id, attr) =>
|
remove: (id, attr) =>
|
||||||
if @pendingChanges.hasOwnProperty("#{id}")
|
if @pendingChanges.hasOwnProperty("#{id}")
|
||||||
delete @pendingChanges["#{id}"]["#{attr}"]
|
delete @pendingChanges["#{id}"]["#{attr}"]
|
||||||
delete @pendingChanges["#{id}"] if @changeCount( @pendingChanges["#{id}"] ) < 1
|
|
||||||
|
if @changeCount( @pendingChanges["#{id}"] ) < 1
|
||||||
|
delete @pendingChanges["#{id}"]
|
||||||
|
StatusMessage.clear()
|
||||||
|
|
||||||
submitAll: (form=null) =>
|
submitAll: (form=null) =>
|
||||||
all = []
|
all = []
|
||||||
@@ -47,5 +50,8 @@ angular.module("admin.indexUtils").factory "pendingChanges", ($q, resources, Sta
|
|||||||
unsavedCount: ->
|
unsavedCount: ->
|
||||||
Object.keys(@pendingChanges).length
|
Object.keys(@pendingChanges).length
|
||||||
|
|
||||||
|
yes: ->
|
||||||
|
@unsavedCount() > 0
|
||||||
|
|
||||||
changeCount: (objectChanges) ->
|
changeCount: (objectChanges) ->
|
||||||
Object.keys(objectChanges).length
|
Object.keys(objectChanges).length
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
angular.module("admin.indexUtils").factory "switchClass", ($timeout) ->
|
angular.module("admin.indexUtils").factory "switchClass", ($timeout, StatusMessage) ->
|
||||||
return (element, classToAdd, removeClasses, timeout) ->
|
return (element, classToAdd, removeClasses, timeout) ->
|
||||||
$timeout.cancel element.timeout if element.timeout
|
$timeout.cancel element.timeout if element.timeout
|
||||||
element.removeClass className for className in removeClasses
|
element.removeClass className for className in removeClasses
|
||||||
@@ -7,4 +7,6 @@ angular.module("admin.indexUtils").factory "switchClass", ($timeout) ->
|
|||||||
if timeout && intRegex.test(timeout)
|
if timeout && intRegex.test(timeout)
|
||||||
element.timeout = $timeout(->
|
element.timeout = $timeout(->
|
||||||
element.removeClass classToAdd
|
element.removeClass classToAdd
|
||||||
|
StatusMessage.clear()
|
||||||
, timeout, true)
|
, timeout, true)
|
||||||
|
element
|
||||||
|
|||||||
@@ -1,2 +0,0 @@
|
|||||||
angular.module('Darkswarm').controller "TmpCtrl", ($scope)->
|
|
||||||
$scope.test = {foo: "bar"}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
@import './mail/all.scss';
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
@import '../../../webpacker/css/admin/globals/palette.scss';
|
|
||||||
@import 'email';
|
|
||||||
@import 'payments_list';
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
= render ConfirmModalComponent.new(id: dom_id(@order, :ship), confirm_reflexes: "click->Admin::OrdersReflex#ship", controller: "orders", reflex: "Admin::Orders#ship") do
|
= render ConfirmModalComponent.new(id: dom_id(@order, :ship), confirm_actions: "click->modal#close", confirm_reflexes: "click->Admin::OrdersReflex#ship", controller: "orders", reflex: "Admin::Orders#ship") do
|
||||||
%div{class: "margin-bottom-30"}
|
%div{class: "margin-bottom-30"}
|
||||||
%p= t('spree.admin.orders.shipment.mark_as_shipped_message_html')
|
%p= t('spree.admin.orders.shipment.mark_as_shipped_message_html')
|
||||||
%div{class: "margin-bottom-30"}
|
%div{class: "margin-bottom-30"}
|
||||||
|
|||||||
16
app/components/webhook_endpoint_form_component.rb
Normal file
16
app/components/webhook_endpoint_form_component.rb
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class WebhookEndpointFormComponent < ViewComponent::Base
|
||||||
|
def initialize(webhooks:, webhook_type:)
|
||||||
|
@webhooks = webhooks
|
||||||
|
@webhook_type = webhook_type
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
attr_reader :webhooks, :webhook_type
|
||||||
|
|
||||||
|
def is_webhook_payment_status?
|
||||||
|
webhook_type == "payment_status_changed"
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
-# Create new endpoints
|
||||||
|
- if webhooks.empty? # Only one allowed for now.
|
||||||
|
%tr
|
||||||
|
%td= t("components.webhook_endpoint_form.event_types.#{webhook_type}")
|
||||||
|
%td
|
||||||
|
= form_with(url: helpers.account_webhook_endpoints_path, id: "#{webhook_type}_webhook_endpoint") do |f|
|
||||||
|
= f.url_field :'webhook_endpoint[url]', id: "#{webhook_type}_webhook_endpoint_url", placeholder: t('components.webhook_endpoint_form.url.create_placeholder'), required: true, size: 64
|
||||||
|
= f.hidden_field :'webhook_endpoint[webhook_type]', id: "#{webhook_type}_webhook_endpoint_webhook_type", value: webhook_type
|
||||||
|
%td.actions
|
||||||
|
= button_tag t(:create), class: 'button primary tiny no-margin', form: "#{webhook_type}_webhook_endpoint"
|
||||||
|
|
||||||
|
-# Existing endpoints
|
||||||
|
- webhooks.each do |webhook_endpoint|
|
||||||
|
%tr
|
||||||
|
%td= t("components.webhook_endpoint_form.event_types.#{webhook_type}")
|
||||||
|
%td= webhook_endpoint.url
|
||||||
|
%td.actions.endpoints-actions
|
||||||
|
- if webhook_endpoint.persisted?
|
||||||
|
= button_to helpers.account_webhook_endpoint_path(webhook_endpoint), method: :delete,
|
||||||
|
class: "tiny alert no-margin",
|
||||||
|
data: { confirm: I18n.t(:are_you_sure) } do
|
||||||
|
= I18n.t(:delete)
|
||||||
|
|
||||||
|
- if is_webhook_payment_status?
|
||||||
|
= form_tag helpers.webhook_endpoint_test_account_path(webhook_endpoint), class: "button_to", 'data-turbo': true do
|
||||||
|
= button_tag type: "submit", class: "tiny alert no-margin", data: { confirm: I18n.t(:are_you_sure) } do
|
||||||
|
= I18n.t("components.webhook_endpoint_form.test_endpoint")
|
||||||
@@ -51,6 +51,18 @@ module Admin
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# copy of Admin::ResourceController without flash notice
|
||||||
|
def update
|
||||||
|
if @object.update(permitted_resource_params)
|
||||||
|
respond_with(@object) do |format|
|
||||||
|
format.html { redirect_to location_after_save }
|
||||||
|
format.js { render layout: false }
|
||||||
|
end
|
||||||
|
else
|
||||||
|
respond_with(@object)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
# copy of Admin::ResourceController without flash notice
|
# copy of Admin::ResourceController without flash notice
|
||||||
def destroy
|
def destroy
|
||||||
if @object.destroy
|
if @object.destroy
|
||||||
|
|||||||
@@ -15,8 +15,8 @@ module Admin
|
|||||||
def index
|
def index
|
||||||
# Fetch DFC catalog JSON for preview
|
# Fetch DFC catalog JSON for preview
|
||||||
@catalog_url = params.require(:catalog_url).strip
|
@catalog_url = params.require(:catalog_url).strip
|
||||||
@catalog_json = api.call(@catalog_url)
|
@catalog_data = api.call(@catalog_url)
|
||||||
catalog = DfcCatalog.from_json(@catalog_json)
|
catalog = DfcCatalog.from_json(@catalog_data)
|
||||||
|
|
||||||
# Render table and let user decide which ones to import.
|
# Render table and let user decide which ones to import.
|
||||||
@items = list_products(catalog)
|
@items = list_products(catalog)
|
||||||
|
|||||||
@@ -162,6 +162,18 @@ module Admin
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def destroy
|
||||||
|
if @object.destroy
|
||||||
|
flash.now[:success] = flash_message_for(@object, :successfully_removed)
|
||||||
|
else
|
||||||
|
flash.now[:error] = @object.errors.full_messages.to_sentence
|
||||||
|
end
|
||||||
|
|
||||||
|
respond_to do |format|
|
||||||
|
format.turbo_stream { render :destroy, status: :ok }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
protected
|
protected
|
||||||
|
|
||||||
def delete_custom_tab
|
def delete_custom_tab
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ module Admin
|
|||||||
errors: @importer.errors.full_messages
|
errors: @importer.errors.full_messages
|
||||||
}
|
}
|
||||||
|
|
||||||
if helpers.feature?(:inventory, *spree_current_user.enterprises)
|
if helpers.inventory_enabled?(spree_current_user.enterprises)
|
||||||
json[:results][:inventory_created] = @importer.inventory_created_count
|
json[:results][:inventory_created] = @importer.inventory_created_count
|
||||||
json[:results][:inventory_updated] = @importer.inventory_updated_count
|
json[:results][:inventory_updated] = @importer.inventory_updated_count
|
||||||
end
|
end
|
||||||
@@ -175,7 +175,7 @@ module Admin
|
|||||||
|
|
||||||
# Return an error if trying to import into inventories when inventory is disable
|
# Return an error if trying to import into inventories when inventory is disable
|
||||||
def can_import_into_inventories?
|
def can_import_into_inventories?
|
||||||
return true if helpers.feature?(:inventory, *spree_current_user.enterprises) ||
|
return true if helpers.inventory_enabled?(spree_current_user.enterprises) ||
|
||||||
params.dig(:settings, "import_into") != 'inventories'
|
params.dig(:settings, "import_into") != 'inventories'
|
||||||
|
|
||||||
redirect_to admin_product_import_url, notice: I18n.t(:product_import_inventory_disable)
|
redirect_to admin_product_import_url, notice: I18n.t(:product_import_inventory_disable)
|
||||||
|
|||||||
@@ -7,11 +7,13 @@ module Admin
|
|||||||
|
|
||||||
before_action :init_filters_params
|
before_action :init_filters_params
|
||||||
before_action :init_pagination_params
|
before_action :init_pagination_params
|
||||||
|
before_action :init_none_tag
|
||||||
|
|
||||||
def index
|
def index
|
||||||
fetch_products
|
fetch_products
|
||||||
render "index",
|
render "index",
|
||||||
locals: { producers:, categories:, tax_category_options:, available_tags:, flash: }
|
locals: { producer_options:, categories:, tax_category_options:, available_tags:,
|
||||||
|
flash:, allowed_producers: }
|
||||||
|
|
||||||
session[:products_return_to_url] = request.url
|
session[:products_return_to_url] = request.url
|
||||||
end
|
end
|
||||||
@@ -32,7 +34,8 @@ module Admin
|
|||||||
|
|
||||||
render "index", status: :unprocessable_entity,
|
render "index", status: :unprocessable_entity,
|
||||||
locals: {
|
locals: {
|
||||||
producers:, categories:, tax_category_options:, available_tags:, flash:
|
producer_options:, categories:, tax_category_options:, available_tags:,
|
||||||
|
allowed_producers:, flash:
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -78,27 +81,29 @@ module Admin
|
|||||||
end
|
end
|
||||||
|
|
||||||
def clone
|
def clone
|
||||||
@product = Spree::Product.find(params[:id])
|
product = Spree::Product.find(params[:id])
|
||||||
authorize! :clone, @product
|
authorize! :clone, product
|
||||||
|
|
||||||
status = :ok
|
status = :ok
|
||||||
|
|
||||||
begin
|
begin
|
||||||
@cloned_product = @product.duplicate
|
cloned_product = product.duplicate
|
||||||
flash.now[:success] = t('.success')
|
flash.now[:success] = t('.success')
|
||||||
|
|
||||||
@product_index = "-#{@cloned_product.id}"
|
product_index = "-#{cloned_product.id}"
|
||||||
@producer_options = producers
|
|
||||||
@category_options = categories
|
|
||||||
@tax_category_options = tax_category_options
|
|
||||||
rescue ActiveRecord::ActiveRecordError => e
|
rescue ActiveRecord::ActiveRecordError => e
|
||||||
flash.now[:error] = clone_error_message(e)
|
flash.now[:error] = clone_error_message(e)
|
||||||
status = :unprocessable_entity
|
status = :unprocessable_entity
|
||||||
@product_index = "-1" # Create a unique enough index
|
product_index = "-1" # Create a unique enough index
|
||||||
end
|
end
|
||||||
|
|
||||||
respond_with do |format|
|
respond_with do |format|
|
||||||
format.turbo_stream { render :clone, status: }
|
format.turbo_stream {
|
||||||
|
render :clone, status:,
|
||||||
|
locals: { product:, cloned_product:, product_index:, producer_options:,
|
||||||
|
category_options: categories, tax_category_options:,
|
||||||
|
allowed_producers: }
|
||||||
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -124,18 +129,31 @@ module Admin
|
|||||||
@per_page = params[:per_page].presence || 15
|
@per_page = params[:per_page].presence || 15
|
||||||
@q = params.permit(q: {})[:q] || { s: 'name asc' }
|
@q = params.permit(q: {})[:q] || { s: 'name asc' }
|
||||||
|
|
||||||
# Transform on_hand sorting to include backorderable_priority (on-demand) for proper ordering
|
# Transform on_hand sorting to properly handle On-Demand products:
|
||||||
|
# - On-Demand products should ignore on_hand completely and sort alphabetically.
|
||||||
|
# - Non-On-Demand products should continue sorting by on_hand as usual.
|
||||||
if @q[:s] == 'on_hand asc'
|
if @q[:s] == 'on_hand asc'
|
||||||
@q[:s] = ['backorderable_priority asc', @q[:s]]
|
@q[:s] = [
|
||||||
|
'backorderable_priority asc',
|
||||||
|
'backorderable_name asc',
|
||||||
|
@q[:s]
|
||||||
|
]
|
||||||
elsif @q[:s] == 'on_hand desc'
|
elsif @q[:s] == 'on_hand desc'
|
||||||
@q[:s] = ['backorderable_priority desc', @q[:s]]
|
@q[:s] = [
|
||||||
|
'backorderable_priority desc',
|
||||||
|
'backorderable_name asc',
|
||||||
|
@q[:s]
|
||||||
|
]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def producers
|
def allowed_producers
|
||||||
producers = OpenFoodNetwork::Permissions.new(spree_current_user)
|
OpenFoodNetwork::Permissions.new(spree_current_user)
|
||||||
.managed_product_enterprises.is_primary_producer.by_name
|
.managed_product_enterprises.is_primary_producer.by_name
|
||||||
producers.map { |p| [p.name, p.id] }
|
end
|
||||||
|
|
||||||
|
def producer_options
|
||||||
|
allowed_producers.map { |p| [p.name, p.id] }
|
||||||
end
|
end
|
||||||
|
|
||||||
def categories
|
def categories
|
||||||
@@ -162,6 +180,8 @@ module Admin
|
|||||||
product_query = OpenFoodNetwork::Permissions.new(spree_current_user)
|
product_query = OpenFoodNetwork::Permissions.new(spree_current_user)
|
||||||
.editable_products.merge(product_scope_with_includes).ransack(ransack_query).result
|
.editable_products.merge(product_scope_with_includes).ransack(ransack_query).result
|
||||||
|
|
||||||
|
product_query = apply_tags_filter(product_query)
|
||||||
|
|
||||||
# Postgres requires ORDER BY expressions to appear in the SELECT list when using DISTINCT.
|
# Postgres requires ORDER BY expressions to appear in the SELECT list when using DISTINCT.
|
||||||
# When the current ransack sort uses the computed stock columns, include them in the select
|
# When the current ransack sort uses the computed stock columns, include them in the select
|
||||||
# so the generated COUNT/DISTINCT query is valid.
|
# so the generated COUNT/DISTINCT query is valid.
|
||||||
@@ -173,6 +193,7 @@ module Admin
|
|||||||
product_query = product_query.select(
|
product_query = product_query.select(
|
||||||
Arel.sql('spree_products.*'),
|
Arel.sql('spree_products.*'),
|
||||||
Spree::Product.backorderable_priority_sql,
|
Spree::Product.backorderable_priority_sql,
|
||||||
|
Spree::Product.backorderable_name_sql,
|
||||||
Spree::Product.on_hand_sql
|
Spree::Product.on_hand_sql
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
@@ -207,12 +228,51 @@ module Admin
|
|||||||
query.merge!(Spree::Variant::SEARCH_KEY => @search_term)
|
query.merge!(Spree::Variant::SEARCH_KEY => @search_term)
|
||||||
end
|
end
|
||||||
query.merge!(variants_primary_taxon_id_in: @category_id) if @category_id.present?
|
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.merge!(@q) if @q
|
||||||
|
|
||||||
query
|
query
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Apply tags filter with OR logic:
|
||||||
|
# - Products with variants having selected tags
|
||||||
|
# - OR products with variants having no tags (when "None" is selected)
|
||||||
|
#
|
||||||
|
# Note: This cannot be implemented using Ransack because Ransack applies
|
||||||
|
# AND semantics across associations and cannot express OR logic that combines
|
||||||
|
# the presence and absence of the same associated records.
|
||||||
|
def apply_tags_filter(base_query)
|
||||||
|
return base_query if @tags.blank?
|
||||||
|
|
||||||
|
tag_names = Array(@tags).dup
|
||||||
|
has_none_tag = (tag_names.delete(@none_tag_value) == @none_tag_value)
|
||||||
|
|
||||||
|
queries = []
|
||||||
|
|
||||||
|
if tag_names.any?
|
||||||
|
# Products with at least one variant having one of the selected tags
|
||||||
|
tagged_product_ids = Spree::Variant
|
||||||
|
.joins(taggings: :tag)
|
||||||
|
.where(tags: { name: tag_names })
|
||||||
|
.select(:product_id)
|
||||||
|
|
||||||
|
queries << base_query.where(id: tagged_product_ids)
|
||||||
|
end
|
||||||
|
|
||||||
|
if has_none_tag
|
||||||
|
# Products where no variants have any tags
|
||||||
|
tagged_product_ids = Spree::Variant
|
||||||
|
.joins(:taggings)
|
||||||
|
.select(:product_id)
|
||||||
|
|
||||||
|
queries << base_query.where.not(id: tagged_product_ids)
|
||||||
|
end
|
||||||
|
|
||||||
|
return base_query if queries.empty?
|
||||||
|
|
||||||
|
# Combine queries using ActiveRecord's or method
|
||||||
|
queries.reduce { |combined, query| combined.or(query) }
|
||||||
|
end
|
||||||
|
|
||||||
# Optimise by pre-loading required columns
|
# Optimise by pre-loading required columns
|
||||||
def product_query_includes
|
def product_query_includes
|
||||||
[
|
[
|
||||||
@@ -271,6 +331,10 @@ module Admin
|
|||||||
t('.error')
|
t('.error')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def init_none_tag
|
||||||
|
@none_tag_value = '""'
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
# rubocop:enable Metrics/ClassLength
|
# rubocop:enable Metrics/ClassLength
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ module Admin
|
|||||||
|
|
||||||
def destroy
|
def destroy
|
||||||
if @object.destroy
|
if @object.destroy
|
||||||
flash[:success] = flash_message_for(@object, :successfully_removed)
|
flash[:success] = Spree.t(:successfully_removed)
|
||||||
respond_with(@object) do |format|
|
respond_with(@object) do |format|
|
||||||
format.html { redirect_to collection_url }
|
format.html { redirect_to collection_url }
|
||||||
format.js { render partial: "spree/admin/shared/destroy" }
|
format.js { render partial: "spree/admin/shared/destroy" }
|
||||||
@@ -76,7 +76,7 @@ module Admin
|
|||||||
protected
|
protected
|
||||||
|
|
||||||
def resource_not_found
|
def resource_not_found
|
||||||
flash[:error] = flash_message_for(model_class.new, :not_found)
|
flash[:error] = Spree.t(:not_found)
|
||||||
redirect_to collection_url
|
redirect_to collection_url
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ module Admin
|
|||||||
class StripeAccountsController < Spree::Admin::BaseController
|
class StripeAccountsController < Spree::Admin::BaseController
|
||||||
def connect
|
def connect
|
||||||
payload = params.permit(:enterprise_id).to_h
|
payload = params.permit(:enterprise_id).to_h
|
||||||
key = Openfoodnetwork::Application.config.secret_token
|
key = Rails.application.secret_key_base
|
||||||
url_params = { state: JWT.encode(payload, key, 'HS256'), scope: "read_write" }
|
url_params = { state: JWT.encode(payload, key, 'HS256'), scope: "read_write" }
|
||||||
redirect_to Stripe::OAuth.authorize_url(url_params)
|
redirect_to Stripe::OAuth.authorize_url(url_params)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ module Admin
|
|||||||
|
|
||||||
status = :ok
|
status = :ok
|
||||||
if @rule.destroy
|
if @rule.destroy
|
||||||
flash[:success] = Spree.t(:successfully_removed, resource: "Tag Rule")
|
flash[:success] = Spree.t(:successfully_removed, resource: Spree.t(:tag_rule))
|
||||||
else
|
else
|
||||||
flash.now[:error] = t(".destroy_error")
|
flash.now[:error] = t(".destroy_error")
|
||||||
status = :internal_server_error
|
status = :internal_server_error
|
||||||
|
|||||||
@@ -44,6 +44,8 @@ module Admin
|
|||||||
def load_data
|
def load_data
|
||||||
@hubs = OpenFoodNetwork::Permissions.new(spree_current_user).
|
@hubs = OpenFoodNetwork::Permissions.new(spree_current_user).
|
||||||
variant_override_hubs.by_name
|
variant_override_hubs.by_name
|
||||||
|
# Only display the ones with inventory enabled
|
||||||
|
@hubs = @hubs.select { |p| helpers.feature?(:inventory, p) }
|
||||||
|
|
||||||
# Used in JS to look up the name of the producer of each product
|
# Used in JS to look up the name of the producer of each product
|
||||||
@producers = OpenFoodNetwork::Permissions.new(spree_current_user).
|
@producers = OpenFoodNetwork::Permissions.new(spree_current_user).
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ module Admin
|
|||||||
)
|
)
|
||||||
|
|
||||||
if @voucher.save
|
if @voucher.save
|
||||||
flash[:success] = I18n.t(:successfully_created, resource: "Voucher")
|
flash[:success] = I18n.t(:successfully_created, resource: Spree.t(:voucher))
|
||||||
redirect_to edit_admin_enterprise_path(@enterprise, anchor: :vouchers_panel)
|
redirect_to edit_admin_enterprise_path(@enterprise, anchor: :vouchers_panel)
|
||||||
else
|
else
|
||||||
render_error
|
render_error
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ module Api
|
|||||||
@enterprise = Enterprise.find_by(permalink: params[:id]) || Enterprise.find(params[:id])
|
@enterprise = Enterprise.find_by(permalink: params[:id]) || Enterprise.find(params[:id])
|
||||||
authorize! :update, @enterprise
|
authorize! :update, @enterprise
|
||||||
|
|
||||||
if params[:logo] && @enterprise.update( logo: params[:logo] )
|
if params[:logo] && @enterprise.update!(logo: params[:logo])
|
||||||
render(html: @enterprise.logo_url(:medium), status: :ok)
|
render(html: @enterprise.logo_url(:medium), status: :ok)
|
||||||
elsif params[:promo] && @enterprise.update!( promo_image: params[:promo] )
|
elsif params[:promo] && @enterprise.update!( promo_image: params[:promo] )
|
||||||
render(html: @enterprise.promo_image_url(:medium), status: :ok)
|
render(html: @enterprise.promo_image_url(:medium), status: :ok)
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ module ManagerInvitations
|
|||||||
extend ActiveSupport::Concern
|
extend ActiveSupport::Concern
|
||||||
|
|
||||||
def create_new_manager(email, enterprise)
|
def create_new_manager(email, enterprise)
|
||||||
password = Devise.friendly_token
|
password = SecureRandom.base58(64)
|
||||||
new_user = Spree::User.create(email:, unconfirmed_email: email, password:)
|
new_user = Spree::User.create(email:, unconfirmed_email: email, password:)
|
||||||
new_user.reset_password_token = Devise.friendly_token
|
new_user.reset_password_token = Devise.friendly_token
|
||||||
# Same time as used in Devise's lib/devise/models/recoverable.rb.
|
# Same time as used in Devise's lib/devise/models/recoverable.rb.
|
||||||
|
|||||||
16
app/controllers/payment_gateways/taler_controller.rb
Normal file
16
app/controllers/payment_gateways/taler_controller.rb
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module PaymentGateways
|
||||||
|
class TalerController < BaseController
|
||||||
|
include OrderCompletion
|
||||||
|
|
||||||
|
# The Taler merchant backend has taken the payment.
|
||||||
|
# Now we just need to confirm that and update our local database
|
||||||
|
# before finalising the order.
|
||||||
|
def confirm
|
||||||
|
payment = Spree::Payment.find(params[:payment_id])
|
||||||
|
@order = payment.order
|
||||||
|
process_payment_completion!
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -68,7 +68,7 @@ module Spree
|
|||||||
destroy_before
|
destroy_before
|
||||||
|
|
||||||
if @object.destroy
|
if @object.destroy
|
||||||
flash[:success] = flash_message_for(@object, :successfully_removed)
|
flash[:success] = Spree.t(:successfully_removed)
|
||||||
end
|
end
|
||||||
|
|
||||||
redirect_to location_after_save
|
redirect_to location_after_save
|
||||||
|
|||||||
@@ -11,10 +11,11 @@ module Spree
|
|||||||
respond_to :html
|
respond_to :html
|
||||||
|
|
||||||
PAYMENT_METHODS = %w{
|
PAYMENT_METHODS = %w{
|
||||||
Spree::PaymentMethod::Check
|
|
||||||
Spree::Gateway::PayPalExpress
|
Spree::Gateway::PayPalExpress
|
||||||
Spree::Gateway::StripeSCA
|
Spree::Gateway::StripeSCA
|
||||||
}.index_with(&:constantize).freeze
|
Spree::PaymentMethod::Check
|
||||||
|
Spree::PaymentMethod::Taler
|
||||||
|
}.freeze
|
||||||
|
|
||||||
def create
|
def create
|
||||||
force_environment
|
force_environment
|
||||||
@@ -95,7 +96,7 @@ module Spree
|
|||||||
@payment_method = PaymentMethod.find(params[:pm_id])
|
@payment_method = PaymentMethod.find(params[:pm_id])
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
@payment_method = PAYMENT_METHODS.fetch(params[:provider_type], PaymentMethod).new
|
@payment_method = PaymentMethod.new(type: params[:provider_type])
|
||||||
end
|
end
|
||||||
|
|
||||||
render partial: 'provider_settings'
|
render partial: 'provider_settings'
|
||||||
@@ -117,7 +118,7 @@ module Spree
|
|||||||
end
|
end
|
||||||
|
|
||||||
def validate_payment_method_provider
|
def validate_payment_method_provider
|
||||||
valid_payment_methods = Rails.application.config.spree.payment_methods.map(&:to_s)
|
valid_payment_methods = PAYMENT_METHODS
|
||||||
return if valid_payment_methods.include?(params[:payment_method][:type])
|
return if valid_payment_methods.include?(params[:payment_method][:type])
|
||||||
|
|
||||||
flash[:error] = Spree.t(:invalid_payment_provider)
|
flash[:error] = Spree.t(:invalid_payment_provider)
|
||||||
@@ -133,13 +134,11 @@ module Spree
|
|||||||
end
|
end
|
||||||
|
|
||||||
def load_providers
|
def load_providers
|
||||||
providers = Gateway.providers.sort_by(&:name)
|
providers = PAYMENT_METHODS.dup
|
||||||
|
|
||||||
unless show_stripe?
|
providers.delete("Spree::Gateway::StripeSCA") unless show_stripe?
|
||||||
providers.reject! { |provider| stripe_provider?(provider) }
|
|
||||||
end
|
|
||||||
|
|
||||||
providers
|
providers.map(&:constantize)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Show Stripe as an option if enabled, or if the
|
# Show Stripe as an option if enabled, or if the
|
||||||
@@ -164,10 +163,6 @@ module Spree
|
|||||||
@payment_method.try(:type) == "Spree::Gateway::StripeSCA"
|
@payment_method.try(:type) == "Spree::Gateway::StripeSCA"
|
||||||
end
|
end
|
||||||
|
|
||||||
def stripe_provider?(provider)
|
|
||||||
provider.name.ends_with?("StripeSCA")
|
|
||||||
end
|
|
||||||
|
|
||||||
def base_params
|
def base_params
|
||||||
@base_params ||= PermittedAttributes::PaymentMethod.new(params[:payment_method]).
|
@base_params ||= PermittedAttributes::PaymentMethod.new(params[:payment_method]).
|
||||||
call.to_h.with_indifferent_access
|
call.to_h.with_indifferent_access
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ module Spree
|
|||||||
@url_filters = ::ProductFilters.new.extract(request.query_parameters)
|
@url_filters = ::ProductFilters.new.extract(request.query_parameters)
|
||||||
|
|
||||||
if @object.destroy
|
if @object.destroy
|
||||||
flash[:success] = flash_message_for(@object, :successfully_removed)
|
flash[:success] = Spree.t(:successfully_removed)
|
||||||
end
|
end
|
||||||
# if destroy fails it won't show any errors to the user
|
# if destroy fails it won't show any errors to the user
|
||||||
redirect_to spree.admin_product_product_properties_url(params[:product_id], @url_filters)
|
redirect_to spree.admin_product_product_properties_url(params[:product_id], @url_filters)
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ module Spree
|
|||||||
end
|
end
|
||||||
|
|
||||||
@object.touch :deleted_at
|
@object.touch :deleted_at
|
||||||
flash[:success] = flash_message_for(@object, :successfully_removed)
|
flash[:success] = Spree.t(:successfully_removed)
|
||||||
|
|
||||||
respond_with(@object) do |format|
|
respond_with(@object) do |format|
|
||||||
format.html { redirect_to collection_url }
|
format.html { redirect_to collection_url }
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ module Spree
|
|||||||
class TaxCategoriesController < ::Admin::ResourceController
|
class TaxCategoriesController < ::Admin::ResourceController
|
||||||
def destroy
|
def destroy
|
||||||
if @object.destroy
|
if @object.destroy
|
||||||
flash[:success] = flash_message_for(@object, :successfully_removed)
|
flash[:success] = Spree.t(:successfully_removed)
|
||||||
respond_with(@object) do |format|
|
respond_with(@object) do |format|
|
||||||
format.html { redirect_to collection_url }
|
format.html { redirect_to collection_url }
|
||||||
format.js { render partial: "spree/admin/shared/destroy" }
|
format.js { render partial: "spree/admin/shared/destroy" }
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ module Spree
|
|||||||
include Spree::Core::ControllerHelpers::Auth
|
include Spree::Core::ControllerHelpers::Auth
|
||||||
include Spree::Core::ControllerHelpers::Common
|
include Spree::Core::ControllerHelpers::Common
|
||||||
include Spree::Core::ControllerHelpers::Order
|
include Spree::Core::ControllerHelpers::Order
|
||||||
include CablecarResponses
|
|
||||||
|
|
||||||
helper 'spree/base'
|
helper 'spree/base'
|
||||||
|
|
||||||
@@ -24,14 +23,12 @@ module Spree
|
|||||||
if spree_user_signed_in?
|
if spree_user_signed_in?
|
||||||
flash[:success] = t('devise.success.logged_in_succesfully')
|
flash[:success] = t('devise.success.logged_in_succesfully')
|
||||||
|
|
||||||
render cable_ready: cable_car.redirect_to(
|
redirect_to return_url_or_default(after_sign_in_path_for(spree_current_user))
|
||||||
url: return_url_or_default(after_sign_in_path_for(spree_current_user))
|
|
||||||
)
|
|
||||||
else
|
else
|
||||||
render status: :unauthorized, cable_ready: cable_car.inner_html(
|
message = t('devise.failure.invalid')
|
||||||
"#login-feedback",
|
render turbo_stream: turbo_stream.update(
|
||||||
partial("layouts/alert", locals: { type: "alert", message: t('devise.failure.invalid') })
|
'login-feedback', partial: 'layouts/alert', locals: { message:, type: 'alert' }
|
||||||
)
|
), status: :unprocessable_entity
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -60,11 +57,13 @@ module Spree
|
|||||||
end
|
end
|
||||||
|
|
||||||
def render_unconfirmed_response
|
def render_unconfirmed_response
|
||||||
render status: :unprocessable_entity, cable_ready: cable_car.inner_html(
|
message = t(:email_unconfirmed)
|
||||||
"#login-feedback",
|
|
||||||
partial("layouts/alert", locals: { type: "alert", message: t(:email_unconfirmed),
|
render turbo_stream: turbo_stream.update(
|
||||||
unconfirmed: true, tab: "login" })
|
'login-feedback',
|
||||||
)
|
partial: 'layouts/alert', locals: { type: "alert", message:, unconfirmed: true,
|
||||||
|
tab: "login", email: params.dig(:spree_user, :email) }
|
||||||
|
), status: :unprocessable_entity
|
||||||
end
|
end
|
||||||
|
|
||||||
def ensure_valid_locale_persisted
|
def ensure_valid_locale_persisted
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
module Spree
|
module Spree
|
||||||
class UsersController < ::BaseController
|
class UsersController < ::BaseController
|
||||||
include I18nHelper
|
include I18nHelper
|
||||||
include CablecarResponses
|
|
||||||
|
|
||||||
layout 'darkswarm'
|
layout 'darkswarm'
|
||||||
|
|
||||||
@@ -25,34 +24,17 @@ module Spree
|
|||||||
@unconfirmed_email = spree_current_user.unconfirmed_email
|
@unconfirmed_email = spree_current_user.unconfirmed_email
|
||||||
end
|
end
|
||||||
|
|
||||||
# Endpoint for queries to check if a user is already registered
|
|
||||||
def registered_email
|
|
||||||
registered = Spree::User.find_by(email: params[:email]).present?
|
|
||||||
|
|
||||||
if registered
|
|
||||||
render status: :ok, cable_ready: cable_car.
|
|
||||||
inner_html(
|
|
||||||
"#login-feedback",
|
|
||||||
partial("layouts/alert",
|
|
||||||
locals: { type: "alert", message: t('devise.failure.already_registered') })
|
|
||||||
).
|
|
||||||
dispatch_event(name: "login:modal:open")
|
|
||||||
else
|
|
||||||
head :not_found
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def create
|
def create
|
||||||
@user = Spree::User.new(user_params)
|
@user = Spree::User.new(user_params)
|
||||||
|
|
||||||
if @user.save
|
if @user.save
|
||||||
flash[:success] = t('devise.user_registrations.spree_user.signed_up_but_unconfirmed')
|
flash[:success] = t('devise.user_registrations.spree_user.signed_up_but_unconfirmed')
|
||||||
render cable_ready: cable_car.redirect_to(url: main_app.root_path)
|
redirect_to main_app.root_path
|
||||||
else
|
else
|
||||||
render status: :unprocessable_entity, cable_ready: cable_car.morph(
|
render turbo_stream: turbo_stream.update(
|
||||||
"#signup-tab",
|
'signup-tab',
|
||||||
partial("layouts/signup_tab", locals: { signup_form_user: @user })
|
partial: 'layouts/signup_tab', locals: { signup_form_user: @user }
|
||||||
)
|
), status: :unprocessable_entity
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -97,13 +79,10 @@ module Spree
|
|||||||
end
|
end
|
||||||
|
|
||||||
def render_alert_timestamp_error_message
|
def render_alert_timestamp_error_message
|
||||||
render cable_ready: cable_car.inner_html(
|
render turbo_stream: turbo_stream.update(
|
||||||
"#signup-feedback",
|
'signup-feedback',
|
||||||
partial("layouts/alert",
|
partial: 'layouts/alert',
|
||||||
locals: {
|
locals: { type: "alert", message: InvisibleCaptcha.timestamp_error_message }
|
||||||
type: "alert",
|
|
||||||
message: InvisibleCaptcha.timestamp_error_message
|
|
||||||
})
|
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
class UserConfirmationsController < DeviseController
|
class UserConfirmationsController < DeviseController
|
||||||
# Needed for access to current_ability, so we can authorize! actions
|
# Needed for access to current_ability, so we can authorize! actions
|
||||||
include Spree::Core::ControllerHelpers::Auth
|
include Spree::Core::ControllerHelpers::Auth
|
||||||
include CablecarResponses
|
|
||||||
|
|
||||||
# GET /resource/confirmation?confirmation_token=abcdef
|
# GET /resource/confirmation?confirmation_token=abcdef
|
||||||
def show
|
def show
|
||||||
@@ -29,12 +28,12 @@ class UserConfirmationsController < DeviseController
|
|||||||
set_flash_message(:error, :confirmation_not_sent)
|
set_flash_message(:error, :confirmation_not_sent)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
render cable_ready: cable_car.inner_html(
|
flash.now[:sucess] = t("devise.confirmations.send_instructions")
|
||||||
"##{params[:tab] || 'forgot'}-feedback",
|
|
||||||
partial("layouts/alert",
|
return render turbo_stream: turbo_stream.update(
|
||||||
locals: { type: "success", message: t("devise.confirmations.send_instructions") })
|
"#{params[:tab] || 'forgot'}-feedback",
|
||||||
|
partial: 'shared/flashes', locals: { flashes: flash }
|
||||||
)
|
)
|
||||||
return
|
|
||||||
end
|
end
|
||||||
|
|
||||||
respond_with_navigational(resource){ redirect_to login_path }
|
respond_with_navigational(resource){ redirect_to login_path }
|
||||||
|
|||||||
@@ -1,37 +1,40 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class UserPasswordsController < Spree::UserPasswordsController
|
class UserPasswordsController < Spree::UserPasswordsController
|
||||||
include CablecarResponses
|
|
||||||
|
|
||||||
layout 'darkswarm'
|
layout 'darkswarm'
|
||||||
|
|
||||||
def create
|
def create
|
||||||
return render_unconfirmed_response if user_unconfirmed?
|
return render_unconfirmed_response if user_unconfirmed?
|
||||||
|
|
||||||
self.resource = resource_class.send_reset_password_instructions(raw_params[resource_name])
|
self.resource = resource_class.send_reset_password_instructions(raw_params[resource_name])
|
||||||
|
status = :ok
|
||||||
|
|
||||||
if resource.errors.empty?
|
if resource.errors.empty?
|
||||||
render cable_ready: cable_car.inner_html(
|
message, type = [t(:password_reset_sent), :success]
|
||||||
"#forgot-feedback",
|
|
||||||
partial("layouts/alert", locals: { type: "success", message: t(:password_reset_sent) })
|
|
||||||
)
|
|
||||||
else
|
else
|
||||||
render status: :not_found, cable_ready: cable_car.inner_html(
|
message, type = [t(:email_not_found), :alert]
|
||||||
"#forgot-feedback",
|
status = :not_found
|
||||||
partial("layouts/alert", locals: { type: "alert", message: t(:email_not_found) })
|
|
||||||
)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
render turbo_stream: turbo_stream.update(
|
||||||
|
'forgot-feedback',
|
||||||
|
partial: 'layouts/alert',
|
||||||
|
locals: { type:, message:, tab: 'forgot',
|
||||||
|
unconfirmed: false, email: params.dig(:spree_user, :email) }
|
||||||
|
), status:
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def render_unconfirmed_response
|
def render_unconfirmed_response
|
||||||
render status: :unprocessable_entity, cable_ready: cable_car.inner_html(
|
message, type, unconfirmed, tab = [t(:email_unconfirmed), :alert, true, 'forgot']
|
||||||
"#forgot-feedback",
|
|
||||||
partial("layouts/alert",
|
render turbo_stream: turbo_stream.update(
|
||||||
locals: { type: "alert", message: t(:email_unconfirmed),
|
'forgot-feedback',
|
||||||
unconfirmed: true, tab: "forgot" })
|
partial: 'layouts/alert',
|
||||||
)
|
locals: { type:, message:, tab:,
|
||||||
|
unconfirmed:, email: params.dig(:spree_user, :email) }
|
||||||
|
), status: :unprocessable_entity
|
||||||
end
|
end
|
||||||
|
|
||||||
def user_unconfirmed?
|
def user_unconfirmed?
|
||||||
|
|||||||
@@ -90,11 +90,13 @@ class VoucherAdjustmentsController < BaseController
|
|||||||
voucher_code: voucher_params[:voucher_code], enterprise: @order.distributor
|
voucher_code: voucher_params[:voucher_code], enterprise: @order.distributor
|
||||||
)
|
)
|
||||||
voucher = vine_voucher_validator.validate
|
voucher = vine_voucher_validator.validate
|
||||||
|
errors = vine_voucher_validator.errors
|
||||||
|
|
||||||
return nil if vine_voucher_validator.errors[:not_found_voucher].present?
|
return nil if errors[:not_found_voucher].present?
|
||||||
|
|
||||||
if vine_voucher_validator.errors.present?
|
if errors.present?
|
||||||
@order.errors.add(:voucher_code, I18n.t('checkout.errors.add_voucher_error'))
|
message = errors[:invalid_voucher] || I18n.t('checkout.errors.add_voucher_error')
|
||||||
|
@order.errors.add(:voucher_code, message)
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class WebhookEndpointsController < BaseController
|
class WebhookEndpointsController < BaseController
|
||||||
before_action :load_resource, only: :destroy
|
before_action :load_resource, only: [:destroy, :test]
|
||||||
|
|
||||||
def create
|
def create
|
||||||
webhook_endpoint = spree_current_user.webhook_endpoints.new(webhook_endpoint_params)
|
webhook_endpoint = spree_current_user.webhook_endpoints.new(webhook_endpoint_params)
|
||||||
@@ -25,12 +25,30 @@ class WebhookEndpointsController < BaseController
|
|||||||
redirect_to redirect_path
|
redirect_to redirect_path
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test
|
||||||
|
at = Time.zone.now
|
||||||
|
test_payload = Payments::WebhookPayload.test_data.to_hash
|
||||||
|
|
||||||
|
WebhookDeliveryJob.perform_later(@webhook_endpoint.url, "payment.completed", test_payload, at:)
|
||||||
|
|
||||||
|
flash[:success] = t(".success")
|
||||||
|
respond_with do |format|
|
||||||
|
format.turbo_stream do
|
||||||
|
render turbo_stream: turbo_stream.update(
|
||||||
|
:flashes, partial: "shared/flashes", locals: { flashes: flash }
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
def load_resource
|
def load_resource
|
||||||
@webhook_endpoint = spree_current_user.webhook_endpoints.find(params[:id])
|
@webhook_endpoint = spree_current_user.webhook_endpoints.find(params[:id])
|
||||||
end
|
end
|
||||||
|
|
||||||
def webhook_endpoint_params
|
def webhook_endpoint_params
|
||||||
params.require(:webhook_endpoint).permit(:url)
|
params.require(:webhook_endpoint).permit(:url, :webhook_type)
|
||||||
end
|
end
|
||||||
|
|
||||||
def redirect_path
|
def redirect_path
|
||||||
|
|||||||
@@ -41,5 +41,11 @@ module Admin
|
|||||||
def hide_producer_column?(producer_options)
|
def hide_producer_column?(producer_options)
|
||||||
spree_current_user.column_preferences.bulk_edit_product.empty? && producer_options.one?
|
spree_current_user.column_preferences.bulk_edit_product.empty? && producer_options.one?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# check if the user is in the "admins" group or if it's enabled for any of
|
||||||
|
# the enterprises the user manages
|
||||||
|
def variant_tag_enabled?(user)
|
||||||
|
feature?(:variant_tag, user) || feature?(:variant_tag, *user.enterprises)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -72,7 +72,23 @@ module ApplicationHelper
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Update "v1" to invalidate existing cache key
|
||||||
def cache_key_with_locale(key, locale)
|
def cache_key_with_locale(key, locale)
|
||||||
Array.wrap(key) + [locale.to_s, I18nDigests.for_locale(locale)]
|
Array.wrap(key) + ["v3", locale.to_s, I18nDigests.for_locale(locale)]
|
||||||
|
end
|
||||||
|
|
||||||
|
def pdf_stylesheet_pack_tag(source)
|
||||||
|
# With shakapacker dev server running, the wicked_pdf_stylesheet_pack_tag will produce a
|
||||||
|
# relative path, because we don't have `config.action_controller.asset_host`. Relative path
|
||||||
|
# can't be resolved by `wkhtmltopdf`. So we pass the wepacker dev server host and port to
|
||||||
|
# the shakapacker helper, so it generates the correct url.
|
||||||
|
# For more info: https://stackoverflow.com/questions/58490299/how-to-include-css-stylesheet-into-wicked-pdf/60541688#60541688
|
||||||
|
if running_in_development?
|
||||||
|
options = { media: "all",
|
||||||
|
host: "#{Shakapacker.dev_server.host}:#{Shakapacker.dev_server.port}" }
|
||||||
|
stylesheet_pack_tag(source, **options)
|
||||||
|
else
|
||||||
|
wicked_pdf_stylesheet_pack_tag(source)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -63,8 +63,11 @@ module EnterprisesHelper
|
|||||||
url = object_url(enterprise)
|
url = object_url(enterprise)
|
||||||
name = t(:delete)
|
name = t(:delete)
|
||||||
options = {}
|
options = {}
|
||||||
options[:class] = "delete-resource"
|
options[:data] = {
|
||||||
options[:data] = { action: 'remove', confirm: enterprise_confirm_delete_message(enterprise) }
|
turbo: true,
|
||||||
|
'turbo-method': 'delete',
|
||||||
|
'turbo-confirm': enterprise_confirm_delete_message(enterprise)
|
||||||
|
}
|
||||||
link_to_with_icon 'icon-trash', name, url, options
|
link_to_with_icon 'icon-trash', name, url, options
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -147,6 +147,10 @@ module Spree
|
|||||||
dom_id(record, 'spree')
|
dom_id(record, 'spree')
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def inventory_enabled?(enterprises)
|
||||||
|
!feature?(:variant_tag, *enterprises) && feature?(:inventory, *enterprises)
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def attribute_name_for(field_name)
|
def attribute_name_for(field_name)
|
||||||
|
|||||||
@@ -120,7 +120,7 @@ module Spree
|
|||||||
end
|
end
|
||||||
|
|
||||||
def cancel_event_link(order)
|
def cancel_event_link(order)
|
||||||
event_label = I18n.t("cancel", scope: "actions")
|
event_label = I18n.t("cancel_order", scope: "actions")
|
||||||
button_link_to(event_label,
|
button_link_to(event_label,
|
||||||
fire_admin_order_url(order, e: "cancel"),
|
fire_admin_order_url(order, e: "cancel"),
|
||||||
method: :put, icon: "icon-cancel", form_id: "cancel_order_form")
|
method: :put, icon: "icon-cancel", form_id: "cancel_order_form")
|
||||||
|
|||||||
@@ -12,7 +12,10 @@ class ApplicationRecord < ActiveRecord::Base
|
|||||||
self.include_root_in_json = true
|
self.include_root_in_json = true
|
||||||
|
|
||||||
def self.image_service
|
def self.image_service
|
||||||
ENV["S3_BUCKET"].present? ? :amazon_public : :local
|
return :local if ENV["S3_BUCKET"].blank?
|
||||||
|
return :amazon_public if ENV["S3_ENDPOINT"].blank?
|
||||||
|
|
||||||
|
:s3_compatible_storage_public
|
||||||
end
|
end
|
||||||
|
|
||||||
# We might have a development environment without S3 but with a database
|
# We might have a development environment without S3 but with a database
|
||||||
|
|||||||
@@ -5,6 +5,18 @@ require "active_support/concern"
|
|||||||
module CalculatedAdjustments
|
module CalculatedAdjustments
|
||||||
extend ActiveSupport::Concern
|
extend ActiveSupport::Concern
|
||||||
|
|
||||||
|
CALCULATORS = %w{
|
||||||
|
Calculator::DefaultTax
|
||||||
|
Calculator::FlatPercentItemTotal
|
||||||
|
Calculator::FlatPercentPerItem
|
||||||
|
Calculator::FlatRate
|
||||||
|
Calculator::FlexiRate
|
||||||
|
Calculator::None
|
||||||
|
Calculator::PerItem
|
||||||
|
Calculator::PriceSack
|
||||||
|
Calculator::Weight
|
||||||
|
}.freeze
|
||||||
|
|
||||||
included do
|
included do
|
||||||
has_one :calculator, as: :calculable, class_name: "Spree::Calculator", dependent: :destroy
|
has_one :calculator, as: :calculable, class_name: "Spree::Calculator", dependent: :destroy
|
||||||
accepts_nested_attributes_for :calculator
|
accepts_nested_attributes_for :calculator
|
||||||
@@ -32,7 +44,11 @@ module CalculatedAdjustments
|
|||||||
end
|
end
|
||||||
|
|
||||||
def calculator_type=(calculator_type)
|
def calculator_type=(calculator_type)
|
||||||
klass = calculator_type.constantize if calculator_type
|
return unless calculator_type
|
||||||
|
|
||||||
|
return unless CALCULATORS.include?(calculator_type)
|
||||||
|
|
||||||
|
klass = calculator_type.constantize
|
||||||
self.calculator = klass.new if klass && !calculator.is_a?(klass)
|
self.calculator = klass.new if klass && !calculator.is_a?(klass)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
module ProductSortByStocks
|
module ProductSortByStocks
|
||||||
extend ActiveSupport::Concern
|
extend ActiveSupport::Concern
|
||||||
|
|
||||||
included do
|
included do # rubocop:disable Metrics/BlockLength
|
||||||
@on_hand_sql = Arel.sql("(
|
@on_hand_sql = Arel.sql("(
|
||||||
SELECT COALESCE(SUM(si.count_on_hand), 0)
|
SELECT COALESCE(SUM(si.count_on_hand), 0)
|
||||||
FROM spree_variants v
|
FROM spree_variants v
|
||||||
@@ -20,8 +20,18 @@ module ProductSortByStocks
|
|||||||
GROUP BY v.product_id
|
GROUP BY v.product_id
|
||||||
)")
|
)")
|
||||||
|
|
||||||
|
# When a product is On-Demand (backorderable = true), return the product name.
|
||||||
|
# This allows alphabetical ordering inside the On-Demand group.
|
||||||
|
# For non-On-Demand products, return NULL so normal on_hand sorting still applies.
|
||||||
|
@backorderable_name_sql = Arel.sql("
|
||||||
|
CASE
|
||||||
|
WHEN (#{@backorderable_priority_sql}) THEN spree_products.name
|
||||||
|
ELSE NULL
|
||||||
|
END
|
||||||
|
")
|
||||||
|
|
||||||
class << self
|
class << self
|
||||||
attr_reader :on_hand_sql, :backorderable_priority_sql
|
attr_reader :on_hand_sql, :backorderable_priority_sql, :backorderable_name_sql
|
||||||
end
|
end
|
||||||
|
|
||||||
ransacker :on_hand do
|
ransacker :on_hand do
|
||||||
@@ -31,5 +41,9 @@ module ProductSortByStocks
|
|||||||
ransacker :backorderable_priority do
|
ransacker :backorderable_priority do
|
||||||
@backorderable_priority_sql
|
@backorderable_priority_sql
|
||||||
end
|
end
|
||||||
|
|
||||||
|
ransacker :backorderable_name do
|
||||||
|
@backorderable_name_sql
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -50,11 +50,11 @@ class Enterprise < ApplicationRecord
|
|||||||
has_many :distributed_orders, class_name: 'Spree::Order',
|
has_many :distributed_orders, class_name: 'Spree::Order',
|
||||||
foreign_key: 'distributor_id',
|
foreign_key: 'distributor_id',
|
||||||
inverse_of: :distributor,
|
inverse_of: :distributor,
|
||||||
dependent: :restrict_with_exception
|
dependent: :restrict_with_error
|
||||||
|
|
||||||
belongs_to :address, class_name: 'Spree::Address'
|
belongs_to :address, class_name: 'Spree::Address'
|
||||||
belongs_to :business_address, optional: true, class_name: 'Spree::Address', dependent: :destroy
|
belongs_to :business_address, optional: true, class_name: 'Spree::Address', dependent: :destroy
|
||||||
has_many :enterprise_fees, dependent: :restrict_with_exception
|
has_many :enterprise_fees, dependent: :restrict_with_error
|
||||||
has_many :enterprise_roles, dependent: :destroy
|
has_many :enterprise_roles, dependent: :destroy
|
||||||
has_many :users, through: :enterprise_roles
|
has_many :users, through: :enterprise_roles
|
||||||
belongs_to :owner, class_name: 'Spree::User',
|
belongs_to :owner, class_name: 'Spree::User',
|
||||||
@@ -62,21 +62,22 @@ class Enterprise < ApplicationRecord
|
|||||||
has_many :distributor_payment_methods,
|
has_many :distributor_payment_methods,
|
||||||
inverse_of: :distributor,
|
inverse_of: :distributor,
|
||||||
foreign_key: :distributor_id,
|
foreign_key: :distributor_id,
|
||||||
dependent: :restrict_with_exception
|
dependent: :restrict_with_error
|
||||||
has_many :distributor_shipping_methods,
|
has_many :distributor_shipping_methods,
|
||||||
inverse_of: :distributor,
|
inverse_of: :distributor,
|
||||||
foreign_key: :distributor_id,
|
foreign_key: :distributor_id,
|
||||||
dependent: :restrict_with_exception
|
dependent: :restrict_with_error
|
||||||
has_many :payment_methods, through: :distributor_payment_methods
|
has_many :payment_methods, through: :distributor_payment_methods
|
||||||
has_many :shipping_methods, through: :distributor_shipping_methods
|
has_many :shipping_methods, through: :distributor_shipping_methods
|
||||||
has_many :customers, dependent: :destroy
|
has_many :customers, dependent: :destroy
|
||||||
has_many :inventory_items, dependent: :destroy
|
has_many :inventory_items, dependent: :destroy
|
||||||
has_many :tag_rules, dependent: :destroy
|
has_many :tag_rules, dependent: :destroy
|
||||||
has_one :stripe_account, dependent: :destroy
|
has_one :stripe_account, dependent: :destroy
|
||||||
has_many :vouchers, dependent: :restrict_with_exception
|
has_many :vouchers, dependent: :restrict_with_error
|
||||||
has_many :connected_apps, dependent: :destroy
|
has_many :connected_apps, dependent: :destroy
|
||||||
has_many :dfc_permissions, dependent: :destroy
|
has_many :dfc_permissions, dependent: :destroy
|
||||||
has_one :custom_tab, dependent: :destroy
|
has_one :custom_tab, dependent: :destroy
|
||||||
|
has_one :semantic_link, as: :subject, dependent: :delete
|
||||||
|
|
||||||
delegate :latitude, :longitude, :city, :state_name, to: :address
|
delegate :latitude, :longitude, :city, :state_name, to: :address
|
||||||
|
|
||||||
@@ -110,11 +111,14 @@ class Enterprise < ApplicationRecord
|
|||||||
end
|
end
|
||||||
|
|
||||||
validates :logo,
|
validates :logo,
|
||||||
processable_image: true,
|
processable_file: true,
|
||||||
content_type: %r{\Aimage/(png|jpeg|gif|jpg|svg\+xml|webp)\Z}
|
content_type: ::Spree::Image::ACCEPTED_CONTENT_TYPES
|
||||||
validates :promo_image,
|
validates :promo_image,
|
||||||
processable_image: true,
|
processable_file: true,
|
||||||
content_type: %r{\Aimage/(png|jpeg|gif|jpg|svg\+xml|webp)\Z}
|
content_type: ::Spree::Image::ACCEPTED_CONTENT_TYPES
|
||||||
|
validates :white_label_logo,
|
||||||
|
processable_file: true,
|
||||||
|
content_type: ::Spree::Image::ACCEPTED_CONTENT_TYPES
|
||||||
validates :terms_and_conditions, content_type: {
|
validates :terms_and_conditions, content_type: {
|
||||||
in: "application/pdf",
|
in: "application/pdf",
|
||||||
message: I18n.t(:enterprise_terms_and_conditions_type_error),
|
message: I18n.t(:enterprise_terms_and_conditions_type_error),
|
||||||
|
|||||||
@@ -29,11 +29,11 @@ class EnterpriseGroup < ApplicationRecord
|
|||||||
has_one_attached :promo_image, service: image_service
|
has_one_attached :promo_image, service: image_service
|
||||||
|
|
||||||
validates :logo,
|
validates :logo,
|
||||||
processable_image: true,
|
processable_file: true,
|
||||||
content_type: %r{\Aimage/(png|jpeg|gif|jpg|svg\+xml|webp)\Z}
|
content_type: ::Spree::Image::ACCEPTED_CONTENT_TYPES
|
||||||
validates :promo_image,
|
validates :promo_image,
|
||||||
processable_image: true,
|
processable_file: true,
|
||||||
content_type: %r{\Aimage/(png|jpeg|gif|jpg|svg\+xml|webp)\Z}
|
content_type: ::Spree::Image::ACCEPTED_CONTENT_TYPES
|
||||||
|
|
||||||
scope :by_position, -> { order('position ASC') }
|
scope :by_position, -> { order('position ASC') }
|
||||||
scope :on_front_page, -> { where(on_front_page: true) }
|
scope :on_front_page, -> { where(on_front_page: true) }
|
||||||
|
|||||||
@@ -95,8 +95,8 @@ class Invoice
|
|||||||
def display_line_item_tax_rate(item)
|
def display_line_item_tax_rate(item)
|
||||||
all_tax_adjustments.select { |a|
|
all_tax_adjustments.select { |a|
|
||||||
a.adjustable.type == 'Spree::LineItem' && a.adjustable.id == item.id
|
a.adjustable.type == 'Spree::LineItem' && a.adjustable.id == item.id
|
||||||
}.map(&:originator).map { |tr|
|
}.map(&:originator).map(&:amount).sort.map { |amount|
|
||||||
number_to_percentage(tr.amount * 100, precision: 1)
|
number_to_percentage(amount * 100, precision: 1)
|
||||||
}.join(", ")
|
}.join(", ")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -196,12 +196,15 @@ module Spree
|
|||||||
def add_product_management_abilities(user)
|
def add_product_management_abilities(user)
|
||||||
# Enterprise User can only access products that they are a supplier for
|
# Enterprise User can only access products that they are a supplier for
|
||||||
can [:create], Spree::Product
|
can [:create], Spree::Product
|
||||||
|
# An enterperprise user can change a product if they are supplier of at least
|
||||||
|
# one of the product's associated variants
|
||||||
can [:admin, :read, :index, :update,
|
can [:admin, :read, :index, :update,
|
||||||
:seo, :group_buy_options,
|
:seo, :group_buy_options,
|
||||||
:bulk_update, :clone, :delete,
|
:bulk_update, :clone, :delete,
|
||||||
:destroy], Spree::Product do |product|
|
:destroy], Spree::Product do |product|
|
||||||
OpenFoodNetwork::Permissions.new(user).managed_product_enterprises.include?(
|
variant_suppliers = product.variants.map(&:supplier)
|
||||||
product.variants.first.supplier
|
OpenFoodNetwork::Permissions.new(user).managed_product_enterprises.intersect?(
|
||||||
|
variant_suppliers
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -31,7 +31,6 @@ module Spree
|
|||||||
preference :admin_products_per_page, :integer, default: 10
|
preference :admin_products_per_page, :integer, default: 10
|
||||||
# Should only be true if you don't need to track inventory
|
# Should only be true if you don't need to track inventory
|
||||||
preference :allow_backorder_shipping, :boolean, default: false
|
preference :allow_backorder_shipping, :boolean, default: false
|
||||||
preference :allow_checkout_on_gateway_error, :boolean, default: false
|
|
||||||
preference :allow_guest_checkout, :boolean, default: true
|
preference :allow_guest_checkout, :boolean, default: true
|
||||||
preference :currency_decimal_mark, :string, default: "."
|
preference :currency_decimal_mark, :string, default: "."
|
||||||
preference :currency_symbol_position, :string, default: "before"
|
preference :currency_symbol_position, :string, default: "before"
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
module Spree
|
module Spree
|
||||||
class Image < Asset
|
class Image < Asset
|
||||||
|
ACCEPTED_CONTENT_TYPES = %r{\Aimage/(png|jpeg|gif|jpg|svg\+xml|webp)\Z}
|
||||||
|
|
||||||
has_one_attached :attachment, service: image_service do |attachment|
|
has_one_attached :attachment, service: image_service do |attachment|
|
||||||
attachment.variant :mini, resize_to_fill: [48, 48]
|
attachment.variant :mini, resize_to_fill: [48, 48]
|
||||||
attachment.variant :small, resize_to_fill: [227, 227]
|
attachment.variant :small, resize_to_fill: [227, 227]
|
||||||
@@ -11,8 +13,8 @@ module Spree
|
|||||||
|
|
||||||
validates :attachment,
|
validates :attachment,
|
||||||
attached: true,
|
attached: true,
|
||||||
processable_image: true,
|
processable_file: true,
|
||||||
content_type: %r{\Aimage/(png|jpeg|gif|jpg|svg\+xml|webp)\Z}
|
content_type: ACCEPTED_CONTENT_TYPES
|
||||||
validate :no_attachment_errors
|
validate :no_attachment_errors
|
||||||
|
|
||||||
def self.default_image_url(size)
|
def self.default_image_url(size)
|
||||||
|
|||||||
@@ -24,6 +24,8 @@ module Spree
|
|||||||
before_validation :copy_price
|
before_validation :copy_price
|
||||||
before_validation :copy_tax_category
|
before_validation :copy_tax_category
|
||||||
before_validation :copy_dimensions
|
before_validation :copy_dimensions
|
||||||
|
before_validation :copy_product_name, on: :create
|
||||||
|
before_validation :copy_variant_name, on: :create
|
||||||
|
|
||||||
validates :quantity, numericality: {
|
validates :quantity, numericality: {
|
||||||
only_integer: true,
|
only_integer: true,
|
||||||
@@ -250,6 +252,18 @@ module Spree
|
|||||||
adjustments.enterprise_fee
|
adjustments.enterprise_fee
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def full_variant_name
|
||||||
|
return variant_name if variant_name.present?
|
||||||
|
|
||||||
|
variant.full_name
|
||||||
|
end
|
||||||
|
|
||||||
|
def full_product_name
|
||||||
|
return product_name if product_name.present?
|
||||||
|
|
||||||
|
variant.product.name
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def computed_weight_from_variant
|
def computed_weight_from_variant
|
||||||
@@ -274,6 +288,18 @@ module Spree
|
|||||||
order.create_tax_charge!
|
order.create_tax_charge!
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def copy_product_name
|
||||||
|
return if variant.nil? || variant.product.nil?
|
||||||
|
|
||||||
|
self.product_name = variant.product.name
|
||||||
|
end
|
||||||
|
|
||||||
|
def copy_variant_name
|
||||||
|
return if variant.nil?
|
||||||
|
|
||||||
|
self.variant_name = variant.full_name
|
||||||
|
end
|
||||||
|
|
||||||
def update_inventory_before_destroy
|
def update_inventory_before_destroy
|
||||||
# This is necessary before destroying the line item
|
# This is necessary before destroying the line item
|
||||||
# so that update_inventory will restore stock to the variant
|
# so that update_inventory will restore stock to the variant
|
||||||
|
|||||||
@@ -437,18 +437,13 @@ module Spree
|
|||||||
#
|
#
|
||||||
# Returns:
|
# Returns:
|
||||||
# - true if all pending_payments processed successfully
|
# - true if all pending_payments processed successfully
|
||||||
# - true if a payment failed, ie. raised a GatewayError
|
|
||||||
# which gets rescued and converted to TRUE when
|
|
||||||
# :allow_checkout_gateway_error is set to true
|
|
||||||
# - false if a payment failed, ie. raised a GatewayError
|
# - false if a payment failed, ie. raised a GatewayError
|
||||||
# which gets rescued and converted to FALSE when
|
# which gets rescued and converted to FALSE
|
||||||
# :allow_checkout_on_gateway_error is set to false
|
|
||||||
#
|
#
|
||||||
def process_payments!
|
def process_payments!
|
||||||
process_each_payment(&:process!)
|
process_each_payment(&:process!)
|
||||||
rescue Core::GatewayError => e
|
rescue Core::GatewayError => e
|
||||||
result = !!Spree::Config[:allow_checkout_on_gateway_error]
|
errors.add(:base, e.message) && (return false)
|
||||||
errors.add(:base, e.message) && (return result)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def process_payments_offline!
|
def process_payments_offline!
|
||||||
|
|||||||
@@ -101,6 +101,24 @@ module Spree
|
|||||||
end
|
end
|
||||||
|
|
||||||
after_transition to: :completed, do: :set_captured_at
|
after_transition to: :completed, do: :set_captured_at
|
||||||
|
after_transition do |payment, transition|
|
||||||
|
# Catch any exceptions to prevent any rollback potentially
|
||||||
|
# preventing payment from going through
|
||||||
|
ActiveSupport::Notifications.instrument(
|
||||||
|
"ofn.payment_transition", payment: payment, event: transition.to
|
||||||
|
)
|
||||||
|
rescue StandardError => e
|
||||||
|
Rails.logger.fatal "ActiveSupport::Notification.instrument failed params: " \
|
||||||
|
"<event_type:ofn.payment_transition> " \
|
||||||
|
"<payment_id:#{payment.id}> " \
|
||||||
|
"<event:#{transition.to}>"
|
||||||
|
Alert.raise(
|
||||||
|
e,
|
||||||
|
metadata: {
|
||||||
|
event_tye: "ofn.payment_transition", payment_id: payment.id, event: transition.to
|
||||||
|
}
|
||||||
|
)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def money
|
def money
|
||||||
|
|||||||
@@ -183,6 +183,7 @@ module Spree
|
|||||||
|
|
||||||
options.merge!({ billing_address: order.bill_address.try(:active_merchant_hash),
|
options.merge!({ billing_address: order.bill_address.try(:active_merchant_hash),
|
||||||
shipping_address: order.ship_address.try(:active_merchant_hash) })
|
shipping_address: order.ship_address.try(:active_merchant_hash) })
|
||||||
|
options.merge!(payment: self)
|
||||||
|
|
||||||
options
|
options
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -52,10 +52,6 @@ module Spree
|
|||||||
.where(environment: [Rails.env, "", nil])
|
.where(environment: [Rails.env, "", nil])
|
||||||
}
|
}
|
||||||
|
|
||||||
def self.providers
|
|
||||||
Rails.application.config.spree.payment_methods
|
|
||||||
end
|
|
||||||
|
|
||||||
def configured?
|
def configured?
|
||||||
!stripe? || stripe_configured?
|
!stripe? || stripe_configured?
|
||||||
end
|
end
|
||||||
@@ -93,8 +89,8 @@ module Spree
|
|||||||
type.demodulize.downcase
|
type.demodulize.downcase
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.find_with_destroyed(*args)
|
def self.find_with_destroyed(*)
|
||||||
unscoped { find(*args) }
|
unscoped { find(*) }
|
||||||
end
|
end
|
||||||
|
|
||||||
def payment_profiles_supported?
|
def payment_profiles_supported?
|
||||||
@@ -118,8 +114,8 @@ module Spree
|
|||||||
end
|
end
|
||||||
|
|
||||||
def self.clean_name
|
def self.clean_name
|
||||||
i18n_key = "spree.admin.payment_methods.providers.#{name.demodulize.downcase}"
|
scope = "spree.admin.payment_methods.providers"
|
||||||
I18n.t(i18n_key)
|
I18n.t(name.demodulize.downcase, scope:)
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|||||||
94
app/models/spree/payment_method/taler.rb
Normal file
94
app/models/spree/payment_method/taler.rb
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require "taler"
|
||||||
|
|
||||||
|
module Spree
|
||||||
|
class PaymentMethod
|
||||||
|
# GNU Taler is a distributed, open source payment system.
|
||||||
|
# You need a hosted Taler backend server to process payments.
|
||||||
|
#
|
||||||
|
# For testing, you can use the official demo backend:
|
||||||
|
#
|
||||||
|
# - Merchant UX: https://backend.demo.taler.net
|
||||||
|
# - Username: sandbox
|
||||||
|
# - Password: sandbox
|
||||||
|
#
|
||||||
|
# Configure this payment method for testing with:
|
||||||
|
#
|
||||||
|
# - backend_url: https://backend.demo.taler.net/instances/sandbox
|
||||||
|
# - api_key: sandbox
|
||||||
|
class Taler < PaymentMethod
|
||||||
|
preference :backend_url, :string
|
||||||
|
preference :api_key, :password
|
||||||
|
|
||||||
|
# Name of the view to display during checkout
|
||||||
|
def method_type
|
||||||
|
"check" # empty view
|
||||||
|
end
|
||||||
|
|
||||||
|
def external_gateway?
|
||||||
|
true
|
||||||
|
end
|
||||||
|
|
||||||
|
# The backend provides this URL. It can look like this:
|
||||||
|
# https://backend.demo.taler.net/instances/blog/orders/2026..?token=S8Y..&session_id=b0b..
|
||||||
|
def external_payment_url(options)
|
||||||
|
order = options.fetch(:order)
|
||||||
|
payment = load_payment(order)
|
||||||
|
|
||||||
|
payment.source ||= self
|
||||||
|
payment.response_code ||= create_taler_order(payment)
|
||||||
|
payment.redirect_auth_url ||= fetch_order_url(payment)
|
||||||
|
payment.save! if payment.changed?
|
||||||
|
|
||||||
|
payment.redirect_auth_url
|
||||||
|
end
|
||||||
|
|
||||||
|
# Main method called by Spree::Payment::Processing during checkout
|
||||||
|
# when the user is redirected back to the app.
|
||||||
|
#
|
||||||
|
# The payment has already been made and we need to verify the success.
|
||||||
|
def purchase(_money, _source, gateway_options)
|
||||||
|
payment = gateway_options[:payment]
|
||||||
|
|
||||||
|
return unless payment.response_code
|
||||||
|
|
||||||
|
taler_order = client.fetch_order(payment.response_code)
|
||||||
|
status = taler_order["order_status"]
|
||||||
|
success = (status == "paid")
|
||||||
|
message = I18n.t(status, default: status, scope: "taler.order_status")
|
||||||
|
|
||||||
|
ActiveMerchant::Billing::Response.new(success, message)
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def load_payment(order)
|
||||||
|
order.payments.checkout.where(payment_method: self).last
|
||||||
|
end
|
||||||
|
|
||||||
|
def create_taler_order(payment)
|
||||||
|
# We are ignoring currency for now so that we can test with the
|
||||||
|
# current demo backend only working with the KUDOS currency.
|
||||||
|
taler_amount = "KUDOS:#{payment.amount}"
|
||||||
|
urls = Rails.application.routes.url_helpers
|
||||||
|
new_order = client.create_order(
|
||||||
|
taler_amount,
|
||||||
|
I18n.t("payment_method_taler.order_summary"),
|
||||||
|
urls.payment_gateways_confirm_taler_url(payment_id: payment.id),
|
||||||
|
)
|
||||||
|
|
||||||
|
new_order["order_id"]
|
||||||
|
end
|
||||||
|
|
||||||
|
def fetch_order_url(payment)
|
||||||
|
order = client.fetch_order(payment.response_code)
|
||||||
|
order["order_status_url"]
|
||||||
|
end
|
||||||
|
|
||||||
|
def client
|
||||||
|
@client ||= ::Taler::Client.new(preferred_backend_url, preferred_api_key)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -31,7 +31,8 @@ module Spree
|
|||||||
|
|
||||||
acts_as_paranoid
|
acts_as_paranoid
|
||||||
|
|
||||||
searchable_attributes :meta_keywords, :sku, :on_hand, :backorderable_priority
|
searchable_attributes :meta_keywords, :sku, :on_hand, :backorderable_priority,
|
||||||
|
:backorderable_name
|
||||||
searchable_associations :properties, :variants
|
searchable_associations :properties, :variants
|
||||||
searchable_scopes :active, :with_properties
|
searchable_scopes :active, :with_properties
|
||||||
|
|
||||||
|
|||||||
@@ -2,5 +2,11 @@
|
|||||||
|
|
||||||
# Records a webhook url to send notifications to
|
# Records a webhook url to send notifications to
|
||||||
class WebhookEndpoint < ApplicationRecord
|
class WebhookEndpoint < ApplicationRecord
|
||||||
|
WEBHOOK_TYPES = %w(order_cycle_opened payment_status_changed).freeze
|
||||||
|
|
||||||
validates :url, presence: true
|
validates :url, presence: true
|
||||||
|
validates :webhook_type, presence: true, inclusion: { in: WEBHOOK_TYPES }
|
||||||
|
|
||||||
|
scope :order_cycle_opened, -> { where(webhook_type: "order_cycle_opened") }
|
||||||
|
scope :payment_status, -> { where(webhook_type: "payment_status_changed") }
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ module Api
|
|||||||
# medium: LOGO_MEDIUM_URL
|
# medium: LOGO_MEDIUM_URL
|
||||||
# }
|
# }
|
||||||
def attachment_urls(attachment, styles)
|
def attachment_urls(attachment, styles)
|
||||||
return unless attachment.variable?
|
return unless attachment.persisted? && attachment.variable?
|
||||||
|
|
||||||
styles.index_with do |style|
|
styles.index_with do |style|
|
||||||
Rails.application.routes.url_helpers.
|
Rails.application.routes.url_helpers.
|
||||||
|
|||||||
@@ -11,7 +11,9 @@ class ImageImporter
|
|||||||
|
|
||||||
image = Spree::Image.create do |img|
|
image = Spree::Image.create do |img|
|
||||||
PrivateAddressCheck.only_public_connections do
|
PrivateAddressCheck.only_public_connections do
|
||||||
img.attachment.attach(io: valid_url.open, filename:, metadata:)
|
io = valid_url.open
|
||||||
|
content_type = Marcel::MimeType.for(io)
|
||||||
|
img.attachment.attach(io:, filename:, metadata:, content_type:)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
product.image = image if image
|
product.image = image if image
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ class LineItemSyncer
|
|||||||
end
|
end
|
||||||
|
|
||||||
def add_order_update_issue(order, line_item)
|
def add_order_update_issue(order, line_item)
|
||||||
issue_description = "#{line_item.product.name} - #{line_item.variant.full_name}"
|
issue_description = "#{line_item.product.name} - #{line_item.full_variant_name}"
|
||||||
issue_description << " - #{stock_issue_description(line_item)}" if line_item.insufficient_stock?
|
issue_description << " - #{stock_issue_description(line_item)}" if line_item.insufficient_stock?
|
||||||
order_update_issues.add(order, issue_description)
|
order_update_issues.add(order, issue_description)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ module OrderCycles
|
|||||||
def create
|
def create
|
||||||
oc = @original_order_cycle.dup
|
oc = @original_order_cycle.dup
|
||||||
oc.name = I18n.t("models.order_cycle.cloned_order_cycle_name", order_cycle: oc.name)
|
oc.name = I18n.t("models.order_cycle.cloned_order_cycle_name", order_cycle: oc.name)
|
||||||
oc.orders_open_at = oc.orders_close_at = oc.mails_sent = oc.processed_at = nil
|
oc.orders_open_at = oc.orders_close_at = oc.mails_sent = oc.processed_at = oc.opened_at = nil
|
||||||
oc.coordinator_fee_ids = @original_order_cycle.coordinator_fee_ids
|
oc.coordinator_fee_ids = @original_order_cycle.coordinator_fee_ids
|
||||||
oc.preferred_product_selection_from_coordinator_inventory_only =
|
oc.preferred_product_selection_from_coordinator_inventory_only =
|
||||||
@original_order_cycle.preferred_product_selection_from_coordinator_inventory_only
|
@original_order_cycle.preferred_product_selection_from_coordinator_inventory_only
|
||||||
|
|||||||
@@ -11,10 +11,12 @@ module OrderCycles
|
|||||||
.merge(coordinator_name: order_cycle.coordinator.name)
|
.merge(coordinator_name: order_cycle.coordinator.name)
|
||||||
|
|
||||||
# Endpoints for coordinator owner
|
# Endpoints for coordinator owner
|
||||||
webhook_endpoints = order_cycle.coordinator.owner.webhook_endpoints
|
webhook_endpoints = order_cycle.coordinator.owner.webhook_endpoints.order_cycle_opened
|
||||||
|
|
||||||
# Plus unique endpoints for distributor owners (ignore duplicates)
|
# Plus unique endpoints for distributor owners (ignore duplicates)
|
||||||
webhook_endpoints |= order_cycle.distributors.map(&:owner).flat_map(&:webhook_endpoints)
|
webhook_endpoints |= order_cycle.distributors.map(&:owner).flat_map { |owner|
|
||||||
|
owner.webhook_endpoints.order_cycle_opened
|
||||||
|
}
|
||||||
|
|
||||||
webhook_endpoints.each do |endpoint|
|
webhook_endpoints.each do |endpoint|
|
||||||
WebhookDeliveryJob.perform_later(endpoint.url, event, webhook_payload, at:)
|
WebhookDeliveryJob.perform_later(endpoint.url, event, webhook_payload, at:)
|
||||||
|
|||||||
13
app/services/payments/status_changed_listener_service.rb
Normal file
13
app/services/payments/status_changed_listener_service.rb
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
# Called by "ActiveSupport::Notifications" when an "ofn.payment_transition" occurs
|
||||||
|
# Event originate from Spree::Payment event machine
|
||||||
|
#
|
||||||
|
module Payments
|
||||||
|
class StatusChangedListenerService
|
||||||
|
def call(_name, started, _finished, _unique_id, payload)
|
||||||
|
event = "payment.#{payload[:event]}"
|
||||||
|
Payments::WebhookService.create_webhook_job(payment: payload[:payment], event:, at: started)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
84
app/services/payments/webhook_payload.rb
Normal file
84
app/services/payments/webhook_payload.rb
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module Payments
|
||||||
|
class WebhookPayload
|
||||||
|
def initialize(payment:, order:, enterprise:)
|
||||||
|
@payment = payment
|
||||||
|
@order = order
|
||||||
|
@enterprise = enterprise
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_hash
|
||||||
|
{
|
||||||
|
payment: @payment.slice(:updated_at, :amount, :state),
|
||||||
|
enterprise: @enterprise.slice(:abn, :acn, :name)
|
||||||
|
.merge(address: @enterprise.address.slice(:address1, :address2, :city, :zipcode)),
|
||||||
|
order: @order.slice(:total, :currency).merge(line_items: line_items)
|
||||||
|
}.with_indifferent_access
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.test_data
|
||||||
|
new(payment: test_payment, order: test_order, enterprise: test_enterprise)
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.test_payment
|
||||||
|
{
|
||||||
|
updated_at: Time.zone.now,
|
||||||
|
amount: 0.00,
|
||||||
|
state: "completed"
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.test_order
|
||||||
|
order = Spree::Order.new(
|
||||||
|
total: 0.00,
|
||||||
|
currency: "AUD",
|
||||||
|
)
|
||||||
|
|
||||||
|
tax_category = Spree::TaxCategory.new(name: "VAT")
|
||||||
|
product = Spree::Product.new(name: "Test product")
|
||||||
|
Spree::Variant.new(product:, display_name: "")
|
||||||
|
order.line_items << Spree::LineItem.new(
|
||||||
|
quantity: 1,
|
||||||
|
price: 20.00,
|
||||||
|
tax_category:,
|
||||||
|
product:,
|
||||||
|
unit_presentation: "1kg"
|
||||||
|
)
|
||||||
|
|
||||||
|
order
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.test_enterprise
|
||||||
|
enterprise = Enterprise.new(
|
||||||
|
abn: "65797115831",
|
||||||
|
acn: "",
|
||||||
|
name: "TEST Enterprise",
|
||||||
|
)
|
||||||
|
enterprise.address = Spree::Address.new(
|
||||||
|
address1: "1 testing street",
|
||||||
|
address2: "",
|
||||||
|
city: "TestCity",
|
||||||
|
zipcode: "1234"
|
||||||
|
)
|
||||||
|
|
||||||
|
enterprise
|
||||||
|
end
|
||||||
|
|
||||||
|
private_class_method :test_payment, :test_order, :test_enterprise
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def line_items
|
||||||
|
@order.line_items.map do |li|
|
||||||
|
li.slice(:quantity, :price)
|
||||||
|
.merge(
|
||||||
|
tax_category_name: li.tax_category&.name,
|
||||||
|
product_name: li.product.name,
|
||||||
|
name_to_display: li.display_name,
|
||||||
|
unit_to_display: li.unit_presentation
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
30
app/services/payments/webhook_service.rb
Normal file
30
app/services/payments/webhook_service.rb
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
# Create a webhook payload for a payment status event.
|
||||||
|
# The payload will be delivered asynchronously.
|
||||||
|
|
||||||
|
module Payments
|
||||||
|
class WebhookService
|
||||||
|
def self.create_webhook_job(payment:, event:, at:)
|
||||||
|
order = payment.order
|
||||||
|
payload = WebhookPayload.new(payment:, order:, enterprise: order.distributor).to_hash
|
||||||
|
|
||||||
|
coordinator = payment.order.order_cycle.coordinator
|
||||||
|
webhook_urls(coordinator).each do |url|
|
||||||
|
WebhookDeliveryJob.perform_later(url, event, payload, at:)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.webhook_urls(coordinator)
|
||||||
|
# url for coordinator owner
|
||||||
|
webhook_urls = coordinator.owner.webhook_endpoints.payment_status.pluck(:url)
|
||||||
|
|
||||||
|
# plus url for coordinator manager (ignore duplicate)
|
||||||
|
users_webhook_urls = coordinator.users.flat_map do |user|
|
||||||
|
user.webhook_endpoints.payment_status.pluck(:url)
|
||||||
|
end
|
||||||
|
|
||||||
|
webhook_urls | users_webhook_urls
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -11,7 +11,7 @@ module PermittedAttributes
|
|||||||
[:name, :description, :type, :active,
|
[:name, :description, :type, :active,
|
||||||
:environment, :display_on, :tag_list,
|
:environment, :display_on, :tag_list,
|
||||||
:preferred_enterprise_id, :preferred_server, :preferred_login, :preferred_password,
|
:preferred_enterprise_id, :preferred_server, :preferred_login, :preferred_password,
|
||||||
:calculator_type, :preferred_api_key,
|
:calculator_type, :preferred_api_key, :preferred_backend_url,
|
||||||
:preferred_signature, :preferred_solution, :preferred_landing_page, :preferred_logourl,
|
:preferred_signature, :preferred_solution, :preferred_landing_page, :preferred_logourl,
|
||||||
:preferred_test_mode, :calculator_type, { distributor_ids: [] },
|
:preferred_test_mode, :calculator_type, { distributor_ids: [] },
|
||||||
{ calculator_attributes: PermittedAttributes::Calculator.attributes }]
|
{ calculator_attributes: PermittedAttributes::Calculator.attributes }]
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ class ProductsRenderer
|
|||||||
|
|
||||||
paginated_products = paginate(results)
|
paginated_products = paginate(results)
|
||||||
|
|
||||||
if options[:inventory_enabled]
|
if inventory_enabled?
|
||||||
# Scope results with variant_overrides
|
# Scope results with variant_overrides
|
||||||
paginated_products.each { |product| product_scoper.scope(product) }
|
paginated_products.each { |product| product_scoper.scope(product) }
|
||||||
end
|
end
|
||||||
@@ -123,7 +123,7 @@ class ProductsRenderer
|
|||||||
includes(:default_price, :product).
|
includes(:default_price, :product).
|
||||||
where(product_id: products)
|
where(product_id: products)
|
||||||
|
|
||||||
if options[:inventory_enabled]
|
if inventory_enabled?
|
||||||
# Scope results with variant_overrides
|
# Scope results with variant_overrides
|
||||||
scoper = OpenFoodNetwork::ScopeVariantToHub.new(distributor)
|
scoper = OpenFoodNetwork::ScopeVariantToHub.new(distributor)
|
||||||
variants = variants.each { |v| scoper.scope(v) }
|
variants = variants.each { |v| scoper.scope(v) }
|
||||||
@@ -143,4 +143,8 @@ class ProductsRenderer
|
|||||||
vs[v.product_id] << v
|
vs[v.product_id] << v
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def inventory_enabled?
|
||||||
|
options[:inventory_enabled] && !options[:variant_tag_enabled]
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -2,6 +2,11 @@
|
|||||||
|
|
||||||
module Vine
|
module Vine
|
||||||
class VoucherValidatorService
|
class VoucherValidatorService
|
||||||
|
VINE_ERRORS = {
|
||||||
|
# https://github.com/openfoodfoundation/vine/blob/main/app/Enums/ApiResponse.php
|
||||||
|
"This voucher has expired." => :expired,
|
||||||
|
}.freeze
|
||||||
|
|
||||||
attr_reader :voucher_code, :errors
|
attr_reader :voucher_code, :errors
|
||||||
|
|
||||||
def initialize(voucher_code:, enterprise:)
|
def initialize(voucher_code:, enterprise:)
|
||||||
@@ -42,8 +47,10 @@ module Vine
|
|||||||
end
|
end
|
||||||
|
|
||||||
def handle_errors(response)
|
def handle_errors(response)
|
||||||
if response[:status] == 400
|
if [400, 409].include?(response[:status])
|
||||||
errors[:invalid_voucher] = I18n.t("vine_voucher_validator_service.errors.invalid_voucher")
|
message = response[:body] && JSON.parse(response[:body]).dig("meta", "message")
|
||||||
|
key = VINE_ERRORS.fetch(message, :invalid_voucher)
|
||||||
|
errors[:invalid_voucher] = I18n.t("vine_voucher_validator_service.errors.#{key}")
|
||||||
elsif response[:status] == 404
|
elsif response[:status] == 404
|
||||||
errors[:not_found_voucher] =
|
errors[:not_found_voucher] =
|
||||||
I18n.t("vine_voucher_validator_service.errors.not_found_voucher")
|
I18n.t("vine_voucher_validator_service.errors.not_found_voucher")
|
||||||
|
|||||||
@@ -44,8 +44,8 @@
|
|||||||
%h1#no_results{ 'ng-show' => '!RequestMonitor.loading && filteredCustomers.length == 0' }
|
%h1#no_results{ 'ng-show' => '!RequestMonitor.loading && filteredCustomers.length == 0' }
|
||||||
=t :no_customers_found
|
=t :no_customers_found
|
||||||
|
|
||||||
%save-bar{ dirty: "customers_form.$dirty", persist: "false" }
|
%save-bar{ persist: "filteredCustomers.length > 0" }
|
||||||
%input.red{ type: "button", value: t(:save_changes), "ng-click": "submitAll(customers_form)" }
|
%input.red{ type: "button", value: t(:save_changes), "ng-click": "submitAll(customers_form)", "ng-disabled": "!hasUnsavedChanges()" }
|
||||||
|
|
||||||
%table.index#customers{ 'ng-show' => '!RequestMonitor.loading && filteredCustomers.length > 0' }
|
%table.index#customers{ 'ng-show' => '!RequestMonitor.loading && filteredCustomers.length > 0' }
|
||||||
%col.email{ width: "20%", 'ng-show' => 'columns.email.visible' }
|
%col.email{ width: "20%", 'ng-show' => 'columns.email.visible' }
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
= form_with url: main_app.import_admin_dfc_product_imports_path, html: { "data-controller": "checked" } do |form|
|
= form_with url: main_app.import_admin_dfc_product_imports_path, html: { "data-controller": "checked" } do |form|
|
||||||
-# This is a very inefficient way of holding a json blob. Maybe base64 encode or store as a temporary file
|
-# This is a very inefficient way of holding a json blob. Maybe base64 encode or store as a temporary file
|
||||||
= form.hidden_field :enterprise_id, value: @enterprise.id
|
= form.hidden_field :enterprise_id, value: @enterprise.id
|
||||||
= form.hidden_field :catalog_json, value: @catalog_json
|
= form.hidden_field :catalog_json, value: @catalog_data.to_json
|
||||||
|
|
||||||
%table
|
%table
|
||||||
%thead
|
%thead
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
%tbody
|
%tbody
|
||||||
= f.fields_for :collection do |enterprise_form|
|
= f.fields_for :collection do |enterprise_form|
|
||||||
- enterprise = enterprise_form.object
|
- enterprise = enterprise_form.object
|
||||||
%tr{class: "enterprise-#{enterprise.id}"}
|
%tr{class: "enterprise-#{enterprise.id}", id: "resource-#{enterprise.id}"}
|
||||||
%td= link_to enterprise.name, main_app.edit_admin_enterprise_path(enterprise)
|
%td= link_to enterprise.name, main_app.edit_admin_enterprise_path(enterprise)
|
||||||
%td
|
%td
|
||||||
= enterprise_form.check_box :is_primary_producer
|
= enterprise_form.check_box :is_primary_producer
|
||||||
|
|||||||
4
app/views/admin/enterprises/destroy.turbo_stream.haml
Normal file
4
app/views/admin/enterprises/destroy.turbo_stream.haml
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
- unless flash[:error]
|
||||||
|
= turbo_stream.remove "resource-#{@object.id}"
|
||||||
|
= turbo_stream.append "flashes" do
|
||||||
|
= render(partial: 'admin/shared/flashes', locals: { flashes: flash })
|
||||||
@@ -20,7 +20,6 @@
|
|||||||
:plain
|
:plain
|
||||||
<solid-permissioning
|
<solid-permissioning
|
||||||
data-src="#{DfcProvider::Engine.routes.url_helpers.enterprise_platforms_url(@enterprise.id)}"
|
data-src="#{DfcProvider::Engine.routes.url_helpers.enterprise_platforms_url(@enterprise.id)}"
|
||||||
scopes-uri="https://cdn.startinblox.com/owl/dfc/taxonomies/scopes.jsonld"
|
|
||||||
noRouter
|
noRouter
|
||||||
auto-lang
|
auto-lang
|
||||||
lang="en"
|
lang="en"
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
%h3= t('.title')
|
%h3= t('.title')
|
||||||
|
|
||||||
= form_for [main_app, :admin, @order_cycle] do |f|
|
= form_for [main_app, :admin, @order_cycle] do |f|
|
||||||
- if feature?(:inventory, @order_cycle.coordinator)
|
- if inventory_enabled?(@order_cycle.coordinator)
|
||||||
.row
|
.row
|
||||||
.three.columns.alpha
|
.three.columns.alpha
|
||||||
= f.label "enterprise_preferred_product_selection_from_coordinator_inventory_only", t('admin.order_cycles.edit.choose_products_from')
|
= f.label "enterprise_preferred_product_selection_from_coordinator_inventory_only", t('admin.order_cycles.edit.choose_products_from')
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
%span{ "ofn-with-tip": '{{ orderCycle.producerNames }}', "ng-show": 'orderCycle.producers.length > 3' }
|
%span{ "ofn-with-tip": '{{ orderCycle.producerNames }}', "ng-show": 'orderCycle.producers.length > 3' }
|
||||||
{{ orderCycle.producers.length }}
|
{{ orderCycle.producers.length }}
|
||||||
= t('.suppliers')
|
= t('.suppliers')
|
||||||
%span{ "ng-hide": 'orderCycle.producers.length > 3', "ng-bind": 'orderCycle.producerNames' }
|
%span{ "ng-hide": 'orderCycle.producers.length > 3', "ng-bind-html": 'orderCycle.producerNames' }
|
||||||
%td.coordinator{ "ng-show": 'columns.coordinator.visible', "ng-bind-html": 'orderCycle.coordinator.name' }
|
%td.coordinator{ "ng-show": 'columns.coordinator.visible', "ng-bind-html": 'orderCycle.coordinator.name' }
|
||||||
%td.shops{ "ng-show": 'columns.shops.visible' }
|
%td.shops{ "ng-show": 'columns.shops.visible' }
|
||||||
%span{ "ofn-with-tip": '{{ orderCycle.shopNames }}', "ng-show": 'orderCycle.shops.length > 3' }
|
%span{ "ofn-with-tip": '{{ orderCycle.shopNames }}', "ng-show": 'orderCycle.shops.length > 3' }
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
-# locals: (products:, pagy:, search_term:, producer_options:, producer_id:, category_options:, category_id:, tax_category_options:, available_tags:, tags:, flashes:, display_search_filter:, allowed_producers:)
|
||||||
%turbo-frame#products-content{ target: "_top", refresh: "morph" }
|
%turbo-frame#products-content{ target: "_top", refresh: "morph" }
|
||||||
.spinner-overlay{ "data-controller": "loading", "data-products-target": "loading", class: "hidden" }
|
.spinner-overlay{ "data-controller": "loading", "data-products-target": "loading", class: "hidden" }
|
||||||
.spinner-container
|
.spinner-container
|
||||||
@@ -17,7 +18,7 @@
|
|||||||
.container.results
|
.container.results
|
||||||
.sixteen.columns
|
.sixteen.columns
|
||||||
= render partial: 'sort', locals: { pagy:, search_term:, producer_id:, category_id:, tags: }
|
= render partial: 'sort', locals: { pagy:, search_term:, producer_id:, category_id:, tags: }
|
||||||
= render partial: 'table', locals: { products:, producer_options:, category_options:, tax_category_options: }
|
= render partial: 'table', locals: { products:, producer_options:, category_options:, tax_category_options: , allowed_producers: }
|
||||||
- if pagy.present? && pagy.pages > 1
|
- if pagy.present? && pagy.pages > 1
|
||||||
= render partial: 'admin/shared/stimulus_pagination', locals: { pagy: pagy }
|
= render partial: 'admin/shared/stimulus_pagination', locals: { pagy: pagy }
|
||||||
- else
|
- else
|
||||||
|
|||||||
@@ -17,13 +17,13 @@
|
|||||||
= select_tag :category_id, options_for_select(category_options, category_id),
|
= select_tag :category_id, options_for_select(category_options, category_id),
|
||||||
include_blank: t('.all_categories'), class: "fullwidth",
|
include_blank: t('.all_categories'), class: "fullwidth",
|
||||||
data: { "controller": "tom-select", 'tom-select-placeholder-value': t('.search_for_categories')}
|
data: { "controller": "tom-select", 'tom-select-placeholder-value': t('.search_for_categories')}
|
||||||
-if feature?(:variant_tag, spree_current_user)
|
-if variant_tag_enabled?(spree_current_user)
|
||||||
.tags
|
.tags
|
||||||
= label_tag :tags_name_in, t('.tags.label')
|
= label_tag :tags_name_in, t('.tags.label')
|
||||||
- select_tag_options = { class: "fullwidth",
|
- select_tag_options = { class: "fullwidth",
|
||||||
multiple: true ,
|
multiple: true ,
|
||||||
data: { controller: "tom-select", "tom-select-placeholder-value": t(".select_tag"), "tom-select-options-value": '{ "maxItems": 5 , "plugins": { "remove_button": {} , "no_active_items": {}, "checkbox_options": { "checkedClassNames": ["ts-checked"], "uncheckedClassNames": ["ts-unchecked"] } } }' } }
|
data: { controller: "tom-select", "tom-select-placeholder-value": t(".select_tag"), "tom-select-options-value": '{ "maxItems": 5 , "plugins": { "remove_button": {} , "no_active_items": {}, "checkbox_options": { "checkedClassNames": ["ts-checked"], "uncheckedClassNames": ["ts-unchecked"] } } }' } }
|
||||||
= select_tag :tags_name_in, options_for_select(available_tags, tags), select_tag_options
|
= select_tag :tags_name_in, options_for_select(available_tags.unshift([t('.tags.none'), @none_tag_value]), tags), select_tag_options
|
||||||
.submit
|
.submit
|
||||||
.search-button
|
.search-button
|
||||||
= button_tag t(".search"), class: "secondary icon-search relaxed", name: nil
|
= button_tag t(".search"), class: "secondary icon-search relaxed", name: nil
|
||||||
|
|||||||
@@ -7,5 +7,6 @@
|
|||||||
#no-products-actions
|
#no-products-actions
|
||||||
%a{ href: "/admin/products/new", class: "button icon-plus", icon: "icon-plus" }
|
%a{ href: "/admin/products/new", class: "button icon-plus", icon: "icon-plus" }
|
||||||
= t(:new_product)
|
= t(:new_product)
|
||||||
%a{ href: "/admin/products/import", class: "button icon-upload secondary", icon: "icon-upload" }
|
%a{ href: admin_product_import_path, class: "button icon-upload secondary", icon: "icon-upload" }
|
||||||
= t(".import_products")
|
= t(".import_products")
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
%td.col-category.align-left
|
%td.col-category.align-left
|
||||||
-# empty
|
-# empty
|
||||||
%td.col-tax_category.align-left
|
%td.col-tax_category.align-left
|
||||||
- if feature?(:variant_tag, spree_current_user)
|
- if variant_tag_enabled?(spree_current_user)
|
||||||
%td.col-tags.align-left
|
%td.col-tags.align-left
|
||||||
-# empty
|
-# empty
|
||||||
%td.col-inherits_properties.align-left
|
%td.col-inherits_properties.align-left
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
-# locals: (form:, product:, product_index:, producer_options:, category_options:, tax_category_options:, allowed_producers:, should_slide_in: false)
|
||||||
= form.fields_for("products", product, index: product_index) do |product_form|
|
= form.fields_for("products", product, index: product_index) do |product_form|
|
||||||
%tbody.relaxed{ id: dom_id(product), data: { 'record-id': product_form.object.id,
|
%tbody.relaxed{ id: dom_id(product), data: { 'record-id': product_form.object.id,
|
||||||
controller: "nested-form product",
|
controller: "nested-form product",
|
||||||
@@ -7,6 +8,9 @@
|
|||||||
= render partial: 'product_row', locals: { f: product_form, product:, product_index: }
|
= render partial: 'product_row', locals: { f: product_form, product:, product_index: }
|
||||||
|
|
||||||
- product.variants.each_with_index do |variant, variant_index|
|
- product.variants.each_with_index do |variant, variant_index|
|
||||||
|
|
||||||
|
-# Filter out variant a user has not permission to update, but keep variant with no supplier
|
||||||
|
- next if variant.supplier.present? && !allowed_producers.include?(variant.supplier)
|
||||||
= form.fields_for("products][#{product_index}][variants_attributes", variant, index: variant_index) do |variant_form|
|
= form.fields_for("products][#{product_index}][variants_attributes", variant, index: variant_index) do |variant_form|
|
||||||
%tr.condensed{ id: dom_id(variant), 'data-controller': "variant", 'class': "nested-form-wrapper", 'data-new-record': variant.new_record? ? "true" : false }
|
%tr.condensed{ id: dom_id(variant), 'data-controller': "variant", 'class': "nested-form-wrapper", 'data-new-record': variant.new_record? ? "true" : false }
|
||||||
= render partial: 'variant_row', locals: { variant:, f: variant_form, category_options:, tax_category_options:, producer_options: }
|
= render partial: 'variant_row', locals: { variant:, f: variant_form, category_options:, tax_category_options:, producer_options: }
|
||||||
@@ -19,7 +23,7 @@
|
|||||||
%tr{ 'data-nested-form-target': "target" }
|
%tr{ 'data-nested-form-target': "target" }
|
||||||
%tr.condensed
|
%tr.condensed
|
||||||
%td
|
%td
|
||||||
- colspan = feature?(:variant_tag, spree_current_user) ? 12 : 11
|
- colspan = variant_tag_enabled?(spree_current_user) ? 12 : 11
|
||||||
%td{ colspan: "#{colspan}" }
|
%td{ colspan: "#{colspan}" }
|
||||||
%button.secondary.condensed.naked.icon-plus{ 'data-action': "nested-form#add",
|
%button.secondary.condensed.naked.icon-plus{ 'data-action': "nested-form#add",
|
||||||
'aria-label': t('.new_variant') }
|
'aria-label': t('.new_variant') }
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
-# locals: (products:, producer_options:, category_options:, tax_category_options:, allowed_producers:)
|
||||||
= form_with url: admin_products_bulk_update_path, method: :post, id: "products-form",
|
= form_with url: admin_products_bulk_update_path, method: :post, id: "products-form",
|
||||||
builder: BulkFormBuilder,
|
builder: BulkFormBuilder,
|
||||||
html: { data: { 'turbo-frame': "_self",
|
html: { data: { 'turbo-frame': "_self",
|
||||||
@@ -26,13 +27,13 @@
|
|||||||
%col.col-producer{ style:"min-width: 6em" }= # (grow to fill)
|
%col.col-producer{ style:"min-width: 6em" }= # (grow to fill)
|
||||||
%col.col-category{ width:"8%" }
|
%col.col-category{ width:"8%" }
|
||||||
%col.col-tax_category{ width:"8%" }
|
%col.col-tax_category{ width:"8%" }
|
||||||
- if feature?(:variant_tag, spree_current_user)
|
- if variant_tag_enabled?(spree_current_user)
|
||||||
%col.col-tags{ width:"8%" }
|
%col.col-tags{ width:"8%" }
|
||||||
%col.col-inherits_properties{ width:"5%" }
|
%col.col-inherits_properties{ width:"5%" }
|
||||||
%col{ width:"5%", style:"min-width: 3em"}= # Actions
|
%col{ width:"5%", style:"min-width: 3em"}= # Actions
|
||||||
%thead
|
%thead
|
||||||
%tr
|
%tr
|
||||||
- colspan = feature?(:variant_tag, spree_current_user) ? 13 : 12
|
- colspan = variant_tag_enabled?(spree_current_user) ? 13 : 12
|
||||||
%td.form-actions-wrapper{ colspan: "#{colspan}" }
|
%td.form-actions-wrapper{ colspan: "#{colspan}" }
|
||||||
.form-actions-wrapper2
|
.form-actions-wrapper2
|
||||||
%fieldset.form-actions{ class: ("hidden" unless defined?(@error_counts)), 'data-bulk-form-target': "actions" }
|
%fieldset.form-actions{ class: ("hidden" unless defined?(@error_counts)), 'data-bulk-form-target': "actions" }
|
||||||
@@ -64,9 +65,9 @@
|
|||||||
%th.align-left.col-producer= t('admin.products_page.columns.producer')
|
%th.align-left.col-producer= t('admin.products_page.columns.producer')
|
||||||
%th.align-left.col-category= t('admin.products_page.columns.category')
|
%th.align-left.col-category= t('admin.products_page.columns.category')
|
||||||
%th.align-left.col-tax_category= t('admin.products_page.columns.tax_category')
|
%th.align-left.col-tax_category= t('admin.products_page.columns.tax_category')
|
||||||
- if feature?(:variant_tag, spree_current_user)
|
- if variant_tag_enabled?(spree_current_user)
|
||||||
%th.align-left.col-tags= t('admin.products_page.columns.tags')
|
%th.align-left.col-tags= t('admin.products_page.columns.tags')
|
||||||
%th.align-left.col-inherits_properties= t('admin.products_page.columns.inherits_properties')
|
%th.align-left.col-inherits_properties= t('admin.products_page.columns.inherits_properties')
|
||||||
%th.align-right= t('admin.products_page.columns.actions')
|
%th.align-right= t('admin.products_page.columns.actions')
|
||||||
- products.each_with_index do |product, product_index|
|
- products.each_with_index do |product, product_index|
|
||||||
= render partial: 'product_variant_row', locals: { form:, product:, product_index:, producer_options:, category_options:, tax_category_options: }
|
= render partial: 'product_variant_row', locals: { form:, product:, product_index:, producer_options:, category_options:, tax_category_options: , allowed_producers:}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
-# locals: (variant:, f:, category_options:, tax_category_options:, producer_options:)
|
||||||
- method_on_demand, method_on_hand = variant.new_record? ? [:on_demand_desired, :on_hand_desired ]: [:on_demand, :on_hand]
|
- method_on_demand, method_on_hand = variant.new_record? ? [:on_demand_desired, :on_hand_desired ]: [:on_demand, :on_hand]
|
||||||
%td.col-image
|
%td.col-image
|
||||||
-# empty
|
-# empty
|
||||||
@@ -8,7 +9,7 @@
|
|||||||
%td.col-sku.field.naked_inputs
|
%td.col-sku.field.naked_inputs
|
||||||
= f.text_field :sku, 'aria-label': t('admin.products_page.columns.sku')
|
= f.text_field :sku, 'aria-label': t('admin.products_page.columns.sku')
|
||||||
= error_message_on variant, :sku
|
= error_message_on variant, :sku
|
||||||
%td.col-unir_scale.field.naked_inputs{ 'data-controller': 'toggle-control', 'data-toggle-control-match-value': 'items' }
|
%td.col-unit_scale.field.naked_inputs{ 'data-controller': 'toggle-control', 'data-toggle-control-match-value': 'items' }
|
||||||
= f.hidden_field :variant_unit
|
= f.hidden_field :variant_unit
|
||||||
= f.hidden_field :variant_unit_scale
|
= f.hidden_field :variant_unit_scale
|
||||||
= f.select :variant_unit_with_scale,
|
= f.select :variant_unit_with_scale,
|
||||||
@@ -78,9 +79,9 @@
|
|||||||
aria_label: t('.tax_category_field_name'),
|
aria_label: t('.tax_category_field_name'),
|
||||||
placeholder_value: t('.search_for_tax_categories')))
|
placeholder_value: t('.search_for_tax_categories')))
|
||||||
= error_message_on variant, :tax_category
|
= error_message_on variant, :tax_category
|
||||||
- if feature?(:variant_tag, spree_current_user)
|
- if variant_tag_enabled?(spree_current_user)
|
||||||
%td.col-tags.field.naked_inputs
|
%td.col-tags.field.naked_inputs
|
||||||
= render TagListInputComponent.new(name: f.field_name(:tag_list), tags: variant.tag_list, autocomplete_url: variant_tag_rules_admin_tag_rules_path(enterprise_id: variant.supplier_id), placeholder: t('.add_a_tag'), aria_label: t('admin.products_page.columns.tags'))
|
= render TagListInputComponent.new(name: f.field_name(:tag_list), tags: variant.tag_list, autocomplete_url: variant_tag_rules_admin_tag_rules_path(enterprise_id: variant.supplier_id), placeholder: t('.add_a_tag'), aria_label: t('admin.products_page.columns.tags')) if feature?(:variant_tag, variant.supplier)
|
||||||
%td.col-inherits_properties.align-left
|
%td.col-inherits_properties.align-left
|
||||||
-# empty
|
-# empty
|
||||||
%td.align-right
|
%td.align-right
|
||||||
|
|||||||
@@ -1,16 +1,18 @@
|
|||||||
|
-# locals: (product:, cloned_product:, product_index:, producer_options:, category_options: category, tax_category_options:, allowed_producers:)
|
||||||
- unless flash[:error]
|
- unless flash[:error]
|
||||||
- product_body = nil
|
- product_body = nil
|
||||||
- form_with do |form|
|
- form_with do |form|
|
||||||
- product_body = render(partial: 'product_variant_row',
|
- product_body = render(partial: 'product_variant_row',
|
||||||
locals: { form:,
|
locals: { form:,
|
||||||
product: @cloned_product,
|
product: cloned_product,
|
||||||
product_index: @product_index,
|
product_index:,
|
||||||
producer_options: @producer_options,
|
producer_options:,
|
||||||
category_options: @category_options,
|
category_options:,
|
||||||
tax_category_options: @tax_category_options,
|
tax_category_options:,
|
||||||
|
allowed_producers:,
|
||||||
should_slide_in: true },
|
should_slide_in: true },
|
||||||
formats: :html)
|
formats: :html)
|
||||||
= turbo_stream.after dom_id(@product) do
|
= turbo_stream.after dom_id(product) do
|
||||||
= product_body
|
= product_body
|
||||||
|
|
||||||
= turbo_stream.append "flashes" do
|
= turbo_stream.append "flashes" do
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
-# locals: (producer_options:, categories:, tax_category_options:, available_tags:, flash:, allowed_producers:)
|
||||||
- content_for :page_title do
|
- content_for :page_title do
|
||||||
= t('.header.title')
|
= t('.header.title')
|
||||||
- content_for :page_actions do
|
- content_for :page_actions do
|
||||||
@@ -13,11 +14,13 @@
|
|||||||
|
|
||||||
#products_v3_page{ 'data-turbo': true }
|
#products_v3_page{ 'data-turbo': true }
|
||||||
= render partial: "content", locals: { products: @products, pagy: @pagy, search_term: @search_term,
|
= render partial: "content", locals: { products: @products, pagy: @pagy, search_term: @search_term,
|
||||||
producer_options: producers, producer_id: @producer_id,
|
producer_options:, producer_id: @producer_id,
|
||||||
category_options: categories, category_id: @category_id,
|
category_options: categories, category_id: @category_id,
|
||||||
tax_category_options:, available_tags:, tags: @tags,
|
tax_category_options:, available_tags:, tags: @tags,
|
||||||
flashes: flash,
|
flashes: flash,
|
||||||
display_search_filter: (@products.any? || @search_term.present? || @category_id.present?) }
|
display_search_filter: (@products.any? || @search_term.present? || @category_id.present?),
|
||||||
|
allowed_producers:}
|
||||||
|
|
||||||
- %w[product variant].each do |object_type|
|
- %w[product variant].each do |object_type|
|
||||||
= render partial: 'delete_modal', locals: { object_type: }
|
= render partial: 'delete_modal', locals: { object_type: }
|
||||||
#modal-component
|
#modal-component
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
.alert-box{ class: "#{type}" }
|
.alert-box{ class: "#{type}" }
|
||||||
= message
|
= message
|
||||||
- if local_assigns[:unconfirmed]
|
- if local_assigns[:unconfirmed]
|
||||||
%a{ "data-action": "login-modal#resend_confirmation", "data-tab": local_assigns[:tab] }
|
= link_to spree_user_confirmation_path(spree_user: { email: }, tab: local_assigns[:tab]), data: { turbo_method: :post } do
|
||||||
= t('devise.confirmations.resend_confirmation_email')
|
= t('devise.confirmations.resend_confirmation_email')
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
#forgot-tab
|
#forgot-tab
|
||||||
= form_with url: spree_user_password_path, scope: :spree_user, data: { remote: "true" } do |form|
|
= form_with url: spree_user_password_path, scope: :spree_user, data: { turbo: true } do |form|
|
||||||
.row
|
.row
|
||||||
.large-12.columns#forgot-feedback
|
.large-12.columns#forgot-feedback
|
||||||
|
|
||||||
.row
|
.row
|
||||||
.large-12.columns
|
.large-12.columns
|
||||||
= form.label :email, t(:signup_email)
|
= form.label :email, t(:signup_email)
|
||||||
= form.email_field :email, { tabindex: 1, inputmode: "email", "data-login-modal-target": "email", "data-action": "input->login-modal#emailOnInput" }
|
= form.email_field :email, { tabindex: 1, inputmode: "email" }
|
||||||
.row
|
.row
|
||||||
.large-12.columns
|
.large-12.columns
|
||||||
= form.submit t(:reset_password), { class: "button primary", tabindex: 2 }
|
= form.submit t(:reset_password), { class: "button primary", tabindex: 2 }
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#login-content
|
#login-content
|
||||||
= form_with url: spree_user_session_path, scope: :spree_user, data: { remote: "true" } do |form|
|
= form_with url: spree_user_session_path, scope: :spree_user, data: { turbo: true } do |form|
|
||||||
.row
|
.row
|
||||||
.large-12.columns#login-feedback
|
.large-12.columns#login-feedback
|
||||||
- confirmation_result = request.query_parameters[:validation]
|
- confirmation_result = request.query_parameters[:validation]
|
||||||
@@ -10,7 +10,7 @@
|
|||||||
.row
|
.row
|
||||||
.large-12.columns
|
.large-12.columns
|
||||||
= form.label :email, t(:email)
|
= form.label :email, t(:email)
|
||||||
= form.email_field :email, { tabindex: 1, inputmode: "email", autocomplete: "off", "data-login-modal-target": "email", "data-action": "input->login-modal#emailOnInput" }
|
= form.email_field :email, { tabindex: 1, inputmode: "email", autocomplete: "off" }
|
||||||
.row
|
.row
|
||||||
.large-12.columns
|
.large-12.columns
|
||||||
= form.label :password, t(:password)
|
= form.label :password, t(:password)
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user