mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-01-18 19:36:48 +00:00
Compare commits
154 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dfabc5fa06 | ||
|
|
7a5a4f956a | ||
|
|
720edb4b05 | ||
|
|
3ec1af104f | ||
|
|
80d034706c | ||
|
|
902f8caea9 | ||
|
|
14091cd106 | ||
|
|
936f5c1a0c | ||
|
|
8963a787d6 | ||
|
|
59cab902f0 | ||
|
|
4d2c93930b | ||
|
|
fb769d37f9 | ||
|
|
65f6f1febf | ||
|
|
99b5d9e0c5 | ||
|
|
c4cd574242 | ||
|
|
a3a6205343 | ||
|
|
25c363feba | ||
|
|
839278fc75 | ||
|
|
1cab9e473b | ||
|
|
93a73b4823 | ||
|
|
7408c45980 | ||
|
|
fe4b20dd7b | ||
|
|
3c71b7f6be | ||
|
|
259e139c47 | ||
|
|
8c1e222788 | ||
|
|
4ca930bdad | ||
|
|
f0a052b65b | ||
|
|
07a72eccd4 | ||
|
|
b04a76e8bf | ||
|
|
1ceb6ac916 | ||
|
|
049f66c2aa | ||
|
|
9c41c296e4 | ||
|
|
d299c8cf01 | ||
|
|
2b2f1ac0cd | ||
|
|
d2998f1190 | ||
|
|
c6c20dc0f6 | ||
|
|
60aaf8100a | ||
|
|
98f42a1f81 | ||
|
|
f589d278cf | ||
|
|
2b884be8dd | ||
|
|
64153c5072 | ||
|
|
9de3370a8a | ||
|
|
63fb46f440 | ||
|
|
aa718824d8 | ||
|
|
4394d2fe43 | ||
|
|
ea5c7c5990 | ||
|
|
2905267142 | ||
|
|
71c6cee94c | ||
|
|
7ef0056225 | ||
|
|
b512d3ce21 | ||
|
|
98c99de835 | ||
|
|
1aa2b7274b | ||
|
|
ae33df946e | ||
|
|
54ad90e071 | ||
|
|
e1c1574931 | ||
|
|
8f8973b6f9 | ||
|
|
3c74541145 | ||
|
|
1ab62fddcb | ||
|
|
1e8d400534 | ||
|
|
1a4e292178 | ||
|
|
49081e171e | ||
|
|
a5472d6b64 | ||
|
|
62b80043ba | ||
|
|
eb040de422 | ||
|
|
b36b0eddee | ||
|
|
aaf7a90f8b | ||
|
|
9e334a4c1e | ||
|
|
56f2d38714 | ||
|
|
6b3da4ac89 | ||
|
|
31415d00e6 | ||
|
|
e155b00ab9 | ||
|
|
3c0172c507 | ||
|
|
3cba9a16aa | ||
|
|
58350ed338 | ||
|
|
54a4952dc5 | ||
|
|
34bfd877cc | ||
|
|
16cc0afe8f | ||
|
|
ccaff08928 | ||
|
|
91908a0e4c | ||
|
|
6b45208cf1 | ||
|
|
fb333c37e7 | ||
|
|
3090cfa909 | ||
|
|
9205c85d4d | ||
|
|
ff9f6c3317 | ||
|
|
25dd47e511 | ||
|
|
ece3e7aa69 | ||
|
|
ff8d935699 | ||
|
|
1d32ecab98 | ||
|
|
ff17ced101 | ||
|
|
fa6cf0f281 | ||
|
|
7e39d78733 | ||
|
|
0152b4da55 | ||
|
|
2a03e42f2a | ||
|
|
01a726d9bd | ||
|
|
93fe8dbc5f | ||
|
|
5c5a6361bf | ||
|
|
0f2cbe8a52 | ||
|
|
f1002b953d | ||
|
|
3ebc8145df | ||
|
|
edc1773676 | ||
|
|
6814eb663f | ||
|
|
78cfcd905f | ||
|
|
9bbef16804 | ||
|
|
974240fd4b | ||
|
|
7472b7cc27 | ||
|
|
a8a933d73a | ||
|
|
bcd07e1791 | ||
|
|
ecb29ec830 | ||
|
|
202aa3e5b7 | ||
|
|
a05f43000a | ||
|
|
61708e5deb | ||
|
|
27586d072d | ||
|
|
3bfa903912 | ||
|
|
0ba670b180 | ||
|
|
c4cfc1dc05 | ||
|
|
17957ed6c0 | ||
|
|
8b6a08457a | ||
|
|
9e2a3d6973 | ||
|
|
55b21310e4 | ||
|
|
1266a37ac5 | ||
|
|
54feb2f57d | ||
|
|
e9eb90507e | ||
|
|
ee44159c83 | ||
|
|
8861f5c6aa | ||
|
|
b089404891 | ||
|
|
2fa2a30c67 | ||
|
|
cabec7e73f | ||
|
|
87df44764f | ||
|
|
8f25568530 | ||
|
|
b1b422b90e | ||
|
|
85d99f3bf2 | ||
|
|
c6b3a615f1 | ||
|
|
242c1a2715 | ||
|
|
21d67a0723 | ||
|
|
59b3bfa161 | ||
|
|
41a5787830 | ||
|
|
010c1c799d | ||
|
|
2faea65f82 | ||
|
|
dd8f139c1b | ||
|
|
6d0d4b5096 | ||
|
|
b85f8d4b45 | ||
|
|
66799bad46 | ||
|
|
f9869d4360 | ||
|
|
1cad631bdb | ||
|
|
03d49c7987 | ||
|
|
c07215552e | ||
|
|
2b01c80c54 | ||
|
|
fa77204e14 | ||
|
|
af713385d8 | ||
|
|
c9972189d0 | ||
|
|
eb07a91acb | ||
|
|
66ba9ff73d | ||
|
|
dbd41e9d31 | ||
|
|
87327dcf57 |
44
.github/workflows/brakeman-analysis.yml
vendored
Normal file
44
.github/workflows/brakeman-analysis.yml
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
# This workflow integrates Brakeman with GitHub's Code Scanning feature
|
||||
# Brakeman is a static analysis security vulnerability scanner for Ruby on Rails applications
|
||||
|
||||
name: Brakeman Scan
|
||||
|
||||
# This section configures the trigger for the workflow. Feel free to customize depending on your convention
|
||||
on:
|
||||
push:
|
||||
branches: [ "master" ]
|
||||
pull_request:
|
||||
branches: [ "master" ]
|
||||
|
||||
jobs:
|
||||
brakeman-scan:
|
||||
name: Brakeman Scan
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
# Checkout the repository to the GitHub Actions runner
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
|
||||
# Customize the ruby version depending on your needs
|
||||
- name: Setup Ruby
|
||||
uses: actions/setup-ruby@v1
|
||||
with:
|
||||
ruby-version: '2.7'
|
||||
|
||||
- name: Setup Brakeman
|
||||
env:
|
||||
BRAKEMAN_VERSION: '4.10' # SARIF support is provided in Brakeman version 4.10+
|
||||
run: |
|
||||
gem install brakeman --version $BRAKEMAN_VERSION
|
||||
|
||||
# Execute Brakeman CLI and generate a SARIF output with the security issues identified during the analysis
|
||||
- name: Scan
|
||||
continue-on-error: true
|
||||
run: |
|
||||
brakeman -f sarif -o output.sarif.json .
|
||||
|
||||
# Upload the SARIF file generated in the previous step
|
||||
- name: Upload SARIF
|
||||
uses: github/codeql-action/upload-sarif@v1
|
||||
with:
|
||||
sarif_file: output.sarif.json
|
||||
19
Gemfile
19
Gemfile
@@ -2,13 +2,14 @@ source 'https://rubygems.org'
|
||||
ruby "2.3.7"
|
||||
git_source(:github) { |repo_name| "https://github.com/#{repo_name}.git" }
|
||||
|
||||
gem 'i18n', '~> 0.6.11'
|
||||
gem 'i18n'
|
||||
gem 'i18n-js', '~> 3.8.0'
|
||||
gem 'rails', '~> 4.0.13'
|
||||
gem 'rails-i18n', '~> 4.0'
|
||||
gem 'rails', '~> 4.2'
|
||||
gem 'rails-i18n'
|
||||
gem 'rails_safe_tasks', '~> 1.0'
|
||||
|
||||
gem "activerecord-import"
|
||||
gem 'responders', '~> 2.0'
|
||||
|
||||
gem "catalog", path: "./engines/catalog"
|
||||
gem 'dfc_provider', path: './engines/dfc_provider'
|
||||
@@ -21,14 +22,14 @@ gem 'pg', '~> 0.21.0'
|
||||
gem 'acts_as_list', '= 0.3.0'
|
||||
gem 'awesome_nested_set', '~> 3.2.1'
|
||||
gem 'cancan', '~> 1.6.10'
|
||||
gem 'ffaker', '~> 1.16'
|
||||
gem 'ffaker'
|
||||
gem 'highline', '2.0.3' # Necessary for the install generator
|
||||
gem 'json', '>= 1.7.7'
|
||||
gem 'money', '5.1.1'
|
||||
gem 'json'
|
||||
gem 'money', '< 6.1.0'
|
||||
gem 'paranoia', '~> 2.0'
|
||||
gem 'ransack', '~> 1.8.10'
|
||||
gem 'state_machine', '1.2.0'
|
||||
gem 'stringex', '~> 1.5.1'
|
||||
gem 'state_machines-activerecord'
|
||||
gem 'stringex', '~> 2.8.5'
|
||||
|
||||
gem 'spree_i18n', github: 'openfoodfoundation/spree_i18n', branch: '1-3-stable'
|
||||
|
||||
@@ -65,7 +66,6 @@ gem 'haml'
|
||||
gem 'redcarpet'
|
||||
gem 'sass'
|
||||
gem 'sass-rails'
|
||||
gem 'truncate_html', '0.9.2'
|
||||
gem 'unicorn'
|
||||
|
||||
gem 'actionpack-action_caching'
|
||||
@@ -91,7 +91,6 @@ gem 'combine_pdf'
|
||||
gem 'wicked_pdf'
|
||||
gem 'wkhtmltopdf-binary'
|
||||
|
||||
gem 'foreigner'
|
||||
gem 'immigrant'
|
||||
gem 'roo', '~> 2.8.3'
|
||||
|
||||
|
||||
259
Gemfile.lock
259
Gemfile.lock
@@ -55,33 +55,44 @@ GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
CFPropertyList (2.3.6)
|
||||
actionmailer (4.0.13)
|
||||
actionpack (= 4.0.13)
|
||||
actionmailer (4.2.11.3)
|
||||
actionpack (= 4.2.11.3)
|
||||
actionview (= 4.2.11.3)
|
||||
activejob (= 4.2.11.3)
|
||||
mail (~> 2.5, >= 2.5.4)
|
||||
actionpack (4.0.13)
|
||||
activesupport (= 4.0.13)
|
||||
builder (~> 3.1.0)
|
||||
erubis (~> 2.7.0)
|
||||
rack (~> 1.5.2)
|
||||
rails-dom-testing (~> 1.0, >= 1.0.5)
|
||||
actionpack (4.2.11.3)
|
||||
actionview (= 4.2.11.3)
|
||||
activesupport (= 4.2.11.3)
|
||||
rack (~> 1.6)
|
||||
rack-test (~> 0.6.2)
|
||||
rails-dom-testing (~> 1.0, >= 1.0.5)
|
||||
rails-html-sanitizer (~> 1.0, >= 1.0.2)
|
||||
actionpack-action_caching (1.2.1)
|
||||
actionpack (>= 4.0.0)
|
||||
actionview (4.2.11.3)
|
||||
activesupport (= 4.2.11.3)
|
||||
builder (~> 3.1)
|
||||
erubis (~> 2.7.0)
|
||||
rails-dom-testing (~> 1.0, >= 1.0.5)
|
||||
rails-html-sanitizer (~> 1.0, >= 1.0.3)
|
||||
active_model_serializers (0.8.4)
|
||||
activemodel (>= 3.0)
|
||||
activejob (4.2.11.3)
|
||||
activesupport (= 4.2.11.3)
|
||||
globalid (>= 0.3.0)
|
||||
activemerchant (1.78.0)
|
||||
activesupport (>= 3.2.14, < 6.x)
|
||||
builder (>= 2.1.2, < 4.0.0)
|
||||
i18n (>= 0.6.9)
|
||||
nokogiri (~> 1.4)
|
||||
activemodel (4.0.13)
|
||||
activesupport (= 4.0.13)
|
||||
builder (~> 3.1.0)
|
||||
activerecord (4.0.13)
|
||||
activemodel (= 4.0.13)
|
||||
activerecord-deprecated_finders (~> 1.0.2)
|
||||
activesupport (= 4.0.13)
|
||||
arel (~> 4.0.0)
|
||||
activerecord-deprecated_finders (1.0.4)
|
||||
activemodel (4.2.11.3)
|
||||
activesupport (= 4.2.11.3)
|
||||
builder (~> 3.1)
|
||||
activerecord (4.2.11.3)
|
||||
activemodel (= 4.2.11.3)
|
||||
activesupport (= 4.2.11.3)
|
||||
arel (~> 6.0)
|
||||
activerecord-import (1.0.7)
|
||||
activerecord (>= 3.2)
|
||||
activerecord-postgresql-adapter (0.0.1)
|
||||
@@ -92,18 +103,20 @@ GEM
|
||||
multi_json (~> 1.11, >= 1.11.2)
|
||||
rack (>= 1.5.2, < 3)
|
||||
railties (>= 4.0)
|
||||
activesupport (4.0.13)
|
||||
i18n (~> 0.6, >= 0.6.9)
|
||||
minitest (~> 4.2)
|
||||
multi_json (~> 1.3)
|
||||
thread_safe (~> 0.1)
|
||||
tzinfo (~> 0.3.37)
|
||||
activesupport (4.2.11.3)
|
||||
i18n (~> 0.7)
|
||||
minitest (~> 5.1)
|
||||
thread_safe (~> 0.3, >= 0.3.4)
|
||||
tzinfo (~> 1.1)
|
||||
acts-as-taggable-on (4.0.0)
|
||||
activerecord (>= 4.0)
|
||||
acts_as_list (0.3.0)
|
||||
activerecord (>= 3.0)
|
||||
addressable (2.7.0)
|
||||
public_suffix (>= 2.0.2, < 5.0)
|
||||
aliyun-sdk (0.8.0)
|
||||
nokogiri (~> 1.6)
|
||||
rest-client (~> 2.0)
|
||||
andand (1.3.3)
|
||||
angular-rails-templates (0.3.0)
|
||||
railties (>= 3.1)
|
||||
@@ -111,7 +124,7 @@ GEM
|
||||
tilt
|
||||
angularjs-file-upload-rails (2.4.1)
|
||||
angularjs-rails (1.5.5)
|
||||
arel (4.0.2)
|
||||
arel (6.0.4)
|
||||
ast (2.4.0)
|
||||
atomic (1.1.101)
|
||||
awesome_nested_set (3.2.1)
|
||||
@@ -122,10 +135,10 @@ GEM
|
||||
aws-sdk-v1 (1.67.0)
|
||||
json (~> 1.4)
|
||||
nokogiri (~> 1)
|
||||
bcrypt (3.1.13)
|
||||
bcrypt (3.1.16)
|
||||
bugsnag (6.18.0)
|
||||
concurrent-ruby (~> 1.0)
|
||||
builder (3.1.4)
|
||||
builder (3.2.4)
|
||||
byebug (11.0.1)
|
||||
cancan (1.6.10)
|
||||
capybara (2.18.0)
|
||||
@@ -137,7 +150,7 @@ GEM
|
||||
xpath (>= 2.0, < 4.0)
|
||||
childprocess (3.0.0)
|
||||
chronic (0.10.2)
|
||||
chunky_png (1.3.11)
|
||||
chunky_png (1.3.14)
|
||||
climate_control (0.2.0)
|
||||
cocaine (0.5.8)
|
||||
climate_control (>= 0.0.3, < 1.0)
|
||||
@@ -169,6 +182,7 @@ GEM
|
||||
sprockets (< 4.0)
|
||||
concurrent-ruby (1.1.7)
|
||||
crack (0.4.4)
|
||||
crass (1.0.6)
|
||||
css_parser (1.7.1)
|
||||
addressable
|
||||
daemons (1.3.1)
|
||||
@@ -202,24 +216,26 @@ GEM
|
||||
devise (>= 2.1.0)
|
||||
devise-token_authenticatable (0.4.10)
|
||||
devise (>= 3.5.2, < 4.0.0)
|
||||
diff-lcs (1.3)
|
||||
diff-lcs (1.4.4)
|
||||
docile (1.3.2)
|
||||
domain_name (0.5.20190701)
|
||||
unf (>= 0.0.5, < 1.0.0)
|
||||
dry-inflector (0.1.2)
|
||||
erubis (2.7.0)
|
||||
eventmachine (1.2.7)
|
||||
excon (0.71.1)
|
||||
excon (0.78.0)
|
||||
execjs (2.7.0)
|
||||
factory_bot (4.10.0)
|
||||
activesupport (>= 3.0.0)
|
||||
factory_bot_rails (4.10.0)
|
||||
factory_bot (~> 4.10.0)
|
||||
railties (>= 3.0.0)
|
||||
faraday (1.0.0)
|
||||
faraday (1.0.1)
|
||||
multipart-post (>= 1.2, < 3)
|
||||
ffaker (1.32.1)
|
||||
ffi (1.12.2)
|
||||
figaro (1.1.1)
|
||||
thor (~> 0.14)
|
||||
ffaker (2.11.0)
|
||||
ffi (1.13.1)
|
||||
figaro (1.2.0)
|
||||
thor (>= 0.14.0, < 2)
|
||||
fission (0.5.0)
|
||||
CFPropertyList (~> 2.2)
|
||||
fog (1.41.0)
|
||||
@@ -256,7 +272,8 @@ GEM
|
||||
fog-xml (~> 0.1.1)
|
||||
ipaddress (~> 0.5)
|
||||
json (>= 1.8, < 2.0)
|
||||
fog-aliyun (0.3.5)
|
||||
fog-aliyun (0.3.19)
|
||||
aliyun-sdk (~> 0.8.0)
|
||||
fog-core
|
||||
fog-json
|
||||
ipaddress (~> 0.8)
|
||||
@@ -302,7 +319,7 @@ GEM
|
||||
fog-core
|
||||
fog-json
|
||||
fog-xml
|
||||
fog-internet-archive (0.0.1)
|
||||
fog-internet-archive (0.0.2)
|
||||
fog-core
|
||||
fog-json
|
||||
fog-xml
|
||||
@@ -359,7 +376,7 @@ GEM
|
||||
fog-voxel (0.1.0)
|
||||
fog-core
|
||||
fog-xml
|
||||
fog-vsphere (3.2.1)
|
||||
fog-vsphere (3.4.0)
|
||||
fog-core
|
||||
rbvmomi (>= 1.9, < 3)
|
||||
fog-xenserver (1.0.0)
|
||||
@@ -369,8 +386,6 @@ GEM
|
||||
fog-xml (0.1.3)
|
||||
fog-core
|
||||
nokogiri (>= 1.5.11, < 2.0.0)
|
||||
foreigner (1.7.4)
|
||||
activerecord (>= 3.0.0)
|
||||
formatador (0.2.5)
|
||||
foundation-icons-sass-rails (3.0.0)
|
||||
railties (>= 3.1.1)
|
||||
@@ -382,8 +397,10 @@ GEM
|
||||
rspec-core (~> 3.0)
|
||||
ruby-progressbar (~> 1.4)
|
||||
geocoder (1.6.4)
|
||||
get_process_mem (0.2.5)
|
||||
get_process_mem (0.2.7)
|
||||
ffi (~> 1.0)
|
||||
globalid (0.4.2)
|
||||
activesupport (>= 4.2.0)
|
||||
gmaps4rails (2.1.2)
|
||||
haml (5.2.0)
|
||||
temple (>= 0.8.0)
|
||||
@@ -391,7 +408,11 @@ GEM
|
||||
hashdiff (1.0.1)
|
||||
highline (2.0.3)
|
||||
hike (1.2.3)
|
||||
i18n (0.6.11)
|
||||
http-accept (1.7.0)
|
||||
http-cookie (1.0.3)
|
||||
domain_name (~> 0.5)
|
||||
i18n (0.9.5)
|
||||
concurrent-ruby (~> 1.0)
|
||||
i18n-js (3.8.0)
|
||||
i18n (>= 0.6.6)
|
||||
immigrant (0.3.6)
|
||||
@@ -422,6 +443,9 @@ GEM
|
||||
letter_opener (1.7.0)
|
||||
launchy (~> 2.2)
|
||||
libv8 (7.3.492.27.1)
|
||||
loofah (2.7.0)
|
||||
crass (~> 1.0.2)
|
||||
nokogiri (>= 1.5.9)
|
||||
mail (2.7.1)
|
||||
mini_mime (>= 0.1.1)
|
||||
method_source (0.9.2)
|
||||
@@ -432,15 +456,17 @@ GEM
|
||||
mini_portile2 (2.4.0)
|
||||
mini_racer (0.2.15)
|
||||
libv8 (> 7.3)
|
||||
minitest (4.7.5)
|
||||
money (5.1.1)
|
||||
i18n (~> 0.6.0)
|
||||
minitest (5.14.2)
|
||||
money (5.0.0)
|
||||
i18n (~> 0.4)
|
||||
json
|
||||
msgpack (1.3.3)
|
||||
multi_json (1.15.0)
|
||||
multi_xml (0.6.0)
|
||||
multipart-post (2.1.1)
|
||||
netrc (0.11.0)
|
||||
newrelic_rpm (3.18.1.330)
|
||||
nokogiri (1.10.9)
|
||||
nokogiri (1.10.10)
|
||||
mini_portile2 (~> 2.4.0)
|
||||
oauth2 (1.4.4)
|
||||
faraday (>= 0.8, < 2.0)
|
||||
@@ -449,7 +475,7 @@ GEM
|
||||
multi_xml (~> 0.5)
|
||||
rack (>= 1.2, < 3)
|
||||
oj (3.10.8)
|
||||
optimist (3.0.0)
|
||||
optimist (3.0.1)
|
||||
orm_adapter (0.5.0)
|
||||
paper_trail (7.1.3)
|
||||
activerecord (>= 4.0, < 5.2)
|
||||
@@ -479,7 +505,7 @@ GEM
|
||||
byebug (~> 11.0)
|
||||
pry (~> 0.10)
|
||||
public_suffix (4.0.6)
|
||||
rack (1.5.5)
|
||||
rack (1.6.13)
|
||||
rack-mini-profiler (2.0.2)
|
||||
rack (>= 1.2.0)
|
||||
rack-protection (1.5.5)
|
||||
@@ -489,21 +515,32 @@ GEM
|
||||
rack
|
||||
rack-test (0.6.3)
|
||||
rack (>= 1.0)
|
||||
rails (4.0.13)
|
||||
actionmailer (= 4.0.13)
|
||||
actionpack (= 4.0.13)
|
||||
activerecord (= 4.0.13)
|
||||
activesupport (= 4.0.13)
|
||||
rails (4.2.11.3)
|
||||
actionmailer (= 4.2.11.3)
|
||||
actionpack (= 4.2.11.3)
|
||||
actionview (= 4.2.11.3)
|
||||
activejob (= 4.2.11.3)
|
||||
activemodel (= 4.2.11.3)
|
||||
activerecord (= 4.2.11.3)
|
||||
activesupport (= 4.2.11.3)
|
||||
bundler (>= 1.3.0, < 2.0)
|
||||
railties (= 4.0.13)
|
||||
sprockets-rails (~> 2.0)
|
||||
rails-i18n (4.0.5)
|
||||
i18n (~> 0.6)
|
||||
railties (= 4.2.11.3)
|
||||
sprockets-rails
|
||||
rails-deprecated_sanitizer (1.0.3)
|
||||
activesupport (>= 4.2.0.alpha)
|
||||
rails-dom-testing (1.0.9)
|
||||
activesupport (>= 4.2.0, < 5.0)
|
||||
nokogiri (~> 1.6)
|
||||
rails-deprecated_sanitizer (>= 1.0.1)
|
||||
rails-html-sanitizer (1.3.0)
|
||||
loofah (~> 2.3)
|
||||
rails-i18n (4.0.9)
|
||||
i18n (~> 0.7)
|
||||
railties (~> 4.0)
|
||||
rails_safe_tasks (1.0.0)
|
||||
railties (4.0.13)
|
||||
actionpack (= 4.0.13)
|
||||
activesupport (= 4.0.13)
|
||||
railties (4.2.11.3)
|
||||
actionpack (= 4.2.11.3)
|
||||
activesupport (= 4.2.11.3)
|
||||
rake (>= 0.8.7)
|
||||
thor (>= 0.18.1, < 2.0)
|
||||
rainbow (3.0.0)
|
||||
@@ -514,10 +551,10 @@ GEM
|
||||
activerecord (>= 3.0, < 5.2)
|
||||
activesupport (>= 3.0, < 5.2)
|
||||
i18n
|
||||
rb-fsevent (0.10.3)
|
||||
rb-fsevent (0.10.4)
|
||||
rb-inotify (0.10.1)
|
||||
ffi (~> 1.0)
|
||||
rbvmomi (2.2.0)
|
||||
rbvmomi (2.4.1)
|
||||
builder (~> 3.0)
|
||||
json (>= 1.8)
|
||||
nokogiri (~> 1.5)
|
||||
@@ -525,41 +562,47 @@ GEM
|
||||
redcarpet (3.5.0)
|
||||
request_store (1.5.0)
|
||||
rack (>= 1.4)
|
||||
responders (1.1.2)
|
||||
railties (>= 3.2, < 4.2)
|
||||
responders (2.4.1)
|
||||
actionpack (>= 4.2.0, < 6.0)
|
||||
railties (>= 4.2.0, < 6.0)
|
||||
rest-client (2.1.0)
|
||||
http-accept (>= 1.7.0, < 2.0)
|
||||
http-cookie (>= 1.0.2, < 2.0)
|
||||
mime-types (>= 1.16, < 4.0)
|
||||
netrc (~> 0.8)
|
||||
rexml (3.2.4)
|
||||
roadie (3.4.0)
|
||||
roadie (3.5.1)
|
||||
css_parser (~> 1.4)
|
||||
nokogiri (~> 1.5)
|
||||
nokogiri (~> 1.8)
|
||||
roadie-rails (1.3.0)
|
||||
railties (>= 3.0, < 5.3)
|
||||
roadie (~> 3.1)
|
||||
roo (2.8.3)
|
||||
nokogiri (~> 1)
|
||||
rubyzip (>= 1.3.0, < 3.0.0)
|
||||
rspec (3.9.0)
|
||||
rspec-core (~> 3.9.0)
|
||||
rspec-expectations (~> 3.9.0)
|
||||
rspec-mocks (~> 3.9.0)
|
||||
rspec-core (3.9.1)
|
||||
rspec-support (~> 3.9.1)
|
||||
rspec-expectations (3.9.0)
|
||||
rspec (3.10.0)
|
||||
rspec-core (~> 3.10.0)
|
||||
rspec-expectations (~> 3.10.0)
|
||||
rspec-mocks (~> 3.10.0)
|
||||
rspec-core (3.10.0)
|
||||
rspec-support (~> 3.10.0)
|
||||
rspec-expectations (3.10.0)
|
||||
diff-lcs (>= 1.2.0, < 2.0)
|
||||
rspec-support (~> 3.9.0)
|
||||
rspec-mocks (3.9.1)
|
||||
rspec-support (~> 3.10.0)
|
||||
rspec-mocks (3.10.0)
|
||||
diff-lcs (>= 1.2.0, < 2.0)
|
||||
rspec-support (~> 3.9.0)
|
||||
rspec-rails (3.9.1)
|
||||
actionpack (>= 3.0)
|
||||
activesupport (>= 3.0)
|
||||
railties (>= 3.0)
|
||||
rspec-core (~> 3.9.0)
|
||||
rspec-expectations (~> 3.9.0)
|
||||
rspec-mocks (~> 3.9.0)
|
||||
rspec-support (~> 3.9.0)
|
||||
rspec-support (~> 3.10.0)
|
||||
rspec-rails (4.0.1)
|
||||
actionpack (>= 4.2)
|
||||
activesupport (>= 4.2)
|
||||
railties (>= 4.2)
|
||||
rspec-core (~> 3.9)
|
||||
rspec-expectations (~> 3.9)
|
||||
rspec-mocks (~> 3.9)
|
||||
rspec-support (~> 3.9)
|
||||
rspec-retry (0.6.2)
|
||||
rspec-core (> 3.3)
|
||||
rspec-support (3.9.2)
|
||||
rspec-support (3.10.0)
|
||||
rswag (2.3.1)
|
||||
rswag-api (= 2.3.1)
|
||||
rswag-specs (= 2.3.1)
|
||||
@@ -601,8 +644,8 @@ GEM
|
||||
selenium-webdriver (3.142.7)
|
||||
childprocess (>= 0.5, < 4.0)
|
||||
rubyzip (>= 1.2.2)
|
||||
shoulda-matchers (3.1.3)
|
||||
activesupport (>= 4.0.0)
|
||||
shoulda-matchers (4.0.1)
|
||||
activesupport (>= 4.2.0)
|
||||
simplecov (0.17.1)
|
||||
docile (~> 1.1)
|
||||
json (>= 1.8, < 3)
|
||||
@@ -624,21 +667,30 @@ GEM
|
||||
actionpack (>= 3.0)
|
||||
activesupport (>= 3.0)
|
||||
sprockets (>= 2.8, < 4.0)
|
||||
state_machine (1.2.0)
|
||||
stringex (1.5.1)
|
||||
stripe (5.25.0)
|
||||
state_machines (0.5.0)
|
||||
state_machines-activemodel (0.7.1)
|
||||
activemodel (>= 4.1)
|
||||
state_machines (>= 0.5.0)
|
||||
state_machines-activerecord (0.6.0)
|
||||
activerecord (>= 4.1)
|
||||
state_machines-activemodel (>= 0.5.0)
|
||||
stringex (2.8.5)
|
||||
stripe (5.28.0)
|
||||
temple (0.8.2)
|
||||
test-prof (0.7.5)
|
||||
test-unit (3.3.6)
|
||||
test-unit (3.3.7)
|
||||
power_assert
|
||||
thor (0.20.3)
|
||||
thread_safe (0.3.6)
|
||||
tilt (1.4.1)
|
||||
timecop (0.9.2)
|
||||
truncate_html (0.9.2)
|
||||
tzinfo (0.3.57)
|
||||
tzinfo (1.2.8)
|
||||
thread_safe (~> 0.1)
|
||||
uglifier (4.2.0)
|
||||
execjs (>= 0.3.0, < 3)
|
||||
unf (0.1.4)
|
||||
unf_ext
|
||||
unf_ext (0.0.7.7)
|
||||
unicode-display_width (1.7.0)
|
||||
unicorn (5.7.0)
|
||||
kgio (~> 2.6)
|
||||
@@ -655,7 +707,7 @@ GEM
|
||||
nokogiri (~> 1.6)
|
||||
rubyzip (>= 1.3.0)
|
||||
selenium-webdriver (>= 3.0, < 4.0)
|
||||
webmock (3.9.5)
|
||||
webmock (3.10.0)
|
||||
addressable (>= 2.3.6)
|
||||
crack (>= 0.3.2)
|
||||
hashdiff (>= 0.4.0, < 2.0.0)
|
||||
@@ -666,8 +718,8 @@ GEM
|
||||
wkhtmltopdf-binary (0.12.5)
|
||||
xml-simple (1.1.5)
|
||||
xmlrpc (0.3.0)
|
||||
xpath (2.1.0)
|
||||
nokogiri (~> 1.3)
|
||||
xpath (3.2.0)
|
||||
nokogiri (~> 1.8)
|
||||
|
||||
PLATFORMS
|
||||
ruby
|
||||
@@ -712,9 +764,8 @@ DEPENDENCIES
|
||||
dfc_provider!
|
||||
eventmachine (>= 1.2.3)
|
||||
factory_bot_rails (= 4.10.0)
|
||||
ffaker (~> 1.16)
|
||||
ffaker
|
||||
figaro
|
||||
foreigner
|
||||
foundation-icons-sass-rails
|
||||
foundation-rails (= 5.5.2.1)
|
||||
fuubar (~> 2.5.0)
|
||||
@@ -722,20 +773,20 @@ DEPENDENCIES
|
||||
gmaps4rails
|
||||
haml
|
||||
highline (= 2.0.3)
|
||||
i18n (~> 0.6.11)
|
||||
i18n
|
||||
i18n-js (~> 3.8.0)
|
||||
immigrant
|
||||
jquery-migrate-rails
|
||||
jquery-rails (= 3.1.5)
|
||||
jquery-ui-rails (~> 4.2)
|
||||
json (>= 1.7.7)
|
||||
json
|
||||
json_spec (~> 1.1.4)
|
||||
jwt (~> 2.2)
|
||||
kaminari (~> 0.17.0)
|
||||
knapsack
|
||||
letter_opener (>= 1.4.1)
|
||||
mini_racer (= 0.2.15)
|
||||
money (= 5.1.1)
|
||||
money (< 6.1.0)
|
||||
newrelic_rpm (~> 3.0)
|
||||
oauth2 (~> 1.4.4)
|
||||
ofn-qz!
|
||||
@@ -750,11 +801,12 @@ DEPENDENCIES
|
||||
rack-mini-profiler (< 3.0.0)
|
||||
rack-rewrite
|
||||
rack-ssl
|
||||
rails (~> 4.0.13)
|
||||
rails-i18n (~> 4.0)
|
||||
rails (~> 4.2)
|
||||
rails-i18n
|
||||
rails_safe_tasks (~> 1.0)
|
||||
ransack (~> 1.8.10)
|
||||
redcarpet
|
||||
responders (~> 2.0)
|
||||
roadie-rails (~> 1.3.0)
|
||||
roo (~> 2.8.3)
|
||||
rspec-rails (>= 3.5.2)
|
||||
@@ -772,13 +824,12 @@ DEPENDENCIES
|
||||
spree_paypal_express!
|
||||
spring
|
||||
spring-commands-rspec
|
||||
state_machine (= 1.2.0)
|
||||
stringex (~> 1.5.1)
|
||||
state_machines-activerecord
|
||||
stringex (~> 2.8.5)
|
||||
stripe
|
||||
test-prof
|
||||
test-unit (~> 3.3)
|
||||
timecop
|
||||
truncate_html (= 0.9.2)
|
||||
uglifier (>= 1.0.3)
|
||||
unicorn
|
||||
unicorn-rails
|
||||
|
||||
@@ -33,7 +33,9 @@ We also have a [Super Admin Guide][super-admin-guide] to help with configuration
|
||||
|
||||
## Testing
|
||||
|
||||
We use [BrowserStack](https://www.browserstack.com/) as a manual testing tool. BrowserStack provides open source projects with unlimited and free of charge accounts. A big thanks to them!
|
||||
If you'd like to help out with testing, please introduce yourself on the #testing channel on [Slack][slack-invite] and download the [ZenHub browser extension][zenhub] to view the development pipeline.
|
||||
|
||||
We use [BrowserStack](https://www.browserstack.com/) as a manual testing tool. BrowserStack provides open source projects with unlimited and free of charge accounts. A big thanks to them!
|
||||
|
||||
## Licence
|
||||
|
||||
@@ -45,3 +47,4 @@ Copyright (c) 2012 - 2020 Open Food Foundation, released under the AGPL licence.
|
||||
[ofn-install]: https://github.com/openfoodfoundation/ofn-install
|
||||
[super-admin-guide]: https://ofn-user-guide.gitbook.io/ofn-super-admin-guide
|
||||
[welcome-dev]: https://github.com/openfoodfoundation/openfoodnetwork/projects/27
|
||||
[zenhub]: https://www.zenhub.com/extension
|
||||
|
||||
@@ -6,7 +6,7 @@ Darkswarm.filter "localizeCurrency", (currencyConfig)->
|
||||
# Set decimal points, 2 or 0 if hide_cents.
|
||||
decimals = if currencyConfig.hide_cents == "true" then 0 else 2
|
||||
# Set format if the currency symbol should come after the number, otherwise (default) use the locale setting.
|
||||
format = if currencyConfig.symbol_position == "after" then "%n %u" else undefined
|
||||
format = if currencyConfig.symbol_position == "after" then "%n%u" else undefined
|
||||
# We need to use parseFloat as the amount should come in as a string.
|
||||
amount = parseFloat(amount)
|
||||
|
||||
|
||||
@@ -14,8 +14,9 @@
|
||||
{{'hubs_delivery' | t}}
|
||||
.row
|
||||
.columns.small-12
|
||||
%a.cta-hub{"ng-href" => "{{::enterprise.path}}", "ng-attr-target" => "{{ embedded_layout ? '_blank' : undefined}}",
|
||||
%a.cta-hub{"ng-href" => "{{::enterprise.path}}#/shop", "ng-attr-target" => "{{ embedded_layout ? '_blank' : undefined}}",
|
||||
"ng-class" => "{primary: enterprise.active, secondary: !enterprise.active}",
|
||||
"ng-click" => "$close()",
|
||||
"ofn-change-hub" => "enterprise"}
|
||||
.hub-name{"ng-bind" => "::enterprise.name"}
|
||||
%span{"ng-if" => "::enterprise.active"} ({{'maps_open' | t}})
|
||||
|
||||
@@ -12,8 +12,9 @@
|
||||
.row
|
||||
.columns.small-12
|
||||
%a.cta-hub{"ng-repeat" => "hub in enterprise.hubs | filter:{id: '!'+enterprise.id} | orderBy:'-active'",
|
||||
"ng-href" => "{{::hub.path}}", "ofn-empties-cart" => "hub",
|
||||
"ng-class" => "::{primary: hub.active, secondary: !hub.active}"}
|
||||
"ng-href" => "{{::hub.path}}#/shop", "ofn-empties-cart" => "hub",
|
||||
"ng-class" => "::{primary: hub.active, secondary: !hub.active}",
|
||||
"ng-click" => "$close()"}
|
||||
.hub-name{"ng-bind" => "::hub.name"}
|
||||
%span{"ng-if" => "::hub.active"} ({{'maps_open' | t}})
|
||||
%span{"ng-if" => "::!hub.active"} ({{'maps_closed' | t}})
|
||||
|
||||
@@ -59,6 +59,7 @@
|
||||
|
||||
// Variant price
|
||||
.variant-price {
|
||||
white-space: nowrap;
|
||||
@include breakpoint(phablet) {
|
||||
padding-left: 1rem;
|
||||
}
|
||||
|
||||
@@ -81,14 +81,14 @@ module Admin
|
||||
end
|
||||
|
||||
def bulk_update
|
||||
@enterprise_set = EnterpriseSet.new(collection, params[:enterprise_set])
|
||||
@enterprise_set = EnterpriseSet.new(collection, bulk_params)
|
||||
if @enterprise_set.save
|
||||
flash[:success] = I18n.t(:enterprise_bulk_update_success_notice)
|
||||
|
||||
redirect_to main_app.admin_enterprises_path
|
||||
else
|
||||
touched_enterprises = @enterprise_set.collection.select(&:changed?)
|
||||
@enterprise_set.collection.select! { |e| touched_enterprises.include? e }
|
||||
@enterprise_set.collection.to_a.select! { |e| touched_enterprises.include? e }
|
||||
flash[:error] = I18n.t(:enterprise_bulk_update_error)
|
||||
render :index
|
||||
end
|
||||
@@ -214,7 +214,8 @@ module Admin
|
||||
rule = @object.tag_rules.find_by(id: attrs.delete(:id)) ||
|
||||
attrs[:type].constantize.new(enterprise: @object)
|
||||
create_calculator_for(rule, attrs) if rule.type == "TagRule::DiscountOrder" && rule.calculator.nil?
|
||||
rule.update(attrs)
|
||||
|
||||
rule.update(attrs.permit(PermittedAttributes::TagRules.attributes))
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -319,6 +320,12 @@ module Admin
|
||||
PermittedAttributes::Enterprise.new(params).call
|
||||
end
|
||||
|
||||
def bulk_params
|
||||
params.require(:enterprise_set).permit(
|
||||
collection_attributes: PermittedAttributes::Enterprise.attributes
|
||||
)
|
||||
end
|
||||
|
||||
# Used in ResourceController#create
|
||||
def permitted_resource_params
|
||||
enterprise_params
|
||||
|
||||
@@ -91,7 +91,7 @@ module Admin
|
||||
|
||||
# Send notifications to all producers who are part of the order cycle
|
||||
def notify_producers
|
||||
Delayed::Job.enqueue OrderCycleNotificationJob.new(params[:id].to_i)
|
||||
OrderCycleNotificationJob.perform_later params[:id].to_i
|
||||
|
||||
redirect_to main_app.admin_order_cycles_path,
|
||||
notice: I18n.t(:order_cycles_email_to_producers_notice)
|
||||
|
||||
@@ -5,11 +5,11 @@ require "spree/core/controller_helpers/ssl"
|
||||
module Api
|
||||
class BaseController < ActionController::Metal
|
||||
include ActionController::StrongParameters
|
||||
include ActionController::RespondWith
|
||||
include Spree::Api::ControllerSetup
|
||||
include Spree::Core::ControllerHelpers::SSL
|
||||
include ::ActionController::Head
|
||||
|
||||
respond_to :json
|
||||
include ::ActionController::ConditionalGet
|
||||
|
||||
attr_accessor :current_api_user
|
||||
|
||||
@@ -73,7 +73,7 @@ module Api
|
||||
end
|
||||
|
||||
def error_during_processing(exception)
|
||||
render(text: { exception: exception.message }.to_json,
|
||||
render(json: { exception: exception.message },
|
||||
status: :unprocessable_entity) && return
|
||||
end
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ module Api
|
||||
@enterprise = Enterprise.new(enterprise_params)
|
||||
if @enterprise.save
|
||||
@enterprise.user_ids = user_ids
|
||||
render text: @enterprise.id, status: :created
|
||||
render json: @enterprise.id, status: :created
|
||||
else
|
||||
invalid_resource!(@enterprise)
|
||||
end
|
||||
@@ -26,7 +26,7 @@ module Api
|
||||
authorize! :update, @enterprise
|
||||
|
||||
if @enterprise.update(enterprise_params)
|
||||
render text: @enterprise.id, status: :ok
|
||||
render json: @enterprise.id, status: :ok
|
||||
else
|
||||
invalid_resource!(@enterprise)
|
||||
end
|
||||
|
||||
@@ -20,7 +20,7 @@ module Api
|
||||
search_params
|
||||
).products_json
|
||||
|
||||
render json: products
|
||||
render plain: products, content_type: "application/json"
|
||||
rescue ProductsRenderer::NoProducts
|
||||
render_no_products
|
||||
end
|
||||
@@ -31,13 +31,15 @@ module Api
|
||||
where(spree_products: { id: distributed_products }).
|
||||
select('DISTINCT spree_taxons.*')
|
||||
|
||||
render json: ActiveModel::ArraySerializer.new(taxons, each_serializer: Api::TaxonSerializer)
|
||||
render plain: ActiveModel::ArraySerializer.new(
|
||||
taxons, each_serializer: Api::TaxonSerializer
|
||||
).to_json, content_type: "application/json"
|
||||
end
|
||||
|
||||
def properties
|
||||
render json: ActiveModel::ArraySerializer.new(
|
||||
render plain: ActiveModel::ArraySerializer.new(
|
||||
product_properties | producer_properties, each_serializer: Api::PropertySerializer
|
||||
)
|
||||
).to_json, content_type: "application/json"
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
@@ -145,7 +145,7 @@ module Api
|
||||
end
|
||||
|
||||
def query_params_with_defaults
|
||||
params[:q].to_h.reverse_merge(s: 'created_at desc')
|
||||
(params[:q] || {}).reverse_merge(s: 'created_at desc')
|
||||
end
|
||||
|
||||
def pagination_data(results)
|
||||
|
||||
@@ -1,7 +1,13 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "application_responder"
|
||||
require 'open_food_network/referer_parser'
|
||||
require_dependency 'spree/authentication_helpers'
|
||||
|
||||
class ApplicationController < ActionController::Base
|
||||
self.responder = ApplicationResponder
|
||||
respond_to :html
|
||||
|
||||
protect_from_forgery
|
||||
|
||||
prepend_before_action :restrict_iframes
|
||||
@@ -10,6 +16,12 @@ class ApplicationController < ActionController::Base
|
||||
include EnterprisesHelper
|
||||
include Spree::AuthenticationHelpers
|
||||
|
||||
# Helper for debugging strong_parameters
|
||||
rescue_from ActiveModel::ForbiddenAttributesError, with: :print_params
|
||||
def print_params
|
||||
raise ActiveModel::ForbiddenAttributesError, params.to_s
|
||||
end
|
||||
|
||||
def redirect_to(options = {}, response_status = {})
|
||||
::Rails.logger.error("Redirected by #{begin
|
||||
caller(1).first
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
require 'spree/core/controller_helpers/order'
|
||||
|
||||
class CartController < BaseController
|
||||
before_action :check_authorization
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ require 'open_food_network/address_finder'
|
||||
class CheckoutController < Spree::StoreController
|
||||
layout 'darkswarm'
|
||||
|
||||
include OrderStockCheck
|
||||
include CheckoutHelper
|
||||
include OrderCyclesHelper
|
||||
include EnterprisesHelper
|
||||
@@ -24,7 +25,7 @@ class CheckoutController < Spree::StoreController
|
||||
|
||||
before_action :ensure_order_not_completed
|
||||
before_action :ensure_checkout_allowed
|
||||
before_action :ensure_sufficient_stock_lines
|
||||
before_action :handle_insufficient_stock
|
||||
|
||||
before_action :associate_user
|
||||
before_action :check_authorization
|
||||
@@ -77,13 +78,6 @@ class CheckoutController < Spree::StoreController
|
||||
redirect_to main_app.cart_path if @order.completed?
|
||||
end
|
||||
|
||||
def ensure_sufficient_stock_lines
|
||||
if @order.insufficient_stock_lines.present?
|
||||
flash[:error] = Spree.t(:inventory_error_flash_for_insufficient_quantity)
|
||||
redirect_to main_app.cart_path
|
||||
end
|
||||
end
|
||||
|
||||
def load_order
|
||||
@order = current_order
|
||||
|
||||
|
||||
18
app/controllers/concerns/order_stock_check.rb
Normal file
18
app/controllers/concerns/order_stock_check.rb
Normal file
@@ -0,0 +1,18 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module OrderStockCheck
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
def handle_insufficient_stock
|
||||
return if sufficient_stock?
|
||||
|
||||
flash[:error] = Spree.t(:inventory_error_flash_for_insufficient_quantity)
|
||||
redirect_to main_app.cart_path
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def sufficient_stock?
|
||||
@sufficient_stock ||= @order.insufficient_stock_lines.blank?
|
||||
end
|
||||
end
|
||||
@@ -6,6 +6,8 @@ class EnterprisesController < BaseController
|
||||
include OrderCyclesHelper
|
||||
include SerializerHelper
|
||||
|
||||
protect_from_forgery except: :check_permalink
|
||||
|
||||
# These prepended filters are in the reverse order of execution
|
||||
prepend_before_action :set_order_cycles, :require_distributor_chosen, :reset_order, only: :shop
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ module Spree
|
||||
end
|
||||
|
||||
def update
|
||||
unless @order.update(order_params) && @order.line_items.present?
|
||||
unless order_params.present? && @order.update(order_params) && @order.line_items.present?
|
||||
if @order.line_items.empty?
|
||||
@order.errors.add(:line_items, Spree.t('errors.messages.blank'))
|
||||
end
|
||||
|
||||
@@ -179,7 +179,7 @@ module Spree
|
||||
end
|
||||
|
||||
def bulk_index_query(params)
|
||||
params[:filters].to_h.merge(page: params[:page], per_page: params[:per_page])
|
||||
(params[:filters] || {}).merge(page: params[:page], per_page: params[:per_page])
|
||||
end
|
||||
|
||||
def load_form_data
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
require 'spree/core/controller_helpers/order'
|
||||
require 'spree/core/controller_helpers/auth'
|
||||
|
||||
module Spree
|
||||
class OrdersController < Spree::StoreController
|
||||
include OrderCyclesHelper
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
Spree::PaypalController.class_eval do
|
||||
include OrderStockCheck
|
||||
|
||||
before_action :enable_embedded_shopfront
|
||||
before_action :destroy_orphaned_paypal_payments, only: :confirm
|
||||
after_action :reset_order_when_complete, only: :confirm
|
||||
@@ -40,6 +42,9 @@ Spree::PaypalController.class_eval do
|
||||
begin
|
||||
pp_response = provider.set_express_checkout(pp_request)
|
||||
if pp_response.success?
|
||||
# At this point Paypal has *provisionally* accepted that the payment can now be placed,
|
||||
# and the user will be redirected to a Paypal payment page. On completion, the user is
|
||||
# sent back and the response is handled in the #confirm action in this controller.
|
||||
redirect_to provider.express_checkout_url(pp_response, useraction: 'commit')
|
||||
else
|
||||
flash[:error] = Spree.t('flash.generic_error', scope: 'paypal', reasons: pp_response.errors.map(&:long_message).join(" "))
|
||||
@@ -51,6 +56,32 @@ Spree::PaypalController.class_eval do
|
||||
end
|
||||
end
|
||||
|
||||
def confirm
|
||||
@order = current_order || raise(ActiveRecord::RecordNotFound)
|
||||
|
||||
# At this point the user has come back from the Paypal form, and we get one
|
||||
# last chance to interact with the payment process before the money moves...
|
||||
return reset_to_cart unless sufficient_stock?
|
||||
|
||||
@order.payments.create!({
|
||||
source: Spree::PaypalExpressCheckout.create({
|
||||
token: params[:token],
|
||||
payer_id: params[:PayerID]
|
||||
}),
|
||||
amount: @order.total,
|
||||
payment_method: payment_method
|
||||
})
|
||||
@order.next
|
||||
if @order.complete?
|
||||
flash.notice = Spree.t(:order_processed_successfully)
|
||||
flash[:commerce_tracking] = "nothing special"
|
||||
session[:order_id] = nil
|
||||
redirect_to completion_route(@order)
|
||||
else
|
||||
redirect_to checkout_state_path(@order.state)
|
||||
end
|
||||
end
|
||||
|
||||
def cancel
|
||||
flash[:notice] = Spree.t('flash.cancel', scope: 'paypal')
|
||||
redirect_to main_app.checkout_path
|
||||
@@ -66,6 +97,10 @@ Spree::PaypalController.class_eval do
|
||||
|
||||
private
|
||||
|
||||
def payment_method
|
||||
@payment_method ||= Spree::PaymentMethod.find(params[:payment_method_id])
|
||||
end
|
||||
|
||||
def permit_parameters!
|
||||
params.permit(:token, :payment_method_id, :PayerID)
|
||||
end
|
||||
@@ -79,6 +114,11 @@ Spree::PaypalController.class_eval do
|
||||
end
|
||||
end
|
||||
|
||||
def reset_to_cart
|
||||
OrderCheckoutRestart.new(@order).call
|
||||
handle_insufficient_stock
|
||||
end
|
||||
|
||||
# See #1074 and #1837 for more detail on why we need this
|
||||
# An 'orphaned' Spree::Payment is created for every call to CheckoutController#update
|
||||
# for orders that are processed using a Spree::Gateway::PayPalExpress payment method
|
||||
|
||||
@@ -18,7 +18,9 @@ module CheckoutHelper
|
||||
enterprise_fee_adjustments = adjustments.select { |a| a.originator_type == 'EnterpriseFee' && a.source_type != 'Spree::LineItem' }
|
||||
adjustments.reject! { |a| a.originator_type == 'EnterpriseFee' && a.source_type != 'Spree::LineItem' }
|
||||
unless exclude.include? :admin_and_handling
|
||||
adjustments << Spree::Adjustment.new(label: I18n.t(:orders_form_admin), amount: enterprise_fee_adjustments.sum(&:amount))
|
||||
adjustments << Spree::Adjustment.new(
|
||||
label: I18n.t(:orders_form_admin), amount: enterprise_fee_adjustments.map(&:amount).sum
|
||||
)
|
||||
end
|
||||
|
||||
adjustments
|
||||
@@ -26,7 +28,7 @@ module CheckoutHelper
|
||||
|
||||
def display_checkout_admin_and_handling_adjustments_total_for(order)
|
||||
adjustments = order.adjustments.eligible.where('originator_type = ? AND source_type != ? ', 'EnterpriseFee', 'Spree::LineItem')
|
||||
Spree::Money.new adjustments.sum(&:amount), currency: order.currency
|
||||
Spree::Money.new adjustments.map(&:amount).sum, currency: order.currency
|
||||
end
|
||||
|
||||
def checkout_line_item_adjustments(order)
|
||||
@@ -34,7 +36,7 @@ module CheckoutHelper
|
||||
end
|
||||
|
||||
def checkout_subtotal(order)
|
||||
order.item_total + checkout_line_item_adjustments(order).sum(&:amount)
|
||||
order.item_total + checkout_line_item_adjustments(order).map(&:amount).sum
|
||||
end
|
||||
|
||||
def display_checkout_subtotal(order)
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
module HtmlHelper
|
||||
def strip_html(html)
|
||||
strip_surrounding_whitespace substitute_entities strip_tags add_linebreaks html
|
||||
end
|
||||
|
||||
def substitute_entities(html)
|
||||
html.andand.gsub(/ /i, ' ').andand.gsub(/&/i, '&')
|
||||
end
|
||||
|
||||
def add_linebreaks(html)
|
||||
# I know Cthulu is coming for me. Forgive me.
|
||||
# http://stackoverflow.com/a/1732454/2720566
|
||||
html.
|
||||
andand.gsub(%r{</h[^>]>|</p>|</div>}, "\\1\n\n").
|
||||
andand.gsub(/<br[^>]*>/, "\\1\n")
|
||||
end
|
||||
|
||||
def strip_surrounding_whitespace(html)
|
||||
html.andand.strip
|
||||
end
|
||||
end
|
||||
25
app/jobs/bulk_invoice_job.rb
Normal file
25
app/jobs/bulk_invoice_job.rb
Normal file
@@ -0,0 +1,25 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class BulkInvoiceJob < ActiveJob::Base
|
||||
def perform(order_ids, filepath)
|
||||
pdf = CombinePDF.new
|
||||
|
||||
orders_from(order_ids).each do |order|
|
||||
invoice = renderer.render_to_string(order)
|
||||
|
||||
pdf << CombinePDF.parse(invoice)
|
||||
end
|
||||
|
||||
pdf.save filepath
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def orders_from(order_ids)
|
||||
Spree::Order.where(id: order_ids).order("completed_at DESC")
|
||||
end
|
||||
|
||||
def renderer
|
||||
@renderer ||= InvoiceRenderer.new
|
||||
end
|
||||
end
|
||||
@@ -1,5 +1,7 @@
|
||||
ConfirmOrderJob = Struct.new(:order_id) do
|
||||
def perform
|
||||
# frozen_string_literal: true
|
||||
|
||||
class ConfirmOrderJob < ActiveJob::Base
|
||||
def perform(order_id)
|
||||
Spree::OrderMailer.confirm_email_for_customer(order_id).deliver
|
||||
Spree::OrderMailer.confirm_email_for_shop(order_id).deliver
|
||||
end
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
ConfirmSignupJob = Struct.new(:user_id) do
|
||||
def perform
|
||||
# frozen_string_literal: true
|
||||
|
||||
class ConfirmSignupJob < ActiveJob::Base
|
||||
def perform(user_id)
|
||||
user = Spree::User.find user_id
|
||||
Spree::UserMailer.signup_confirmation(user).deliver
|
||||
end
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
# Delivers an email with a report of the order cycle to each of its suppliers
|
||||
OrderCycleNotificationJob = Struct.new(:order_cycle_id) do
|
||||
def perform
|
||||
class OrderCycleNotificationJob < ActiveJob::Base
|
||||
def perform(order_cycle_id)
|
||||
order_cycle = OrderCycle.find(order_cycle_id)
|
||||
order_cycle.suppliers.each do |supplier|
|
||||
ProducerMailer.order_cycle_report(supplier, order_cycle).deliver
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
WelcomeEnterpriseJob = Struct.new(:enterprise_id) do
|
||||
def perform
|
||||
# frozen_string_literal: true
|
||||
|
||||
class WelcomeEnterpriseJob < ActiveJob::Base
|
||||
def perform(enterprise_id)
|
||||
enterprise = Enterprise.find enterprise_id
|
||||
EnterpriseMailer.welcome(enterprise).deliver
|
||||
end
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
module Spree
|
||||
class OrderMailer < BaseMailer
|
||||
helper HtmlHelper
|
||||
helper ::CheckoutHelper
|
||||
helper SpreeCurrencyHelper
|
||||
helper Spree::Admin::PaymentsHelper
|
||||
|
||||
@@ -9,7 +9,7 @@ module ApiActionCaching
|
||||
included do
|
||||
include ActionController::Caching
|
||||
include ActionController::Caching::Actions
|
||||
include AbstractController::Layouts
|
||||
include ActionView::Layouts
|
||||
|
||||
# These configs are not assigned to the controller automatically with ActionController::Metal
|
||||
self.cache_store = Rails.configuration.cache_store
|
||||
|
||||
@@ -132,7 +132,7 @@ class Enterprise < ActiveRecord::Base
|
||||
where(nil)
|
||||
end
|
||||
}
|
||||
scope :is_primary_producer, -> { where(is_primary_producer: true) }
|
||||
scope :is_primary_producer, -> { where("enterprises.is_primary_producer IS TRUE") }
|
||||
scope :is_distributor, -> { where('sells != ?', 'none') }
|
||||
scope :is_hub, -> { where(sells: 'any') }
|
||||
scope :supplying_variant_in, lambda { |variants|
|
||||
@@ -400,7 +400,7 @@ class Enterprise < ActiveRecord::Base
|
||||
end
|
||||
|
||||
def send_welcome_email
|
||||
Delayed::Job.enqueue WelcomeEnterpriseJob.new(id)
|
||||
WelcomeEnterpriseJob.perform_later(id)
|
||||
end
|
||||
|
||||
def strip_url(url)
|
||||
|
||||
@@ -178,7 +178,7 @@ module Spree
|
||||
end
|
||||
|
||||
def included_tax
|
||||
adjustments.included_tax.sum(&:included_tax)
|
||||
adjustments.included_tax.sum(:included_tax)
|
||||
end
|
||||
|
||||
def tax_rates
|
||||
|
||||
@@ -466,7 +466,7 @@ module Spree
|
||||
def deliver_order_confirmation_email
|
||||
return if subscription.present?
|
||||
|
||||
Delayed::Job.enqueue ConfirmOrderJob.new(id)
|
||||
ConfirmOrderJob.perform_later(id)
|
||||
end
|
||||
|
||||
# Helper methods for checkout steps
|
||||
@@ -729,15 +729,15 @@ module Spree
|
||||
end
|
||||
|
||||
def shipping_tax
|
||||
adjustments(:reload).shipping.sum(&:included_tax)
|
||||
adjustments(:reload).shipping.sum(:included_tax)
|
||||
end
|
||||
|
||||
def enterprise_fee_tax
|
||||
adjustments(:reload).enterprise_fee.sum(&:included_tax)
|
||||
adjustments(:reload).enterprise_fee.sum(:included_tax)
|
||||
end
|
||||
|
||||
def total_tax
|
||||
(adjustments + price_adjustments).sum(&:included_tax)
|
||||
(adjustments.to_a + price_adjustments.to_a).sum(&:included_tax)
|
||||
end
|
||||
|
||||
def price_adjustments
|
||||
|
||||
@@ -34,7 +34,7 @@ module Spree
|
||||
klass = self
|
||||
|
||||
# To avoid a ton of warnings when the state machine is re-defined
|
||||
StateMachine::Machine.ignore_method_conflicts = true
|
||||
StateMachines::Machine.ignore_method_conflicts = true
|
||||
# To avoid multiple occurrences of the same transition being defined
|
||||
# On first definition, state_machines will not be defined
|
||||
state_machines.clear if respond_to?(:state_machines)
|
||||
|
||||
@@ -98,7 +98,7 @@ module Spree
|
||||
end
|
||||
|
||||
def init
|
||||
unless reflections.key?(:calculator)
|
||||
unless _reflections.key?(:calculator)
|
||||
self.class.include Spree::Core::CalculatedAdjustments
|
||||
end
|
||||
|
||||
|
||||
@@ -61,6 +61,8 @@ module Spree
|
||||
end
|
||||
|
||||
def delete(key)
|
||||
return if key.nil?
|
||||
|
||||
@cache.delete(key)
|
||||
destroy(key)
|
||||
end
|
||||
|
||||
@@ -95,6 +95,7 @@ module Spree
|
||||
validates :tax_category_id, presence: true, if: "Spree::Config.products_require_tax_category"
|
||||
|
||||
validates :variant_unit, presence: true
|
||||
validates :unit_value, presence: { if: ->(p) { %w(weight volume).include? p.variant_unit } }
|
||||
validates :variant_unit_scale,
|
||||
presence: { if: ->(p) { %w(weight volume).include? p.variant_unit } }
|
||||
validates :variant_unit_name,
|
||||
|
||||
@@ -15,7 +15,7 @@ module Spree
|
||||
# may still be in an active cart after it's deleted, so this will mark it as out of stock.
|
||||
return 0 if @variant.deleted?
|
||||
|
||||
stock_items.sum(&:count_on_hand)
|
||||
stock_items.sum(:count_on_hand)
|
||||
end
|
||||
|
||||
def backorderable?
|
||||
|
||||
@@ -58,9 +58,11 @@ module Spree
|
||||
has_spree_role?('admin')
|
||||
end
|
||||
|
||||
# handle_asynchronously will define send_reset_password_instructions_with_delay.
|
||||
# If handle_asynchronously is called twice, we get an infinite job loop.
|
||||
handle_asynchronously :send_reset_password_instructions unless method_defined? :send_reset_password_instructions_with_delay
|
||||
# Send devise-based user emails asyncronously via ActiveJob
|
||||
# See: https://github.com/heartcombo/devise/tree/v3.5.10#activejob-integration
|
||||
def send_devise_notification(notification, *args)
|
||||
devise_mailer.public_send(notification, self, *args).deliver_later
|
||||
end
|
||||
|
||||
def regenerate_reset_password_token
|
||||
set_reset_password_token
|
||||
@@ -72,6 +74,7 @@ module Spree
|
||||
else
|
||||
Spree::User
|
||||
.includes(:enterprises)
|
||||
.references(:enterprises)
|
||||
.where("enterprises.id IN (SELECT enterprise_id FROM enterprise_roles WHERE user_id = ?)",
|
||||
id)
|
||||
end
|
||||
@@ -100,7 +103,7 @@ module Spree
|
||||
end
|
||||
|
||||
def send_signup_confirmation
|
||||
Delayed::Job.enqueue ConfirmSignupJob.new(id)
|
||||
ConfirmSignupJob.perform_later(id)
|
||||
end
|
||||
|
||||
def associate_customers
|
||||
|
||||
@@ -136,7 +136,7 @@ module Spree
|
||||
end
|
||||
|
||||
def self.indexed
|
||||
scoped.index_by(&:id)
|
||||
where(nil).index_by(&:id)
|
||||
end
|
||||
|
||||
def self.active(currency = nil)
|
||||
|
||||
@@ -16,7 +16,7 @@ module Api
|
||||
end
|
||||
|
||||
def item_count
|
||||
object.line_items.sum(&:quantity)
|
||||
object.line_items.sum(:quantity)
|
||||
end
|
||||
|
||||
def completed_at
|
||||
|
||||
@@ -6,17 +6,8 @@ class BulkInvoiceService
|
||||
end
|
||||
|
||||
def start_pdf_job(order_ids)
|
||||
pdf = CombinePDF.new
|
||||
|
||||
orders_from(order_ids).each do |order|
|
||||
invoice = renderer.render_to_string(order)
|
||||
|
||||
pdf << CombinePDF.parse(invoice)
|
||||
end
|
||||
|
||||
pdf.save "#{file_directory}/#{@id}.pdf"
|
||||
BulkInvoiceJob.perform_later order_ids, "#{file_directory}/#{@id}.pdf"
|
||||
end
|
||||
handle_asynchronously :start_pdf_job
|
||||
|
||||
def invoice_created?(invoice_id)
|
||||
File.exist? filepath(invoice_id)
|
||||
@@ -28,10 +19,6 @@ class BulkInvoiceService
|
||||
|
||||
private
|
||||
|
||||
def orders_from(order_ids)
|
||||
Spree::Order.where(id: order_ids).order("completed_at DESC")
|
||||
end
|
||||
|
||||
def new_invoice_id
|
||||
Time.zone.now.to_i.to_s
|
||||
end
|
||||
@@ -40,10 +27,6 @@ class BulkInvoiceService
|
||||
'tmp/invoices'
|
||||
end
|
||||
|
||||
def renderer
|
||||
@renderer ||= InvoiceRenderer.new
|
||||
end
|
||||
|
||||
def file_directory
|
||||
Dir.mkdir(directory) unless File.exist?(directory)
|
||||
directory
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
class InvoiceRenderer
|
||||
def render_to_string(order)
|
||||
renderer.instance_variable_set(:@order, order)
|
||||
renderer.render_to_string(args(order))
|
||||
end
|
||||
|
||||
@@ -8,15 +9,14 @@ class InvoiceRenderer
|
||||
pdf: "invoice-#{order.number}.pdf",
|
||||
template: invoice_template,
|
||||
formats: [:html],
|
||||
encoding: "UTF-8",
|
||||
locals: { :@order => order }
|
||||
encoding: "UTF-8"
|
||||
}
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def renderer
|
||||
ApplicationController.new
|
||||
@renderer ||= ApplicationController.new
|
||||
end
|
||||
|
||||
def invoice_template
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# This class allows orders with eager-loaded adjustment objects to calculate various adjustment
|
||||
# types without triggering additional queries.
|
||||
#
|
||||
# For example; `order.adjustments.shipping.sum(&:amount)` would normally trigger a new query
|
||||
# For example; `order.adjustments.shipping.sum(:amount)` would normally trigger a new query
|
||||
# regardless of whether or not adjustments have been preloaded, as `#shipping` is an adjustment
|
||||
# scope, eg; `scope :shipping, where(originator_type: 'Spree::ShippingMethod')`.
|
||||
#
|
||||
|
||||
@@ -9,19 +9,19 @@ module PermittedAttributes
|
||||
def call
|
||||
return @params[:enterprise] if @params[:enterprise].blank?
|
||||
|
||||
@params.require(:enterprise).permit(
|
||||
basic_permitted_attributes + [
|
||||
group_ids: [], user_ids: [],
|
||||
shipping_method_ids: [], payment_method_ids: [],
|
||||
address_attributes: PermittedAttributes::Address.attributes,
|
||||
producer_properties_attributes: [:id, :property_name, :value, :_destroy]
|
||||
]
|
||||
)
|
||||
@params.require(:enterprise).permit(self.class.attributes)
|
||||
end
|
||||
|
||||
private
|
||||
def self.attributes
|
||||
basic_permitted_attributes + [
|
||||
group_ids: [], user_ids: [],
|
||||
shipping_method_ids: [], payment_method_ids: [],
|
||||
address_attributes: PermittedAttributes::Address.attributes,
|
||||
producer_properties_attributes: [:id, :property_name, :value, :_destroy]
|
||||
]
|
||||
end
|
||||
|
||||
def basic_permitted_attributes
|
||||
def self.basic_permitted_attributes
|
||||
[
|
||||
:id, :name, :visible, :permalink, :owner_id, :contact_name, :email_address, :phone,
|
||||
:is_primary_producer, :sells, :website, :facebook, :instagram, :linkedin, :twitter,
|
||||
|
||||
16
app/services/permitted_attributes/tag_rules.rb
Normal file
16
app/services/permitted_attributes/tag_rules.rb
Normal file
@@ -0,0 +1,16 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module PermittedAttributes
|
||||
class TagRules
|
||||
def self.attributes
|
||||
[
|
||||
:id, :type, :priority, :is_default, :preferred_customer_tags, :preferred_exchange_tags,
|
||||
:preferred_matched_order_cycles_visibility, :preferred_shipping_method_tags,
|
||||
:preferred_matched_shipping_methods_visibility, :preferred_payment_method_tags,
|
||||
:preferred_matched_payment_methods_visibility, :preferred_variant_tags,
|
||||
:preferred_matched_variants_visibility, :calculator_type,
|
||||
{ calculator_attributes: [:id, :preferred_flat_percent] }
|
||||
]
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -8,7 +8,8 @@
|
||||
.four.columns
|
||||
= f.field_container :included_tax do
|
||||
= f.label :included_tax, t(:included_tax)
|
||||
= text_field :adjustment, :included_tax, disabled: true, class: 'fullwidth'
|
||||
= f.text_field :included_tax, disabled: true, class: 'fullwidth',
|
||||
value: number_with_precision(f.object.included_tax, precision: 2)
|
||||
= f.error_message_on :included_tax
|
||||
|
||||
.omega.four.columns
|
||||
|
||||
@@ -199,5 +199,9 @@ module Openfoodnetwork
|
||||
config.assets.precompile += ['*.jpg', '*.jpeg', '*.png', '*.gif' '*.svg']
|
||||
|
||||
config.active_support.escape_html_entities_in_json = true
|
||||
|
||||
config.active_job.queue_adapter = :delayed_job
|
||||
|
||||
config.active_record.raise_in_transactional_callbacks = true
|
||||
end
|
||||
end
|
||||
|
||||
@@ -44,7 +44,7 @@ Openfoodnetwork::Application.configure do
|
||||
# Use a different cache store in production
|
||||
memcached_value_max_megabytes = ENV.fetch("MEMCACHED_VALUE_MAX_MEGABYTES", 1).to_i
|
||||
memcached_value_max_bytes = memcached_value_max_megabytes * 1024 * 1024
|
||||
config.cache_store = :dalli_store, { value_max_bytes: memcached_value_max_bytes }
|
||||
config.cache_store = :mem_cache_store, { value_max_bytes: memcached_value_max_bytes }
|
||||
|
||||
# Enable serving of images, stylesheets, and JavaScripts from an asset server
|
||||
# config.action_controller.asset_host = "http://assets.example.com"
|
||||
|
||||
@@ -44,7 +44,7 @@ Openfoodnetwork::Application.configure do
|
||||
# Use a different cache store in production
|
||||
memcached_value_max_megabytes = ENV.fetch("MEMCACHED_VALUE_MAX_MEGABYTES", 1).to_i
|
||||
memcached_value_max_bytes = memcached_value_max_megabytes * 1024 * 1024
|
||||
config.cache_store = :dalli_store, { value_max_bytes: memcached_value_max_bytes }
|
||||
config.cache_store = :mem_cache_store, { value_max_bytes: memcached_value_max_bytes }
|
||||
|
||||
# Enable serving of images, stylesheets, and JavaScripts from an asset server
|
||||
# config.action_controller.asset_host = "http://assets.example.com"
|
||||
|
||||
@@ -51,6 +51,8 @@ Openfoodnetwork::Application.configure do
|
||||
require 'open_food_network/rack_request_blocker'
|
||||
# Make sure the middleware is inserted first in middleware chain
|
||||
config.middleware.insert_before('ActionDispatch::Static', 'RackRequestBlocker')
|
||||
|
||||
config.active_job.queue_adapter = :test
|
||||
end
|
||||
|
||||
# Allows us to use _url helpers in Rspec
|
||||
|
||||
15
config/initializers/paranoia.rb
Normal file
15
config/initializers/paranoia.rb
Normal file
@@ -0,0 +1,15 @@
|
||||
module Paranoia
|
||||
def paranoia_delete
|
||||
raise ActiveRecord::ReadOnlyRecord, "#{self.class} is marked as readonly" if readonly?
|
||||
if persisted?
|
||||
# if a transaction exists, add the record so that after_commit
|
||||
# callbacks can be run
|
||||
add_to_transaction unless self.class.connection.current_transaction.closed?
|
||||
update_columns(paranoia_destroy_attributes)
|
||||
elsif !frozen?
|
||||
assign_attributes(paranoia_destroy_attributes)
|
||||
end
|
||||
self
|
||||
end
|
||||
alias_method :delete, :paranoia_delete
|
||||
end
|
||||
@@ -3,11 +3,16 @@
|
||||
# Your secret key for verifying the integrity of signed cookies.
|
||||
# If you change this key, all old signed cookies will become invalid!
|
||||
# Make sure the secret is at least 30 characters and all random,
|
||||
# no regular words or you'll be exposed to dictionary attacks.
|
||||
Openfoodnetwork::Application.config.secret_token = if Rails.env.development? or Rails.env.test?
|
||||
# no regular words or you'll be exposed to dictionary attacks.
|
||||
|
||||
secret_key = if Rails.env.development? or Rails.env.test?
|
||||
('x' * 30) # Meets basic minimum of 30 chars.
|
||||
else
|
||||
ENV["SECRET_TOKEN"]
|
||||
end
|
||||
|
||||
Openfoodnetwork::Application.config.secret_key_base = 'ceb1eb86c50285e696f899b2e7ea306d1ec1e81fe5c7af0e5cbc238bebe3fd60f19df7b9076fab836182821ebe14e41b64bdcdb4370520dc5bb711c1bc0ae616'
|
||||
# Rails 4+ key for signing and encrypting cookies.
|
||||
Openfoodnetwork::Application.config.secret_key_base = secret_key
|
||||
|
||||
# Legacy secret_token variable. This is still used directly for encryption.
|
||||
Openfoodnetwork::Application.config.secret_token = secret_key
|
||||
|
||||
@@ -1282,13 +1282,13 @@ ar:
|
||||
footer_logo: "الشعار (220 × 76)"
|
||||
footer_facebook_url: "رابط الفيسبوك"
|
||||
footer_twitter_url: "رابط تويتر"
|
||||
footer_instagram_url: "عنوان انستغرام"
|
||||
footer_instagram_url: "رابط انستغرام"
|
||||
footer_linkedin_url: "رابط لينكدن"
|
||||
footer_googleplus_url: "رابط جوجل بلس"
|
||||
footer_pinterest_url: "رابط بنتيريست"
|
||||
footer_email: "البريد الإلكتروني"
|
||||
footer_links_md: "الروابط"
|
||||
footer_about_url: "حول الرابط "
|
||||
footer_about_url: "رابط نحن"
|
||||
user_guide_link: "رابط دليل المستخدم"
|
||||
name: اسم
|
||||
first_name: الاسم الاول
|
||||
@@ -3006,7 +3006,7 @@ ar:
|
||||
landing_page: "الصفحة المقصودة"
|
||||
server: "الخادم"
|
||||
test_mode: "وضع الاختبار"
|
||||
logourl: "وحدة"
|
||||
logourl: "رابط الشعار"
|
||||
are_you_sure_delete: "هل أنت متأكد أنك تريد حذف هذا السجل؟"
|
||||
confirm_delete: "تأكيد الحذف"
|
||||
configurations: "تهيئة"
|
||||
@@ -3472,10 +3472,10 @@ ar:
|
||||
edit:
|
||||
legal_settings: "الإعدادات القانونية"
|
||||
cookies_consent_banner_toggle: "عرض راية موافقة ملفات تعريف الارتباط"
|
||||
privacy_policy_url: "URL سياسة الخصوصية"
|
||||
privacy_policy_url: "رابط سياسة الخصوصية"
|
||||
enterprises_require_tos: "يجب على المؤسسات قبول شروط الخدمة"
|
||||
cookies_policy_matomo_section: "عرض قسم Matomo في صفحة سياسة ملفات تعريف الارتباط"
|
||||
footer_tos_url: "شروط الخدمة URL"
|
||||
footer_tos_url: "رابط شروط الخدمة "
|
||||
checkout:
|
||||
payment:
|
||||
stripe:
|
||||
@@ -3492,7 +3492,7 @@ ar:
|
||||
remember_this_card: تذكر هذه البطاقة؟
|
||||
date_picker:
|
||||
format: '٪ س-٪ م-%d'
|
||||
js_format: 'يوم-شهر-سنة'
|
||||
js_format: 'yy-mm-dd'
|
||||
orders:
|
||||
error_flash_for_unavailable_items: "عنصر في سلة التسوق الخاصة بك أصبح غير متوفر. يرجى تحديث الكميات المحددة."
|
||||
edit:
|
||||
|
||||
@@ -3446,7 +3446,7 @@ en_GB:
|
||||
order_summary_canceled_html: "<strong>Order Summary #%{number} [CANCELED]</strong>"
|
||||
details: "Here are the details of what you ordered:"
|
||||
unpaid_order: "Your order was unpaid so no refund has been made"
|
||||
paid_order: "Your order was paid so %{distributor} has refunded the full amount"
|
||||
paid_order: "Your order was paid so %{distributor} will refund the full amount. Please don't hesitate to get in touch to notify them that you cancelled your order. Many business reconcile payments at the end of the month but will happily issue refunds sooner, if they are aware you are waiting."
|
||||
credit_order: "Your order was paid so your account has been credited"
|
||||
subject: "Cancellation of Order"
|
||||
confirm_email:
|
||||
|
||||
@@ -289,11 +289,16 @@ en_NZ:
|
||||
create_and_add_another: "Create and Add Another"
|
||||
create: "Create"
|
||||
cancel: "Cancel"
|
||||
resume: "Resume"
|
||||
save: "Save"
|
||||
edit: "Edit"
|
||||
update: "Update"
|
||||
delete: "Delete"
|
||||
add: "Add"
|
||||
cut: "Cut"
|
||||
paste: "Paste"
|
||||
destroy: "Destroy"
|
||||
rename: "Rename"
|
||||
admin:
|
||||
begins_at: Begins At
|
||||
begins_on: Begins On
|
||||
@@ -601,6 +606,8 @@ en_NZ:
|
||||
controls:
|
||||
back_to_my_inventory: Back to my inventory
|
||||
orders:
|
||||
edit:
|
||||
order_sure_want_to: Are you sure you want to %{event} this order?
|
||||
invoice_email_sent: 'Invoice email has been sent'
|
||||
order_email_resent: 'Order email has been resent'
|
||||
bulk_management:
|
||||
@@ -2877,6 +2884,8 @@ en_NZ:
|
||||
delete: "Delete"
|
||||
cannot_set_shipping_method_without_address: "Cannot set shipping method until customer details are provided."
|
||||
no_tracking_present: "No tracking details provided."
|
||||
tracking: "Tracking"
|
||||
tracking_number: "Tracking Number"
|
||||
order_total: "Order Total"
|
||||
customer_details: "Customer Details"
|
||||
customer_search: "Customer Search"
|
||||
@@ -2910,6 +2919,8 @@ en_NZ:
|
||||
server: "Server"
|
||||
test_mode: "Test Mode"
|
||||
logourl: "Logourl"
|
||||
are_you_sure_delete: "Are you sure you want to delete this record?"
|
||||
confirm_delete: "Confirm Deletion"
|
||||
configurations: "Configurations"
|
||||
general_settings: "General Settings"
|
||||
site_name: "Site Name"
|
||||
|
||||
@@ -2884,6 +2884,8 @@ en_US:
|
||||
delete: "Delete"
|
||||
cannot_set_shipping_method_without_address: "Cannot set shipping method until customer details are provided."
|
||||
no_tracking_present: "No tracking details provided."
|
||||
tracking: "Tracking"
|
||||
tracking_number: "Tracking Number"
|
||||
order_total: "Order Total"
|
||||
customer_details: "Customer Details"
|
||||
customer_search: "Customer Search"
|
||||
|
||||
@@ -829,17 +829,17 @@ pt_BR:
|
||||
owner: Proprietário
|
||||
producer: Produtor
|
||||
change_type_form:
|
||||
producer_profile: Perfil do produtor
|
||||
producer_profile: Perfil Simples
|
||||
connect_ofn: Conecte-se através da OFB
|
||||
always_free: SEMPRE GRATUITO
|
||||
producer_description_text: Adicione os seus produtos à Open Food Brasil, permitindo que as centrais os comercialize em suas lojas.
|
||||
producer_shop: Loja do produtor
|
||||
producer_shop: Loja de Produtor
|
||||
sell_your_produce: 'Venda seus próprios produtos '
|
||||
producer_shop_description_text: Venda seus produtos diretamente aos compradores através da sua própria loja virtual na Open Food Brasil.
|
||||
producer_shop_description_text2: Uma loja de produtor é apenas para o seu produto, se você quiser vender produtos produzidos por outras pessoas ou locais, selecione 'Central de produtor'.
|
||||
producer_shop_description_text2: Uma Loja de Produtor vende ou distribui apenas produtos próprios. Se você quiser vender produtos produzidos por outras pessoas ou iniciativas, selecione 'Central de Produtor'.
|
||||
producer_hub: Central de produtor
|
||||
producer_hub_text: Comercialize seus próprios produtos e de outros produtores
|
||||
producer_hub_description_text: Sua iniciativa é a espinha dorsal do seu sistema de produção e consumo local. Você pode comercializar seus próprios bens, assim como produtos agregados de outras iniciativas e produtores, através da sua loja na Open Food Brasil.
|
||||
producer_hub_description_text: Escolha este tipo de perfil se a sua iniciativa funciona como um intermediário, ou seja, ela vende / distribui produtos seus e de outros produtores também
|
||||
profile: Perfil Simples
|
||||
get_listing: Obter uma listagem
|
||||
profile_description_text: As pessoas podem te encontrar e te contactar na Open Food Brasil. Sua iniciativa estará visível no mapa e poderá ser encontrada em buscas.
|
||||
@@ -874,7 +874,7 @@ pt_BR:
|
||||
next_step: Próximo passo
|
||||
choose_starting_point: 'Escolha o seu tipo de perfil:'
|
||||
profile: 'Perfil'
|
||||
producer_profile: 'Perfil do produtor'
|
||||
producer_profile: 'Perfil Simples'
|
||||
invite_manager:
|
||||
user_already_exists: "Usuário já existe"
|
||||
error: "Algo deu errado"
|
||||
@@ -1015,10 +1015,10 @@ pt_BR:
|
||||
unitsize: Unidade de Medida
|
||||
total: TOTAL
|
||||
total_items: TOTAL DE ITEMS
|
||||
supplier_totals: Total do fornecedor do ciclo de pedidos
|
||||
supplier_totals_by_distributor: Total do fornecedor do ciclo de pedidos por distribuidor
|
||||
totals_by_supplier: Total do distribuidor do ciclo da pedidos pelo fornecedor
|
||||
customer_totals: Total do consumidor do ciclo de pedidos
|
||||
supplier_totals: 'Fechamento do Ciclo: por Fornecedor'
|
||||
supplier_totals_by_distributor: 'Fechamento do Ciclo: por Fornecedor / Distribuidor'
|
||||
totals_by_supplier: 'Fechamento do Ciclo: por Distribuidor / Fornecedor'
|
||||
customer_totals: 'Fechamento do Ciclo: por Consumidor'
|
||||
all_products: Todos os produtos
|
||||
inventory: Inventário (disponível)
|
||||
lettuce_share: LettuceShare
|
||||
@@ -1198,8 +1198,8 @@ pt_BR:
|
||||
mobile_menu:
|
||||
cart: "Carrinho"
|
||||
register_call:
|
||||
selling_on_ofn: "Interessado em registrar a sua iniciativa na Open Food Brasil?"
|
||||
register: "Registre-se aqui"
|
||||
selling_on_ofn: "Quer fazer parte da Open Food Brasil?"
|
||||
register: "Registre aqui a sua iniciativa"
|
||||
footer:
|
||||
footer_secure: "Seguro e confiável."
|
||||
footer_secure_text: "A Open Food Brasil utiliza a criptografia SSL (2048 bit RSA) para manter suas informações em segurança. Nossos servidores não guardam os detalhes do seu cartão de crédito e os pagamentos são processados por serviços compatíveis com PCI."
|
||||
@@ -1812,7 +1812,7 @@ pt_BR:
|
||||
steps:
|
||||
introduction:
|
||||
registration_greeting: "Olá!"
|
||||
registration_intro: "Você pode criar um perfil de produtor ou central"
|
||||
registration_intro: "Vamos criar um perfil para a sua iniciativa? "
|
||||
registration_checklist: "O que eu preciso?"
|
||||
registration_time: "5-10 minutos"
|
||||
registration_enterprise_address: "Endereço da iniciativa"
|
||||
@@ -1822,14 +1822,14 @@ pt_BR:
|
||||
registration_about_us: "'Sobre Nós'"
|
||||
registration_outcome_headline: "O que eu ganho?"
|
||||
registration_outcome1_html: "Seu perfil ajuda as pessoas a te <strong>encontrarem</strong> e entrarem em <strong>contato</strong> com você na Open Food Brasil."
|
||||
registration_outcome2: "Use esse espaço para contar a história da sua iniciativa e ajudar a impulsionar as conexões com sua presença social e online."
|
||||
registration_outcome3: "Esse é também o primeiro passo para começar a comercializar na Open Food Brasil, ou abrir uma loja online."
|
||||
registration_outcome2: "Use esse espaço para contar a história da sua iniciativa e divulgar o seu trabalho."
|
||||
registration_outcome3: "Esse é também o primeiro passo para começar a fornecer ou comercializar seus produtos na Open Food Brasil."
|
||||
registration_action: "Vamos começar!"
|
||||
details:
|
||||
title: "Detalhes"
|
||||
headline: "Vamos começar"
|
||||
enterprise: "Woot! Primeiro, você precisa conhecer um pouco da sua empresa:"
|
||||
producer: "Primeiro precisamos saber mais sobre sua produção:"
|
||||
enterprise: "Boa! Primeiro, precisamos saber um pouco mais sobre a sua iniciativa:"
|
||||
producer: "Boa! Primeiro, precisamos saber um pouco mais sobre a sua produção:"
|
||||
enterprise_name_field: "Nome da iniciativa:"
|
||||
producer_name_field: "Nome da Produção"
|
||||
producer_name_field_placeholder: "ex. Fazenda da Nina"
|
||||
@@ -1863,9 +1863,9 @@ pt_BR:
|
||||
yes_producer: "Sim, sou um produtor"
|
||||
no_producer: "Não, não sou um produtor"
|
||||
producer_field_error: "Por favor escolha um. Você é um produtor?"
|
||||
yes_producer_help: "Produtores fazem coisas deliciosas de comer e beber. "
|
||||
yes_producer_help: "Produtores são aqueles que cultivam, colhem, beneficiam, cozinham, preparam e produzem alimentos e/ou produtos artesanais. "
|
||||
no_producer_help: "Se você não é um produtor, você provavelmente é alguém que vende e distribui alimentos. Você pode ser uma cooperativa, grupo de consumo, varejista, atacadista ou outro. Nos referimos a você como central, já que centraliza pessoas e produtos, independente do modelo organizacional. "
|
||||
create_profile: "Crir perfil"
|
||||
create_profile: "Criar perfil"
|
||||
about:
|
||||
title: "Sobre"
|
||||
headline: "Boa!"
|
||||
@@ -2468,15 +2468,14 @@ pt_BR:
|
||||
profile_only_text3: >
|
||||
Adicione seus produtos à Open Food Brasil, permitindo que as centrais
|
||||
armazenem seus produtos em suas lojas.
|
||||
producer_shop: Loja do produtor
|
||||
producer_shop: Loja de Produtor
|
||||
producer_shop_text1: >
|
||||
Venda os seus produtos diretamente aos compradores através da sua própria
|
||||
loja na Open Food Brasil.
|
||||
producer_shop_text2: >
|
||||
Uma loja de produtor é individual, somente para comercialização de produtos
|
||||
feitos por você. Se quiser vender bens produzidos em outros lugares
|
||||
e/ou pessoas, para além dos seus próprios, por favor selecione 'Central
|
||||
de Produtor'.
|
||||
Uma Loja de Produtor comercializa ou distribui somente produções próprias.
|
||||
Se quiser movimentar bens produzidos por outras pessoas ou iniciativas,
|
||||
além dos seus próprios, por favor selecione 'Central de Produtor'.
|
||||
producer_hub: Central de produtor
|
||||
producer_hub_text1: >
|
||||
A sua iniciativa é a espinha dorsal do seu sistema de produção e consumo
|
||||
@@ -2498,8 +2497,8 @@ pt_BR:
|
||||
enterprise_producer:
|
||||
producer: Produtor
|
||||
producer_text1: >
|
||||
Os produtores fazem coisas deliciosas para comer ou beber. Você é um
|
||||
produtor se você cultiva, cria, prepara, cozinha, fermenta, ou ordenha.
|
||||
Produtores são aqueles que cultivam, colhem, beneficiam, cozinham, preparam
|
||||
e produzem alimentos e/ou produtos artesanais.
|
||||
producer_text2: >
|
||||
Os produtores também podem desempenhar outras funções, como agregar
|
||||
alimentos de outras iniciativas e vendê-lo através de uma loja da Open
|
||||
|
||||
1187
db/schema.rb
1187
db/schema.rb
File diff suppressed because it is too large
Load Diff
13
dependabot.yml
Normal file
13
dependabot.yml
Normal file
@@ -0,0 +1,13 @@
|
||||
version: 2
|
||||
updates:
|
||||
|
||||
- package-ecosystem: "bundler"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
open-pull-requests-limit: 10
|
||||
|
||||
- package-ecosystem: "yarn"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
@@ -49,6 +49,7 @@ If you are using Windows and having issues related to the ruby-build not finding
|
||||
* docker/build: This script builds the Docker containers specified for this app, seeds the database, and logs the screen output for these operations. After you use "git clone" to download this repository, run the docker/build script to start the setup process.
|
||||
* docker/server: Use this script to run this app in the Rails server. This script executes the "docker-compose up" command and logs the results. If all goes well, you will be able to view this app on your local browser at http://localhost:3000/.
|
||||
* docker/test: Use this script to run the entire test suite.
|
||||
* docker/qtest: Use this script to run the entire test suite in quiet mode. The deprecation warnings are removed to make the test results easier to read.
|
||||
* docker/run: Use this script to run commands within the Docker container. If you want shell access, enter "docker/run bash". To execute "ls -l" within the Docker container, enter "docker/run ls -l".
|
||||
* docker/seed: Use this script to seed the database. Please note that this process is not compatible with simultaneously running the Rails server or tests.
|
||||
* docker/nuke: Use this script to delete all Docker images and containers. This fully resets your Docker setup and is useful for making sure that the setup procedure specified for this app is complete.
|
||||
|
||||
9
docker/qtest
Executable file
9
docker/qtest
Executable file
@@ -0,0 +1,9 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
# This script runs the entire test suite AND logs the screen output.
|
||||
# This is the quiet version of docker/test.
|
||||
# The deprecation warnings that obscure the test results are omitted.
|
||||
|
||||
DATE=`date +%Y%m%d-%H%M%S-%3N`
|
||||
docker/qtest-log 2>&1 | tee log/qtest-$DATE.log
|
||||
17
docker/qtest-log
Executable file
17
docker/qtest-log
Executable file
@@ -0,0 +1,17 @@
|
||||
#!/bin/bash
|
||||
|
||||
echo '--------------------------------------------------------------'
|
||||
echo 'BEGIN: docker-compose run web bundle exec rake db:test:prepare'
|
||||
echo '--------------------------------------------------------------'
|
||||
docker-compose run web bundle exec rake db:test:prepare
|
||||
echo '------------------------------------------------------------'
|
||||
echo 'END: docker-compose run web bundle exec rake db:test:prepare'
|
||||
echo '------------------------------------------------------------'
|
||||
|
||||
echo '--------------------------------------'
|
||||
echo 'BEGIN: running test suite (quiet mode)'
|
||||
echo '--------------------------------------'
|
||||
docker-compose run web bundle exec rspec spec | grep -v 'DEPRECATION WARNING' | grep -v 'Post.includes(:comments)' | grep -v 'Currently, Active Record recognizes the table in the string' | grep -v "If you don't rely on implicit join references"
|
||||
echo '------------------------------------'
|
||||
echo 'END: running test suite (quiet mode)'
|
||||
echo '------------------------------------'
|
||||
@@ -101,10 +101,9 @@ module OrderManagement
|
||||
|
||||
def inspect
|
||||
out = "#{order} - "
|
||||
out << contents.map do |content_item|
|
||||
out.dup << contents.map do |content_item|
|
||||
"#{content_item.variant.name} #{content_item.quantity} #{content_item.state}"
|
||||
end.join('/')
|
||||
out
|
||||
end
|
||||
|
||||
def to_shipment
|
||||
|
||||
@@ -112,6 +112,13 @@ module OrderManagement
|
||||
|
||||
expect(shipment.shipping_method).to eq shipping_method
|
||||
end
|
||||
|
||||
describe "#inpsect" do
|
||||
it "prints the package contents" do
|
||||
subject.add variant, 5
|
||||
expect(subject.inspect).to match("#{variant.name} 5")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "#shipping_methods and #shipping_categories" do
|
||||
|
||||
@@ -10,7 +10,7 @@ module OrderManagement
|
||||
|
||||
subject { Packer.new(stock_location, order) }
|
||||
|
||||
before { order.line_items.first.variant.update(weight: 1) }
|
||||
before { order.line_items.first.variant.update(unit_value: 100) }
|
||||
|
||||
it 'builds a package with all the items' do
|
||||
package = subject.package
|
||||
|
||||
@@ -28,22 +28,42 @@
|
||||
# https://gist.github.com/victorblasco/f675b4cbaf9c0bc19f81
|
||||
|
||||
module ActionDispatch
|
||||
class Request
|
||||
def deep_munge(hash)
|
||||
hash.each do |_k, v|
|
||||
case v
|
||||
when Array
|
||||
v.grep(Hash) { |x| deep_munge(x) }
|
||||
v.compact!
|
||||
class Request < Rack::Request
|
||||
class Utils # :nodoc:
|
||||
mattr_accessor :perform_deep_munge
|
||||
self.perform_deep_munge = true
|
||||
|
||||
# This patch removes the next line
|
||||
# hash[k] = nil if v.empty?
|
||||
when Hash
|
||||
deep_munge(v)
|
||||
class << self
|
||||
# Remove nils from the params hash
|
||||
def deep_munge(hash, keys = [])
|
||||
return hash unless perform_deep_munge
|
||||
|
||||
hash.each do |key, value|
|
||||
deep_munge_value(key, value, keys)
|
||||
end
|
||||
|
||||
hash
|
||||
end
|
||||
|
||||
def deep_munge_value(key, value, keys)
|
||||
keys << key
|
||||
case value
|
||||
when Array
|
||||
value.grep(Hash) { |x| deep_munge(x, keys) }
|
||||
value.compact!
|
||||
|
||||
# This patch removes the following lines
|
||||
# if v.empty?
|
||||
# hash[k] = nil
|
||||
# ActiveSupport::Notifications.instrument("deep_munge.action_controller",
|
||||
# keys: keys)
|
||||
# end
|
||||
when Hash
|
||||
deep_munge(value, keys)
|
||||
end
|
||||
keys.pop
|
||||
end
|
||||
end
|
||||
|
||||
hash
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
6
lib/application_responder.rb
Normal file
6
lib/application_responder.rb
Normal file
@@ -0,0 +1,6 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class ApplicationResponder < ActionController::Responder
|
||||
include Responders::FlashResponder
|
||||
include Responders::HttpCacheResponder
|
||||
end
|
||||
@@ -60,7 +60,11 @@ module OpenFoodNetwork
|
||||
def filter_to_supplier(orders)
|
||||
if params[:supplier_id].to_i > 0
|
||||
orders.select do |order|
|
||||
order.line_items.includes(:product).where("spree_products.supplier_id = ?", params[:supplier_id].to_i).count > 0
|
||||
order.line_items.includes(:product)
|
||||
.where("spree_products.supplier_id = ?", params[:supplier_id].to_i)
|
||||
.references(:product)
|
||||
.count
|
||||
.positive?
|
||||
end
|
||||
else
|
||||
orders
|
||||
|
||||
@@ -38,7 +38,7 @@ module OpenFoodNetwork
|
||||
# Cycle thorugh variant of a product
|
||||
variant_groups = line_items_by_product.group_by(&:variant)
|
||||
variant_groups.each do |variant, line_items_by_variant|
|
||||
sum_quantities = line_items_by_variant.sum(&:quantity)
|
||||
sum_quantities = line_items_by_variant.to_a.sum(&:quantity)
|
||||
sum_max_quantities = line_items_by_variant.sum { |li| li.max_quantity || 0 }
|
||||
variants_and_quantities << GroupBuyVariantRow.new(variant, sum_quantities, sum_max_quantities)
|
||||
end
|
||||
|
||||
@@ -134,7 +134,7 @@ module OpenFoodNetwork
|
||||
proc { |line_items| line_items.first.variant.product.name },
|
||||
proc { |line_items| line_items.first.variant.full_name },
|
||||
|
||||
proc { |line_items| line_items.sum(&:quantity) },
|
||||
proc { |line_items| line_items.to_a.sum(&:quantity) },
|
||||
proc { |line_items| line_items.sum(&:amount) },
|
||||
proc { |line_items| line_items.sum(&:amount_with_adjustments) },
|
||||
proc { |_line_items| "" },
|
||||
|
||||
@@ -45,7 +45,7 @@ module OpenFoodNetwork
|
||||
supplier_name,
|
||||
product_name,
|
||||
line_items_name,
|
||||
proc { |line_items| line_items.sum(&:quantity) },
|
||||
proc { |line_items| line_items.to_a.sum(&:quantity) },
|
||||
proc { |line_items| line_items.first.price },
|
||||
proc { |line_items| line_items.sum { |li| li.quantity * li.price } },
|
||||
proc { |_line_items| "" },
|
||||
|
||||
@@ -59,7 +59,7 @@ module OpenFoodNetwork
|
||||
proc { |line_items| line_items.first.variant.product.supplier.name },
|
||||
proc { |line_items| line_items.first.variant.product.name },
|
||||
proc { |line_items| line_items.first.variant.full_name },
|
||||
proc { |line_items| line_items.sum(&:quantity) },
|
||||
proc { |line_items| line_items.to_a.sum(&:quantity) },
|
||||
proc { |line_items| line_items.first.price },
|
||||
proc { |line_items| line_items.sum(&:amount) },
|
||||
proc { |_line_items| "" },
|
||||
|
||||
@@ -60,7 +60,7 @@ module OpenFoodNetwork
|
||||
proc { |line_items| line_items.first.variant.product.name },
|
||||
proc { |line_items| line_items.first.variant.full_name },
|
||||
proc { |line_items| line_items.first.order.distributor.name },
|
||||
proc { |line_items| line_items.sum(&:quantity) },
|
||||
proc { |line_items| line_items.to_a.sum(&:quantity) },
|
||||
proc { |line_items| line_items.first.price },
|
||||
proc { |line_items| line_items.sum(&:amount) },
|
||||
proc { |_line_items| I18n.t(:report_header_shipping_method) }
|
||||
|
||||
@@ -44,7 +44,7 @@ module OpenFoodNetwork
|
||||
supplier_name,
|
||||
product_name,
|
||||
line_items_name,
|
||||
proc { |line_items| line_items.sum(&:quantity) },
|
||||
proc { |line_items| line_items.to_a.sum(&:quantity) },
|
||||
proc { |line_items| total_units(line_items) },
|
||||
proc { |line_items| line_items.first.price },
|
||||
proc { |line_items| line_items.sum(&:amount) },
|
||||
|
||||
@@ -96,18 +96,32 @@ module OpenFoodNetwork
|
||||
when "itemised_payment_totals"
|
||||
[proc { |orders| orders.first.payment_state },
|
||||
proc { |orders| orders.first.distributor.name },
|
||||
proc { |orders| orders.sum(&:item_total) },
|
||||
proc { |orders| orders.to_a.sum(&:item_total) },
|
||||
proc { |orders| orders.sum(&:ship_total) },
|
||||
proc { |orders| orders.sum(&:outstanding_balance) },
|
||||
proc { |orders| orders.sum(&:total) }]
|
||||
proc { |orders| orders.map(&:total).sum }]
|
||||
when "payment_totals"
|
||||
[proc { |orders| orders.first.payment_state },
|
||||
proc { |orders| orders.first.distributor.name },
|
||||
proc { |orders| orders.sum(&:item_total) },
|
||||
proc { |orders| orders.to_a.sum(&:item_total) },
|
||||
proc { |orders| orders.sum(&:ship_total) },
|
||||
proc { |orders| orders.sum(&:total) },
|
||||
proc { |orders| orders.sum { |o| o.payments.select { |payment| payment.completed? && (payment.payment_method.name.to_s.include? "EFT") }.sum(&:amount) } },
|
||||
proc { |orders| orders.sum { |o| o.payments.select { |payment| payment.completed? && (payment.payment_method.name.to_s.include? "PayPal") }.sum(&:amount) } },
|
||||
proc { |orders| orders.map(&:total).sum },
|
||||
proc { |orders|
|
||||
orders.sum { |o|
|
||||
o.payments.select { |payment|
|
||||
payment.completed? &&
|
||||
(payment.payment_method.name.to_s.include? "EFT")
|
||||
}.sum(&:amount)
|
||||
}
|
||||
},
|
||||
proc { |orders|
|
||||
orders.sum { |o|
|
||||
o.payments.select { |payment|
|
||||
payment.completed? &&
|
||||
(payment.payment_method.name.to_s.include? "PayPal")
|
||||
}.sum(&:amount)
|
||||
}
|
||||
},
|
||||
proc { |orders| orders.sum(&:outstanding_balance) }]
|
||||
else
|
||||
[proc { |payments| payments.first.order.payment_state },
|
||||
|
||||
@@ -101,7 +101,7 @@ module OpenFoodNetwork
|
||||
end
|
||||
|
||||
def tax_included_in(line_item)
|
||||
line_item.adjustments.sum(&:included_tax)
|
||||
line_item.adjustments.sum(:included_tax)
|
||||
end
|
||||
|
||||
def shipment_inc_vat
|
||||
|
||||
@@ -122,7 +122,7 @@ module OpenFoodNetwork
|
||||
end
|
||||
|
||||
def to_bool(value)
|
||||
ActiveRecord::ConnectionAdapters::Column.value_to_boolean(value)
|
||||
ActiveRecord::Type::Boolean.new.type_cast_from_database(value)
|
||||
end
|
||||
|
||||
def to_local_datetime(date)
|
||||
|
||||
@@ -188,32 +188,32 @@ module OpenFoodNetwork
|
||||
end
|
||||
|
||||
def total_untaxable_fees(order)
|
||||
order.adjustments.enterprise_fee.without_tax.sum(&:amount)
|
||||
order.adjustments.enterprise_fee.without_tax.sum(:amount)
|
||||
end
|
||||
|
||||
def total_taxable_fees(order)
|
||||
order.adjustments.enterprise_fee.with_tax.sum(&:amount)
|
||||
order.adjustments.enterprise_fee.with_tax.sum(:amount)
|
||||
end
|
||||
|
||||
def total_shipping(order)
|
||||
order.adjustments.shipping.sum(&:amount)
|
||||
order.adjustments.shipping.sum(:amount)
|
||||
end
|
||||
|
||||
def total_transaction(order)
|
||||
order.adjustments.payment_fee.sum(&:amount)
|
||||
order.adjustments.payment_fee.sum(:amount)
|
||||
end
|
||||
|
||||
def tax_on_shipping_s(order)
|
||||
tax_on_shipping = order.adjustments.shipping.sum(&:included_tax) > 0
|
||||
tax_on_shipping = order.adjustments.shipping.sum(:included_tax) > 0
|
||||
tax_on_shipping ? I18n.t(:report_header_gst_on_income) : I18n.t(:report_header_gst_free_income)
|
||||
end
|
||||
|
||||
def total_untaxable_admin_adjustments(order)
|
||||
order.adjustments.admin.without_tax.sum(&:amount)
|
||||
order.adjustments.admin.without_tax.sum(:amount)
|
||||
end
|
||||
|
||||
def total_taxable_admin_adjustments(order)
|
||||
order.adjustments.admin.with_tax.sum(&:amount)
|
||||
order.adjustments.admin.with_tax.sum(:amount)
|
||||
end
|
||||
|
||||
def detail?
|
||||
|
||||
@@ -4,7 +4,7 @@ module Spree
|
||||
def self.included(klass)
|
||||
klass.class_eval do
|
||||
include AbstractController::Rendering
|
||||
include AbstractController::ViewPaths
|
||||
include ActionView::ViewPaths
|
||||
include AbstractController::Callbacks
|
||||
include AbstractController::Helpers
|
||||
|
||||
@@ -13,7 +13,6 @@ module Spree
|
||||
include ActionController::Rendering
|
||||
include ActionController::ImplicitRender
|
||||
include ActionController::Rescue
|
||||
include ActionController::MimeResponds
|
||||
include ActionController::Head
|
||||
|
||||
include CanCan::ControllerAdditions
|
||||
@@ -21,8 +20,6 @@ module Spree
|
||||
|
||||
prepend_view_path Rails.root + "app/views"
|
||||
append_view_path File.expand_path("../../../app/views", File.dirname(__FILE__))
|
||||
|
||||
respond_to :json
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -10,7 +10,7 @@ require 'mail'
|
||||
require 'paperclip'
|
||||
require 'paranoia'
|
||||
require 'ransack'
|
||||
require 'state_machine'
|
||||
require 'state_machines'
|
||||
|
||||
module Spree
|
||||
mattr_accessor :user_class
|
||||
|
||||
@@ -30,6 +30,22 @@ module ActionController
|
||||
(options.delete(:responder) || Spree::Responder).call(self, resources, options)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def retrieve_collector_from_mimes(mimes = nil, &block)
|
||||
mimes ||= collect_mimes_from_class_level
|
||||
collector = Collector.new(mimes, request.variant)
|
||||
block.call(collector) if block_given?
|
||||
format = collector.negotiate_format(request)
|
||||
|
||||
if format
|
||||
_process_format(format)
|
||||
collector
|
||||
else
|
||||
raise ActionController::UnknownFormat
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
64
lib/tasks/subscriptions/debug.rake
Normal file
64
lib/tasks/subscriptions/debug.rake
Normal file
@@ -0,0 +1,64 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
# rubocop:disable Metrics/BlockLength
|
||||
namespace :ofn do
|
||||
namespace :subs do
|
||||
namespace :debug do
|
||||
desc "Print standard info about a specific Order Cycle"
|
||||
task order_cycle: :environment do
|
||||
order_cycle_id = request_order_cycle_id
|
||||
|
||||
order_cycle = OrderCycle.find_by(id: order_cycle_id)
|
||||
puts "Order Cycle #{order_cycle.name}"
|
||||
order_cycle.schedules.each do |schedule|
|
||||
puts "Schedule #{schedule.name}"
|
||||
Subscription.where(schedule_id: schedule.id).each do |subscription|
|
||||
puts
|
||||
puts "Subscription #{subscription.id}"
|
||||
puts subscription.shop.name
|
||||
puts subscription.customer.email
|
||||
puts subscription.payment_method.name
|
||||
puts "Active from #{subscription.begins_at} to #{subscription.ends_at}"
|
||||
puts "Last edited on #{subscription.updated_at}"
|
||||
puts "Canceled at #{subscription.canceled_at} and paused at #{subscription.paused_at}"
|
||||
|
||||
ProxyOrder.where(order_cycle_id: order_cycle_id,
|
||||
subscription_id: subscription.id).each do |proxy_order|
|
||||
puts
|
||||
puts "Proxy Order #{proxy_order.id}"
|
||||
puts "Canceled at #{proxy_order.canceled_at}"
|
||||
puts "Last updated at #{proxy_order.updated_at}"
|
||||
puts "Placed at #{proxy_order.placed_at}"
|
||||
puts "Confirmed at #{proxy_order.confirmed_at}"
|
||||
|
||||
puts
|
||||
puts "Order #{proxy_order.order_id} - #{proxy_order.order.number}"
|
||||
puts "Order is #{proxy_order.order.state} with total #{proxy_order.order.total}"
|
||||
proxy_order.order.payments.each do |payment|
|
||||
puts "Payment #{payment.id} with state #{payment.state}"
|
||||
puts "Amount #{payment.amount}"
|
||||
puts "Source #{payment.source_type} #{payment.source_id}"
|
||||
if payment.source_type == "Spree::CreditCard"
|
||||
puts "Source #{payment.source.to_json}"
|
||||
end
|
||||
Spree::LogEntry.where(source_type: "Spree::Payment",
|
||||
source_id: payment.id).each do |log_entry|
|
||||
puts "Log Entries found"
|
||||
puts log_entry.details
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def request_order_cycle_id
|
||||
puts "Please input Order Cycle ID to debug"
|
||||
input = STDIN.gets.chomp
|
||||
exit if input.blank? || !Integer(input)
|
||||
Integer(input)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
# rubocop:enable Metrics/BlockLength
|
||||
@@ -195,7 +195,7 @@ describe Admin::BulkLineItemsController, type: :controller do
|
||||
|
||||
it "returns an empty JSON response" do
|
||||
spree_put :update, params
|
||||
expect(response.body).to eq ' '
|
||||
expect(response.body).to eq ""
|
||||
end
|
||||
|
||||
it 'returns a 204 response' do
|
||||
@@ -273,7 +273,7 @@ describe Admin::BulkLineItemsController, type: :controller do
|
||||
|
||||
it 'returns an empty JSON response' do
|
||||
spree_delete :destroy, params
|
||||
expect(response.body).to eq ' '
|
||||
expect(response.body).to eq ""
|
||||
end
|
||||
|
||||
it 'returns a 204 response' do
|
||||
|
||||
@@ -27,6 +27,23 @@ module Spree
|
||||
spree_post :confirm, payment_method_id: payment_method.id
|
||||
expect(session[:access_token]).to eq(controller.current_order.token)
|
||||
end
|
||||
|
||||
context "if the stock ran out whilst the payment was being placed" do
|
||||
before do
|
||||
allow(controller.current_order).to receive(:insufficient_stock_lines).and_return(true)
|
||||
end
|
||||
|
||||
it "redirects to the cart with out of stock error" do
|
||||
expect(spree_post(:confirm, payment_method_id: payment_method.id)).
|
||||
to redirect_to cart_path
|
||||
|
||||
order = controller.current_order.reload
|
||||
|
||||
# Order is in "cart" state and did not complete processing of the payment
|
||||
expect(order.state).to eq "cart"
|
||||
expect(order.payments.count).to eq 0
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#expire_current_order' do
|
||||
|
||||
@@ -70,7 +70,9 @@ describe UserConfirmationsController, type: :controller do
|
||||
performing_deliveries do
|
||||
expect do
|
||||
spree_post :create, spree_user: { email: unconfirmed_user.email }
|
||||
end.to send_confirmation_instructions
|
||||
end.to enqueue_job ActionMailer::DeliveryJob
|
||||
|
||||
expect(enqueued_jobs.last.to_s).to match "confirmation_instructions"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
require 'ffaker'
|
||||
|
||||
FactoryBot.define do
|
||||
sequence(:random_string) { Faker::Lorem.sentence }
|
||||
sequence(:random_description) { Faker::Lorem.paragraphs(Kernel.rand(1..5)).join("\n") }
|
||||
sequence(:random_email) { Faker::Internet.email }
|
||||
sequence(:random_string) { FFaker::Lorem.sentence }
|
||||
sequence(:random_description) { FFaker::Lorem.paragraphs(Kernel.rand(1..5)).join("\n") }
|
||||
sequence(:random_email) { FFaker::Internet.email }
|
||||
|
||||
factory :classification, class: Spree::Classification do
|
||||
end
|
||||
@@ -112,7 +112,7 @@ FactoryBot.define do
|
||||
end
|
||||
|
||||
factory :customer, class: Customer do
|
||||
email { Faker::Internet.email }
|
||||
email { generate(:random_email) }
|
||||
enterprise
|
||||
code { SecureRandom.base64(150) }
|
||||
user
|
||||
|
||||
@@ -20,11 +20,11 @@ FactoryBot.define do
|
||||
end
|
||||
|
||||
trait :randomized do
|
||||
firstname { Faker::Name.first_name }
|
||||
lastname { Faker::Name.last_name }
|
||||
address1 { Faker::Address.street_address }
|
||||
firstname { FFaker::Name.first_name }
|
||||
lastname { FFaker::Name.last_name }
|
||||
address1 { FFaker::Address.street_address }
|
||||
address2 nil
|
||||
phone { Faker::PhoneNumber.phone_number }
|
||||
phone { FFaker::PhoneNumber.phone_number }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -112,6 +112,27 @@ feature '
|
||||
variant = product.variants.first
|
||||
expect(variant.on_demand).to be true
|
||||
end
|
||||
|
||||
scenario "creating product with empty unit value", js: true do
|
||||
login_as_admin_and_visit spree.admin_products_path
|
||||
|
||||
click_link 'New Product'
|
||||
|
||||
fill_in 'product_name', with: 'Hot Cakes'
|
||||
select 'New supplier', from: 'product_supplier_id'
|
||||
select "Weight (kg)", from: 'product_variant_unit_with_scale'
|
||||
select taxon.name, from: "product_primary_taxon_id"
|
||||
fill_in 'product_price', with: '1.99'
|
||||
fill_in 'product_on_hand', with: 0
|
||||
check 'product_on_demand'
|
||||
select 'Test Tax Category', from: 'product_tax_category_id'
|
||||
find("div[id^='taTextElement']").native.send_keys('In demand, and on_demand! The hottest cakes in town.')
|
||||
|
||||
click_button 'Create'
|
||||
|
||||
expect(current_path).to eq spree.admin_products_path
|
||||
expect(page).to have_content "Unit value can't be blank"
|
||||
end
|
||||
end
|
||||
|
||||
context "as an enterprise user" do
|
||||
|
||||
@@ -124,7 +124,7 @@ feature "Managing users" do
|
||||
# The `a` element doesn't have an href, so we can't use click_link.
|
||||
find("a", text: "Resend").click
|
||||
expect(page).to have_text "Resend done"
|
||||
end.to send_confirmation_instructions
|
||||
end.to enqueue_job ActionMailer::DeliveryJob
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -21,23 +21,23 @@ feature "Account Settings", js: true do
|
||||
end
|
||||
|
||||
it "allows the user to update their email address" do
|
||||
performing_deliveries do
|
||||
fill_in 'user_email', with: 'new@email.com'
|
||||
fill_in 'user_email', with: 'new@email.com'
|
||||
|
||||
performing_deliveries do
|
||||
expect do
|
||||
click_button I18n.t(:update)
|
||||
end.to send_confirmation_instructions
|
||||
|
||||
sent_mail = ActionMailer::Base.deliveries.last
|
||||
expect(sent_mail.to).to eq ['new@email.com']
|
||||
|
||||
expect(find(".alert-box.success").text.strip).to eq "#{I18n.t('spree.account_updated')} ×"
|
||||
user.reload
|
||||
expect(user.email).to eq 'old@email.com'
|
||||
expect(user.unconfirmed_email).to eq 'new@email.com'
|
||||
click_link I18n.t('spree.users.show.tabs.settings')
|
||||
expect(page).to have_content I18n.t('spree.users.show.unconfirmed_email', unconfirmed_email: 'new@email.com')
|
||||
end.to enqueue_job ActionMailer::DeliveryJob
|
||||
end
|
||||
|
||||
expect(enqueued_jobs.last.to_s).to match "new@email.com"
|
||||
|
||||
expect(find(".alert-box.success").text.strip).to eq "#{I18n.t('spree.account_updated')} ×"
|
||||
user.reload
|
||||
expect(user.email).to eq 'old@email.com'
|
||||
expect(user.unconfirmed_email).to eq 'new@email.com'
|
||||
click_link I18n.t('spree.users.show.tabs.settings')
|
||||
expect(page).to have_content I18n.t('spree.users.show.unconfirmed_email',
|
||||
unconfirmed_email: 'new@email.com')
|
||||
end
|
||||
|
||||
it "allows the user to change their password" do
|
||||
|
||||
@@ -82,7 +82,7 @@ feature "Authentication", js: true do
|
||||
expect do
|
||||
click_signup_button
|
||||
expect(page).to have_content I18n.t('devise.user_registrations.spree_user.signed_up_but_unconfirmed')
|
||||
end.to send_confirmation_instructions
|
||||
end.to enqueue_job ActionMailer::DeliveryJob
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -104,8 +104,9 @@ feature "Authentication", js: true do
|
||||
expect do
|
||||
click_reset_password_button
|
||||
expect(page).to have_reset_password
|
||||
end.to enqueue_job Delayed::PerformableMethod
|
||||
expect(Delayed::Job.last.payload_object.method_name).to eq(:send_reset_password_instructions_without_delay)
|
||||
end.to enqueue_job ActionMailer::DeliveryJob
|
||||
|
||||
expect(enqueued_jobs.last.to_s).to match "reset_password_instructions"
|
||||
end
|
||||
|
||||
context "user with unconfirmed email" do
|
||||
|
||||
@@ -3,6 +3,8 @@ require "spec_helper"
|
||||
feature "Check out with Paypal", js: true do
|
||||
include ShopWorkflow
|
||||
include CheckoutHelper
|
||||
include AuthenticationHelper
|
||||
include PaypalHelper
|
||||
|
||||
let(:distributor) { create(:distributor_enterprise) }
|
||||
let(:supplier) { create(:supplier_enterprise) }
|
||||
@@ -34,6 +36,7 @@ feature "Check out with Paypal", js: true do
|
||||
distributor_ids: [distributor.id]
|
||||
)
|
||||
end
|
||||
let(:user) { create(:user) }
|
||||
|
||||
before do
|
||||
distributor.shipping_methods << free_shipping
|
||||
@@ -41,23 +44,43 @@ feature "Check out with Paypal", js: true do
|
||||
add_product_to_cart order, product
|
||||
end
|
||||
|
||||
describe "as a guest" do
|
||||
context "as a guest" do
|
||||
it "fails with an error message" do
|
||||
visit checkout_path
|
||||
checkout_as_guest
|
||||
fill_out_form(free_shipping.name, paypal.name, save_default_addresses: false)
|
||||
|
||||
paypal_response = double(:response, success?: false, errors: [])
|
||||
paypal_provider = double(
|
||||
:provider,
|
||||
build_set_express_checkout: nil,
|
||||
set_express_checkout: paypal_response
|
||||
)
|
||||
allow_any_instance_of(Spree::PaypalController).to receive(:provider).
|
||||
and_return(paypal_provider)
|
||||
stub_paypal_response success: false
|
||||
|
||||
place_order
|
||||
expect(page).to have_content "PayPal failed."
|
||||
end
|
||||
end
|
||||
|
||||
context "as a registered user" do
|
||||
before { login_as user }
|
||||
|
||||
it "completes the checkout after successful Paypal payment" do
|
||||
visit checkout_path
|
||||
fill_out_details
|
||||
fill_out_form(free_shipping.name, paypal.name, save_default_addresses: false)
|
||||
|
||||
# Normally the checkout would redirect to Paypal, a form would be filled out there, and the
|
||||
# user would be redirected back to #confirm_paypal_path. Here we skip the PayPal part and
|
||||
# jump straight to being redirected back to OFN with a "confirmed" payment.
|
||||
stub_paypal_response(
|
||||
success: true,
|
||||
redirect: spree.confirm_paypal_path(
|
||||
payment_method_id: paypal.id, token: "t123", PayerID: 'p123'
|
||||
)
|
||||
)
|
||||
stub_paypal_confirm
|
||||
|
||||
place_order
|
||||
expect(page).to have_content "Your order has been processed successfully"
|
||||
|
||||
expect(order.reload.state).to eq "complete"
|
||||
expect(order.payments.count).to eq 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe HtmlHelper, type: :helper do
|
||||
describe "stripping html from a string" do
|
||||
it "strips tags" do
|
||||
expect(helper.strip_html('<p><b>Hello</b> <em>world</em>!</p>')).to eq("Hello world!")
|
||||
end
|
||||
|
||||
it "removes nbsp and amp entities" do
|
||||
expect(helper.strip_html('Hello world&&')).to eq('Hello world&&')
|
||||
end
|
||||
|
||||
it "returns nil for nil input" do
|
||||
expect(helper.strip_html(nil)).to be_nil
|
||||
end
|
||||
|
||||
describe "line breaks" do
|
||||
it "adds two line breaks after heading tags" do
|
||||
expect(helper.strip_html("<h1>foo</h1>bar")).to eq("foo\n\nbar");
|
||||
expect(helper.strip_html("<h2>foo</h2>bar")).to eq("foo\n\nbar");
|
||||
end
|
||||
|
||||
it "adds two line breaks after p tags" do
|
||||
expect(helper.strip_html("<p>foo</p>bar")).to eq("foo\n\nbar");
|
||||
end
|
||||
|
||||
it "adds two line breaks after div tags" do
|
||||
expect(helper.strip_html("<div>foo</div>bar")).to eq("foo\n\nbar");
|
||||
end
|
||||
|
||||
it "adds a line break after br tags" do
|
||||
expect(helper.strip_html("foo<br>bar")).to eq("foo\nbar");
|
||||
expect(helper.strip_html("foo<br/>bar")).to eq("foo\nbar");
|
||||
expect(helper.strip_html("foo<br />bar")).to eq("foo\nbar");
|
||||
end
|
||||
|
||||
it "strips line breaks at the end of the string" do
|
||||
expect(helper.strip_html("<div>foo</div><br />")).to eq("foo");
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -9,7 +9,7 @@ describe Spree::BaseHelper, type: :helper do
|
||||
subject { helper.link_to_remove_fields(name, form, options) }
|
||||
|
||||
it 'returns an `a` tag followed by a hidden `input` tag' do
|
||||
expect(subject).to eq("<a class=\"remove_fields icon_link with-tip icon-trash\" data-action=\"remove\" href=\"#\" title=\"Remove\"><span class='text'>Hola</span></a><input type="hidden" name="_method" value="destroy">")
|
||||
expect(subject).to eq("<a class=\"remove_fields icon_link with-tip icon-trash\" data-action=\"remove\" title=\"Remove\" href=\"#\"><span class='text'>Hola</span></a><input type="hidden" name="_method" value="destroy">")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -26,7 +26,7 @@ describe 'convert number to localised currency ', ->
|
||||
|
||||
it "can place symbols after the amount", ->
|
||||
currencyconfig.symbol_position = "after"
|
||||
expect(filter(333.3)).toEqual "333.30 $"
|
||||
expect(filter(333.3)).toEqual "333.30$"
|
||||
|
||||
it "can add a currency string", ->
|
||||
currencyconfig.display_currency = "true"
|
||||
|
||||
@@ -11,6 +11,6 @@ describe ConfirmOrderJob do
|
||||
expect(customer_confirm_fake).to receive :deliver
|
||||
expect(shop_confirm_fake).to receive :deliver
|
||||
|
||||
run_job ConfirmOrderJob.new order.id
|
||||
ConfirmOrderJob.perform_now order.id
|
||||
end
|
||||
end
|
||||
|
||||
@@ -8,6 +8,6 @@ describe ConfirmSignupJob do
|
||||
expect(Spree::UserMailer).to receive(:signup_confirmation).with(user).and_return(mail)
|
||||
expect(mail).to receive(:deliver)
|
||||
|
||||
run_job ConfirmSignupJob.new user.id
|
||||
ConfirmSignupJob.perform_now(user.id)
|
||||
end
|
||||
end
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user