mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-01-18 19:36:48 +00:00
Compare commits
108 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5d39155519 | ||
|
|
b6c9d4d6a9 | ||
|
|
0c92a594f4 | ||
|
|
4dacdb180f | ||
|
|
c1ad4243bb | ||
|
|
9f3ddfc88b | ||
|
|
67d7d225cc | ||
|
|
24edad15ae | ||
|
|
6d56a0791f | ||
|
|
cd1d77c572 | ||
|
|
2dddd625a1 | ||
|
|
5b676e8f93 | ||
|
|
5d91f5f398 | ||
|
|
62959cc883 | ||
|
|
bab4b404f4 | ||
|
|
5ecd24d66a | ||
|
|
db373a826b | ||
|
|
1ddfd2a4f7 | ||
|
|
d972f6e041 | ||
|
|
cf756c5774 | ||
|
|
4252bd0bb1 | ||
|
|
cb6e626193 | ||
|
|
77c384633b | ||
|
|
64de303b59 | ||
|
|
88cae21ab4 | ||
|
|
66e4986944 | ||
|
|
b3e08b47b9 | ||
|
|
85508f45b4 | ||
|
|
f07cc32be0 | ||
|
|
2c43522bf9 | ||
|
|
adf35f8e18 | ||
|
|
04ff4fa47c | ||
|
|
0d30e3359f | ||
|
|
b1bfac5144 | ||
|
|
30e2be13f0 | ||
|
|
dc1cdf4254 | ||
|
|
c4bd9208ce | ||
|
|
01f8aff3e0 | ||
|
|
07fd5cb29c | ||
|
|
ee7da14019 | ||
|
|
e5adbf1f08 | ||
|
|
7f9179193e | ||
|
|
3be0e1c13a | ||
|
|
18c020535a | ||
|
|
8d1fcc06fd | ||
|
|
2b6a72ffb4 | ||
|
|
157d86c94f | ||
|
|
d41de06809 | ||
|
|
d730f21dc7 | ||
|
|
49dfaa20ab | ||
|
|
bfeb892cab | ||
|
|
4b56422abd | ||
|
|
53e3e2b66d | ||
|
|
834140f0a2 | ||
|
|
0d95d83ef9 | ||
|
|
54d373c963 | ||
|
|
1dfd68c691 | ||
|
|
df9213e812 | ||
|
|
03a078a3a0 | ||
|
|
11da025247 | ||
|
|
07a9da901f | ||
|
|
4ac3853be9 | ||
|
|
eae7a9978c | ||
|
|
bdd8572fbf | ||
|
|
07422dac29 | ||
|
|
088ae496cc | ||
|
|
c83a619082 | ||
|
|
ca7d1b111a | ||
|
|
3c507c1727 | ||
|
|
b111d24488 | ||
|
|
4dc8b44e81 | ||
|
|
27a9ad7bcb | ||
|
|
fbd4d512d5 | ||
|
|
0f85db6d36 | ||
|
|
0f78b5b315 | ||
|
|
78e3bb1acd | ||
|
|
c5e1c057ae | ||
|
|
f34a3c3c02 | ||
|
|
546a32e97a | ||
|
|
abd269949d | ||
|
|
0d5f76b19e | ||
|
|
bfa77baae1 | ||
|
|
a2a1aac384 | ||
|
|
43ede7ba26 | ||
|
|
883e9fdf62 | ||
|
|
c625766af1 | ||
|
|
23730ab28f | ||
|
|
0c8bfea2f7 | ||
|
|
0306732a3d | ||
|
|
6842cbfda4 | ||
|
|
ecb4cb31ad | ||
|
|
dd47430f19 | ||
|
|
afe97bcc96 | ||
|
|
8af6fedf8a | ||
|
|
d8042b25e4 | ||
|
|
f97e71d054 | ||
|
|
d066f0b94d | ||
|
|
e9d389e4f1 | ||
|
|
325b97b683 | ||
|
|
7ab065e8cd | ||
|
|
aea0670268 | ||
|
|
cb914e4729 | ||
|
|
ab027d6af6 | ||
|
|
6a8ee544e8 | ||
|
|
b265fbf9a0 | ||
|
|
ed6b7f1ab4 | ||
|
|
4453123944 | ||
|
|
122ba385f7 |
@@ -1 +1 @@
|
||||
2.5.8
|
||||
2.5.9
|
||||
|
||||
26
Dockerfile
26
Dockerfile
@@ -7,23 +7,39 @@ RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
|
||||
RUN echo "deb http://security.ubuntu.com/ubuntu bionic-security main" >> /etc/apt/sources.list
|
||||
|
||||
# Install all the requirements
|
||||
RUN apt-get update && apt-get install -y curl git build-essential software-properties-common wget zlib1g-dev libssl1.0-dev libreadline-dev libyaml-dev libffi-dev libxml2-dev libxslt1-dev wait-for-it imagemagick unzip
|
||||
RUN apt-get update && apt-get install -y \
|
||||
curl \
|
||||
git \
|
||||
build-essential \
|
||||
software-properties-common \
|
||||
wget \
|
||||
zlib1g-dev \
|
||||
libreadline-dev \
|
||||
libyaml-dev \
|
||||
libffi-dev \
|
||||
libxml2-dev \
|
||||
libxslt1-dev \
|
||||
wait-for-it \
|
||||
imagemagick \
|
||||
unzip \
|
||||
libjemalloc-dev \
|
||||
libssl-dev
|
||||
|
||||
# Setup ENV variables
|
||||
ENV PATH /usr/local/src/rbenv/shims:/usr/local/src/rbenv/bin:$PATH
|
||||
ENV RBENV_ROOT /usr/local/src/rbenv
|
||||
ENV CONFIGURE_OPTS --disable-install-doc
|
||||
ENV BUNDLE_PATH /bundles
|
||||
ENV LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libjemalloc.so
|
||||
|
||||
WORKDIR /usr/src/app
|
||||
COPY .ruby-version .
|
||||
|
||||
# Install Rbenv & Ruby
|
||||
RUN git clone --depth 1 --branch v1.1.2 https://github.com/rbenv/rbenv.git ${RBENV_ROOT} && \
|
||||
git clone --depth 1 --branch v20200520 https://github.com/rbenv/ruby-build.git ${RBENV_ROOT}/plugins/ruby-build && \
|
||||
${RBENV_ROOT}/plugins/ruby-build/install.sh && \
|
||||
RUN git clone --depth 1 https://github.com/rbenv/rbenv.git ${RBENV_ROOT} && \
|
||||
git clone --depth 1 https://github.com/rbenv/ruby-build.git ${RBENV_ROOT}/plugins/ruby-build && \
|
||||
echo 'eval "$(rbenv init -)"' >> /etc/profile.d/rbenv.sh && \
|
||||
rbenv install $(cat .ruby-version) && \
|
||||
RUBY_CONFIGURE_OPTS=--with-jemalloc rbenv install $(cat .ruby-version) && \
|
||||
rbenv global $(cat .ruby-version) && \
|
||||
gem install bundler --version=1.17.3
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ The fastest way to make it work locally is to use Docker, you only need to setup
|
||||
Otherwise, for a local setup you will need:
|
||||
* Ruby and bundler (check current Ruby version in [.ruby-version](https://github.com/openfoodfoundation/openfoodnetwork/blob/master/.ruby-version) file)
|
||||
* PostgreSQL database
|
||||
* Redis (for background jobs)
|
||||
* Chrome (for testing)
|
||||
|
||||
The following guides will provide OS-specific step-by-step instructions to get these requirements installed:
|
||||
@@ -47,7 +48,11 @@ $ sudo -u postgres psql -c "CREATE USER ofn WITH SUPERUSER CREATEDB PASSWORD 'f0
|
||||
|
||||
This will create the "ofn" user as superuser and allowing it to create databases. If this command fails, check the [troubleshooting section](#creating-the-database) for an alternative.
|
||||
|
||||
Once done, run `script/setup`. If the script succeeds you're ready to start developing. If not, take a look at the output as it should be informative enough to help you troubleshoot.
|
||||
Next, it is _strongly recommended_ to run the setup script.
|
||||
```sh
|
||||
$ script/setup
|
||||
```
|
||||
If the script succeeds you're ready to start developing. If not, take a look at the output as it should be informative enough to help you troubleshoot.
|
||||
|
||||
Now, your dreams of spinning up a development server can be realised:
|
||||
|
||||
|
||||
27
Gemfile
27
Gemfile
@@ -1,18 +1,18 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
source 'https://rubygems.org'
|
||||
ruby "2.5.8"
|
||||
ruby "2.5.9"
|
||||
git_source(:github) { |repo_name| "https://github.com/#{repo_name}.git" }
|
||||
|
||||
gem 'rails', '~> 5.2'
|
||||
gem 'rails', '~> 6.0.3.7'
|
||||
|
||||
gem 'activemerchant', '>= 1.78.0'
|
||||
gem 'angular-rails-templates', '>= 0.3.0'
|
||||
gem 'awesome_nested_set'
|
||||
gem 'ransack', '2.4.1'
|
||||
gem 'responders'
|
||||
gem 'sass', '<= 4.7.1'
|
||||
gem 'sass-rails', '< 6.0.0'
|
||||
gem 'sass', '~> 3.4.0' # this restriction originates from foundation-rails's version
|
||||
gem 'sass-rails', '< 5.1.0' # this restriction originates from the compass-rails's version
|
||||
|
||||
gem 'i18n'
|
||||
gem 'i18n-js', '~> 3.8.3'
|
||||
@@ -20,8 +20,8 @@ gem 'rails-i18n'
|
||||
gem 'rails_safe_tasks', '~> 1.0'
|
||||
|
||||
gem "activerecord-import"
|
||||
gem "db2fog", github: "openfoodfoundation/db2fog", branch: "rails-5"
|
||||
gem "fog-aws", ">= 0.6.0"
|
||||
gem "db2fog", github: "openfoodfoundation/db2fog", branch: "rails-6"
|
||||
gem "fog-aws", "~> 2.0" # db2fog does not support v3
|
||||
|
||||
gem "catalog", path: "./engines/catalog"
|
||||
gem 'dfc_provider', path: './engines/dfc_provider'
|
||||
@@ -52,7 +52,6 @@ gem 'oauth2', '~> 1.4.7' # Used for Stripe Connect
|
||||
|
||||
gem 'daemons'
|
||||
gem 'delayed_job_active_record'
|
||||
gem 'delayed_job_web'
|
||||
|
||||
gem 'kaminari', '~> 1.2.1'
|
||||
|
||||
@@ -70,6 +69,7 @@ gem "active_model_serializers", "0.8.4"
|
||||
gem 'activerecord-session_store'
|
||||
gem 'acts-as-taggable-on', '~> 7.0'
|
||||
gem 'angularjs-file-upload-rails', '~> 2.4.1'
|
||||
gem 'bootsnap', require: false
|
||||
gem 'custom_error_message', github: 'jeremydurham/custom-err-msg'
|
||||
gem 'dalli'
|
||||
gem 'figaro'
|
||||
@@ -80,10 +80,12 @@ gem 'paper_trail', '~> 10.3.1'
|
||||
gem 'paperclip', '~> 3.4.1'
|
||||
gem 'rack-rewrite'
|
||||
gem 'rack-ssl', require: 'rack/ssl'
|
||||
gem 'roadie-rails', '~> 2.2.0'
|
||||
gem 'roadie-rails'
|
||||
|
||||
gem 'redis', '>= 4.0', require: ['redis', 'redis/connection/hiredis']
|
||||
gem 'hiredis'
|
||||
gem 'sidekiq'
|
||||
gem 'sidekiq-scheduler'
|
||||
|
||||
gem 'combine_pdf'
|
||||
gem 'wicked_pdf'
|
||||
@@ -112,6 +114,9 @@ gem 'jquery-migrate-rails'
|
||||
gem 'jquery-rails', '4.4.0'
|
||||
gem 'jquery-ui-rails', '~> 4.2'
|
||||
gem 'select2-rails', '~> 3.4.7'
|
||||
# Thor v0.20 works with both select2-rails 3.4.7 and railties 6.0.3.6
|
||||
# To upgrade to thor v1 we need to upgrade select2-rails to v3.5 which requires some work
|
||||
gem 'thor', '~> 0.20'
|
||||
|
||||
gem 'ofn-qz', github: 'openfoodfoundation/ofn-qz', branch: 'ofn-rails-4'
|
||||
|
||||
@@ -155,6 +160,7 @@ group :test do
|
||||
gem 'test-prof'
|
||||
gem 'webmock'
|
||||
gem 'rails-controller-testing'
|
||||
gem 'pdf-reader'
|
||||
# See spec/spec_helper.rb for instructions
|
||||
# gem 'perftools.rb'
|
||||
end
|
||||
@@ -171,10 +177,5 @@ group :development do
|
||||
|
||||
gem "view_component_storybook", require: "view_component/storybook/engine"
|
||||
|
||||
# 1.0.9 fixed openssl issues on macOS https://github.com/eventmachine/eventmachine/issues/602
|
||||
# While we don't require this gem directly, no dependents forced the upgrade to a version
|
||||
# greater than 1.0.9, so we just required the latest available version here.
|
||||
gem 'eventmachine', '>= 1.2.3'
|
||||
|
||||
gem 'rack-mini-profiler', '< 3.0.0'
|
||||
end
|
||||
|
||||
242
Gemfile.lock
242
Gemfile.lock
@@ -6,13 +6,13 @@ GIT
|
||||
|
||||
GIT
|
||||
remote: https://github.com/openfoodfoundation/db2fog.git
|
||||
revision: 8ceef362c64e6573d62d26db5ebb0c0f33cd3d61
|
||||
branch: rails-5
|
||||
revision: 5b63343847452f52aa42f7fc169d6ab3af57cda3
|
||||
branch: rails-6
|
||||
specs:
|
||||
db2fog (0.9.1)
|
||||
activerecord (>= 3.2.0, < 6.0)
|
||||
db2fog (0.9.2)
|
||||
activerecord (>= 3.2.0, < 7.0)
|
||||
fog-core (~> 1.0)
|
||||
rails (>= 3.2.0, < 6.0)
|
||||
rails (>= 3.2.0, < 7.0)
|
||||
|
||||
GIT
|
||||
remote: https://github.com/openfoodfoundation/ofn-qz.git
|
||||
@@ -47,47 +47,62 @@ PATH
|
||||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
actioncable (5.2.6)
|
||||
actionpack (= 5.2.6)
|
||||
Ascii85 (1.1.0)
|
||||
nio4r (~> 2.0)
|
||||
websocket-driver (>= 0.6.1)
|
||||
actionmailer (5.2.6)
|
||||
actionpack (= 5.2.6)
|
||||
actionview (= 5.2.6)
|
||||
activejob (= 5.2.6)
|
||||
actioncable (6.0.3.7)
|
||||
actionpack (= 6.0.3.7)
|
||||
nio4r (~> 2.0)
|
||||
websocket-driver (>= 0.6.1)
|
||||
actionmailbox (6.0.3.7)
|
||||
actionpack (= 6.0.3.7)
|
||||
activejob (= 6.0.3.7)
|
||||
activerecord (= 6.0.3.7)
|
||||
activestorage (= 6.0.3.7)
|
||||
activesupport (= 6.0.3.7)
|
||||
mail (>= 2.7.1)
|
||||
actionmailer (6.0.3.7)
|
||||
actionpack (= 6.0.3.7)
|
||||
actionview (= 6.0.3.7)
|
||||
activejob (= 6.0.3.7)
|
||||
mail (~> 2.5, >= 2.5.4)
|
||||
rails-dom-testing (~> 2.0)
|
||||
actionpack (5.2.6)
|
||||
actionview (= 5.2.6)
|
||||
activesupport (= 5.2.6)
|
||||
actionpack (6.0.3.7)
|
||||
actionview (= 6.0.3.7)
|
||||
activesupport (= 6.0.3.7)
|
||||
rack (~> 2.0, >= 2.0.8)
|
||||
rack-test (>= 0.6.3)
|
||||
rails-dom-testing (~> 2.0)
|
||||
rails-html-sanitizer (~> 1.0, >= 1.0.2)
|
||||
rails-html-sanitizer (~> 1.0, >= 1.2.0)
|
||||
actionpack-action_caching (1.2.2)
|
||||
actionpack (>= 4.0.0)
|
||||
actionview (5.2.6)
|
||||
activesupport (= 5.2.6)
|
||||
actiontext (6.0.3.7)
|
||||
actionpack (= 6.0.3.7)
|
||||
activerecord (= 6.0.3.7)
|
||||
activestorage (= 6.0.3.7)
|
||||
activesupport (= 6.0.3.7)
|
||||
nokogiri (>= 1.8.5)
|
||||
actionview (6.0.3.7)
|
||||
activesupport (= 6.0.3.7)
|
||||
builder (~> 3.1)
|
||||
erubi (~> 1.4)
|
||||
rails-dom-testing (~> 2.0)
|
||||
rails-html-sanitizer (~> 1.0, >= 1.0.3)
|
||||
rails-html-sanitizer (~> 1.1, >= 1.2.0)
|
||||
active_model_serializers (0.8.4)
|
||||
activemodel (>= 3.0)
|
||||
activejob (5.2.6)
|
||||
activesupport (= 5.2.6)
|
||||
activejob (6.0.3.7)
|
||||
activesupport (= 6.0.3.7)
|
||||
globalid (>= 0.3.6)
|
||||
activemerchant (1.119.0)
|
||||
activesupport (>= 4.2)
|
||||
builder (>= 2.1.2, < 4.0.0)
|
||||
i18n (>= 0.6.9)
|
||||
nokogiri (~> 1.4)
|
||||
activemodel (5.2.6)
|
||||
activesupport (= 5.2.6)
|
||||
activerecord (5.2.6)
|
||||
activemodel (= 5.2.6)
|
||||
activesupport (= 5.2.6)
|
||||
arel (>= 9.0)
|
||||
activemodel (6.0.3.7)
|
||||
activesupport (= 6.0.3.7)
|
||||
activerecord (6.0.3.7)
|
||||
activemodel (= 6.0.3.7)
|
||||
activesupport (= 6.0.3.7)
|
||||
activerecord-import (1.1.0)
|
||||
activerecord (>= 3.2)
|
||||
activerecord-postgresql-adapter (0.0.1)
|
||||
@@ -98,21 +113,24 @@ GEM
|
||||
multi_json (~> 1.11, >= 1.11.2)
|
||||
rack (>= 2.0.8, < 3)
|
||||
railties (>= 5.2.4.1)
|
||||
activestorage (5.2.6)
|
||||
actionpack (= 5.2.6)
|
||||
activerecord (= 5.2.6)
|
||||
activestorage (6.0.3.7)
|
||||
actionpack (= 6.0.3.7)
|
||||
activejob (= 6.0.3.7)
|
||||
activerecord (= 6.0.3.7)
|
||||
marcel (~> 1.0.0)
|
||||
activesupport (5.2.6)
|
||||
activesupport (6.0.3.7)
|
||||
concurrent-ruby (~> 1.0, >= 1.0.2)
|
||||
i18n (>= 0.7, < 2)
|
||||
minitest (~> 5.1)
|
||||
tzinfo (~> 1.1)
|
||||
zeitwerk (~> 2.2, >= 2.2.2)
|
||||
acts-as-taggable-on (7.0.0)
|
||||
activerecord (>= 5.0, < 6.2)
|
||||
acts_as_list (1.0.4)
|
||||
activerecord (>= 4.2)
|
||||
addressable (2.7.0)
|
||||
public_suffix (>= 2.0.2, < 5.0)
|
||||
afm (0.2.2)
|
||||
andand (1.3.3)
|
||||
angular-rails-templates (1.1.0)
|
||||
railties (>= 4.2, < 7)
|
||||
@@ -122,7 +140,6 @@ GEM
|
||||
railties (>= 3, < 7)
|
||||
angularjs-file-upload-rails (2.4.1)
|
||||
angularjs-rails (1.5.5)
|
||||
arel (9.0.0)
|
||||
ast (2.4.2)
|
||||
awesome_nested_set (3.4.0)
|
||||
activerecord (>= 4.0.0, < 7.0)
|
||||
@@ -133,6 +150,8 @@ GEM
|
||||
json (~> 1.4)
|
||||
nokogiri (~> 1)
|
||||
bcrypt (3.1.16)
|
||||
bootsnap (1.7.5)
|
||||
msgpack (~> 1.0)
|
||||
bugsnag (6.20.0)
|
||||
concurrent-ruby (~> 1.0)
|
||||
builder (3.2.4)
|
||||
@@ -184,6 +203,7 @@ GEM
|
||||
sass-rails (< 5.1)
|
||||
sprockets (< 4.0)
|
||||
concurrent-ruby (1.1.8)
|
||||
connection_pool (2.2.5)
|
||||
crack (0.4.5)
|
||||
rexml
|
||||
crass (1.0.6)
|
||||
@@ -191,7 +211,12 @@ GEM
|
||||
addressable
|
||||
daemons (1.4.0)
|
||||
dalli (2.7.11)
|
||||
database_cleaner (1.99.0)
|
||||
database_cleaner (2.0.1)
|
||||
database_cleaner-active_record (~> 2.0.0)
|
||||
database_cleaner-active_record (2.0.0)
|
||||
activerecord (>= 5.a)
|
||||
database_cleaner-core (~> 2.0.0)
|
||||
database_cleaner-core (2.0.1)
|
||||
ddtrace (0.49.0)
|
||||
ffi (~> 1.0)
|
||||
msgpack
|
||||
@@ -201,11 +226,6 @@ GEM
|
||||
delayed_job_active_record (4.1.6)
|
||||
activerecord (>= 3.0, < 6.2)
|
||||
delayed_job (>= 3.0, < 5)
|
||||
delayed_job_web (1.4.4)
|
||||
activerecord (> 3.0.0)
|
||||
delayed_job (> 2.0.3)
|
||||
rack-protection (>= 1.5.5)
|
||||
sinatra (>= 1.4.4)
|
||||
devise (4.8.0)
|
||||
bcrypt (~> 3.0)
|
||||
orm_adapter (~> 0.1)
|
||||
@@ -218,20 +238,26 @@ GEM
|
||||
devise (>= 4.0.0, < 5.0.0)
|
||||
diff-lcs (1.4.4)
|
||||
docile (1.3.5)
|
||||
e2mmap (0.1.0)
|
||||
erubi (1.10.0)
|
||||
eventmachine (1.2.7)
|
||||
excon (0.79.0)
|
||||
et-orbi (1.2.4)
|
||||
tzinfo
|
||||
excon (0.81.0)
|
||||
execjs (2.7.0)
|
||||
factory_bot (6.2.0)
|
||||
activesupport (>= 5.0.0)
|
||||
factory_bot_rails (6.2.0)
|
||||
factory_bot (~> 6.2.0)
|
||||
railties (>= 5.0.0)
|
||||
faraday (1.3.0)
|
||||
faraday (1.4.1)
|
||||
faraday-excon (~> 1.1)
|
||||
faraday-net_http (~> 1.0)
|
||||
faraday-net_http_persistent (~> 1.1)
|
||||
multipart-post (>= 1.2, < 3)
|
||||
ruby2_keywords
|
||||
ruby2_keywords (>= 0.0.4)
|
||||
faraday-excon (1.1.0)
|
||||
faraday-net_http (1.0.1)
|
||||
faraday-net_http_persistent (1.1.0)
|
||||
ffaker (2.18.0)
|
||||
ffi (1.15.0)
|
||||
figaro (1.2.0)
|
||||
@@ -267,6 +293,9 @@ GEM
|
||||
foundation-rails (5.5.2.1)
|
||||
railties (>= 3.1.0)
|
||||
sass (>= 3.3.0, < 3.5)
|
||||
fugit (1.4.5)
|
||||
et-orbi (~> 1.1, >= 1.1.8)
|
||||
raabro (~> 1.4)
|
||||
fuubar (2.5.1)
|
||||
rspec-core (~> 3.0)
|
||||
ruby-progressbar (~> 1.4)
|
||||
@@ -283,6 +312,7 @@ GEM
|
||||
temple (>= 0.8.0)
|
||||
tilt
|
||||
hashdiff (1.0.1)
|
||||
hashery (2.1.2)
|
||||
highline (2.0.3)
|
||||
hiredis (0.6.3)
|
||||
i18n (1.8.10)
|
||||
@@ -321,11 +351,11 @@ GEM
|
||||
kgio (2.11.3)
|
||||
knapsack (1.22.0)
|
||||
rake
|
||||
launchy (2.4.3)
|
||||
addressable (~> 2.3)
|
||||
launchy (2.5.0)
|
||||
addressable (~> 2.7)
|
||||
letter_opener (1.7.0)
|
||||
launchy (~> 2.2)
|
||||
libv8-node (15.14.0.0)
|
||||
libv8-node (15.14.0.1)
|
||||
loofah (2.9.1)
|
||||
crass (~> 1.0.2)
|
||||
nokogiri (>= 1.5.9)
|
||||
@@ -335,12 +365,12 @@ GEM
|
||||
method_source (1.0.0)
|
||||
mime-types (3.3.1)
|
||||
mime-types-data (~> 3.2015)
|
||||
mime-types-data (3.2020.1104)
|
||||
mime-types-data (3.2021.0225)
|
||||
mimemagic (0.4.3)
|
||||
nokogiri (~> 1)
|
||||
rake
|
||||
mini_mime (1.1.0)
|
||||
mini_portile2 (2.5.1)
|
||||
mini_portile2 (2.5.3)
|
||||
mini_racer (0.4.0)
|
||||
libv8-node (~> 15.14.0.0)
|
||||
minitest (5.14.4)
|
||||
@@ -352,10 +382,8 @@ GEM
|
||||
multi_json (1.15.0)
|
||||
multi_xml (0.6.0)
|
||||
multipart-post (2.1.1)
|
||||
mustermann (1.1.1)
|
||||
ruby2_keywords (~> 0.0.1)
|
||||
nio4r (2.5.7)
|
||||
nokogiri (1.11.4)
|
||||
nokogiri (1.11.7)
|
||||
mini_portile2 (~> 2.5.0)
|
||||
racc (~> 1.4)
|
||||
oauth2 (1.4.7)
|
||||
@@ -384,15 +412,22 @@ GEM
|
||||
xml-simple
|
||||
paypal-sdk-merchant (1.117.2)
|
||||
paypal-sdk-core (~> 0.3.0)
|
||||
pdf-reader (2.4.2)
|
||||
Ascii85 (~> 1.0)
|
||||
afm (~> 0.2.1)
|
||||
hashery (~> 2.0)
|
||||
ruby-rc4
|
||||
ttfunk
|
||||
pg (1.2.3)
|
||||
power_assert (2.0.0)
|
||||
pry (0.13.1)
|
||||
pry (0.14.1)
|
||||
coderay (~> 1.1)
|
||||
method_source (~> 1.0)
|
||||
pry-byebug (3.9.0)
|
||||
pry-byebug (3.8.0)
|
||||
byebug (~> 11.0)
|
||||
pry (~> 0.13.0)
|
||||
pry (~> 0.10)
|
||||
public_suffix (4.0.6)
|
||||
raabro (1.4.0)
|
||||
racc (1.5.2)
|
||||
rack (2.2.3)
|
||||
rack-mini-profiler (2.3.2)
|
||||
@@ -404,18 +439,20 @@ GEM
|
||||
rack
|
||||
rack-test (1.1.0)
|
||||
rack (>= 1.0, < 3)
|
||||
rails (5.2.6)
|
||||
actioncable (= 5.2.6)
|
||||
actionmailer (= 5.2.6)
|
||||
actionpack (= 5.2.6)
|
||||
actionview (= 5.2.6)
|
||||
activejob (= 5.2.6)
|
||||
activemodel (= 5.2.6)
|
||||
activerecord (= 5.2.6)
|
||||
activestorage (= 5.2.6)
|
||||
activesupport (= 5.2.6)
|
||||
rails (6.0.3.7)
|
||||
actioncable (= 6.0.3.7)
|
||||
actionmailbox (= 6.0.3.7)
|
||||
actionmailer (= 6.0.3.7)
|
||||
actionpack (= 6.0.3.7)
|
||||
actiontext (= 6.0.3.7)
|
||||
actionview (= 6.0.3.7)
|
||||
activejob (= 6.0.3.7)
|
||||
activemodel (= 6.0.3.7)
|
||||
activerecord (= 6.0.3.7)
|
||||
activestorage (= 6.0.3.7)
|
||||
activesupport (= 6.0.3.7)
|
||||
bundler (>= 1.3.0)
|
||||
railties (= 5.2.6)
|
||||
railties (= 6.0.3.7)
|
||||
sprockets-rails (>= 2.0.0)
|
||||
rails-controller-testing (1.0.5)
|
||||
actionpack (>= 5.0.1.rc1)
|
||||
@@ -426,16 +463,16 @@ GEM
|
||||
nokogiri (>= 1.6)
|
||||
rails-html-sanitizer (1.3.0)
|
||||
loofah (~> 2.3)
|
||||
rails-i18n (5.1.3)
|
||||
rails-i18n (6.0.0)
|
||||
i18n (>= 0.7, < 2)
|
||||
railties (>= 5.0, < 6)
|
||||
railties (>= 6.0.0, < 7)
|
||||
rails_safe_tasks (1.0.0)
|
||||
railties (5.2.6)
|
||||
actionpack (= 5.2.6)
|
||||
activesupport (= 5.2.6)
|
||||
railties (6.0.3.7)
|
||||
actionpack (= 6.0.3.7)
|
||||
activesupport (= 6.0.3.7)
|
||||
method_source
|
||||
rake (>= 0.8.7)
|
||||
thor (>= 0.19.0, < 2.0)
|
||||
thor (>= 0.20.3, < 2.0)
|
||||
rainbow (3.0.0)
|
||||
raindrops (0.19.1)
|
||||
rake (13.0.3)
|
||||
@@ -443,7 +480,7 @@ GEM
|
||||
activerecord (>= 5.2.4)
|
||||
activesupport (>= 5.2.4)
|
||||
i18n
|
||||
rb-fsevent (0.10.4)
|
||||
rb-fsevent (0.11.0)
|
||||
rb-inotify (0.10.1)
|
||||
ffi (~> 1.0)
|
||||
redcarpet (3.5.1)
|
||||
@@ -500,16 +537,16 @@ GEM
|
||||
rswag-ui (2.4.0)
|
||||
actionpack (>= 3.1, < 7.0)
|
||||
railties (>= 3.1, < 7.0)
|
||||
rubocop (1.15.0)
|
||||
rubocop (1.16.0)
|
||||
parallel (~> 1.10)
|
||||
parser (>= 3.0.0.0)
|
||||
rainbow (>= 2.2.2, < 4.0)
|
||||
regexp_parser (>= 1.8, < 3.0)
|
||||
rexml
|
||||
rubocop-ast (>= 1.5.0, < 2.0)
|
||||
rubocop-ast (>= 1.7.0, < 2.0)
|
||||
ruby-progressbar (~> 1.7)
|
||||
unicode-display_width (>= 1.4.0, < 3.0)
|
||||
rubocop-ast (1.5.0)
|
||||
rubocop-ast (1.7.0)
|
||||
parser (>= 3.0.1.1)
|
||||
rubocop-rails (2.10.1)
|
||||
activesupport (>= 4.2.0)
|
||||
@@ -517,11 +554,13 @@ GEM
|
||||
rubocop (>= 1.7.0, < 2.0)
|
||||
ruby-progressbar (1.11.0)
|
||||
ruby-rc4 (0.1.5)
|
||||
ruby2_keywords (0.0.2)
|
||||
ruby2_keywords (0.0.4)
|
||||
rubyzip (2.3.0)
|
||||
rufus-scheduler (3.7.0)
|
||||
fugit (~> 1.1, >= 1.1.6)
|
||||
sass (3.4.25)
|
||||
sass-rails (5.0.7)
|
||||
railties (>= 4.0.0, < 6)
|
||||
sass-rails (5.0.8)
|
||||
railties (>= 5.2.0)
|
||||
sass (~> 3.1)
|
||||
sprockets (>= 2.8, < 4.0)
|
||||
sprockets-rails (>= 2.0, < 4.0)
|
||||
@@ -534,17 +573,23 @@ GEM
|
||||
rubyzip (>= 1.2.2)
|
||||
shoulda-matchers (4.5.1)
|
||||
activesupport (>= 4.2.0)
|
||||
sidekiq (6.2.1)
|
||||
connection_pool (>= 2.2.2)
|
||||
rack (~> 2.0)
|
||||
redis (>= 4.2.0)
|
||||
sidekiq-scheduler (3.0.1)
|
||||
e2mmap
|
||||
redis (>= 3, < 5)
|
||||
rufus-scheduler (~> 3.2)
|
||||
sidekiq (>= 3)
|
||||
thwait
|
||||
tilt (>= 1.4.0)
|
||||
simplecov (0.21.2)
|
||||
docile (~> 1.1)
|
||||
simplecov-html (~> 0.11)
|
||||
simplecov_json_formatter (~> 0.1)
|
||||
simplecov-html (0.12.3)
|
||||
simplecov_json_formatter (0.1.2)
|
||||
sinatra (2.1.0)
|
||||
mustermann (~> 1.0)
|
||||
rack (~> 2.2)
|
||||
rack-protection (= 2.1.0)
|
||||
tilt (~> 2.0)
|
||||
simplecov_json_formatter (0.1.3)
|
||||
spring (2.1.1)
|
||||
spring-commands-rspec (1.0.4)
|
||||
spring (>= 0.9.1)
|
||||
@@ -563,15 +608,18 @@ GEM
|
||||
activerecord (>= 5.1)
|
||||
state_machines-activemodel (>= 0.8.0)
|
||||
stringex (2.8.5)
|
||||
stripe (5.30.0)
|
||||
stripe (5.32.1)
|
||||
temple (0.8.2)
|
||||
test-prof (1.0.5)
|
||||
test-unit (3.4.1)
|
||||
test-unit (3.4.2)
|
||||
power_assert
|
||||
thor (0.20.3)
|
||||
thread_safe (0.3.6)
|
||||
thwait (0.2.0)
|
||||
e2mmap
|
||||
tilt (2.0.10)
|
||||
timecop (0.9.4)
|
||||
ttfunk (1.7.0)
|
||||
tzinfo (1.2.9)
|
||||
thread_safe (~> 0.1)
|
||||
uglifier (4.2.0)
|
||||
@@ -586,8 +634,8 @@ GEM
|
||||
unicorn-worker-killer (0.4.5)
|
||||
get_process_mem (~> 0)
|
||||
unicorn (>= 4, < 7)
|
||||
uniform_notifier (1.14.1)
|
||||
view_component (2.31.1)
|
||||
uniform_notifier (1.14.2)
|
||||
view_component (2.33.0)
|
||||
activesupport (>= 5.0.0, < 7.0)
|
||||
view_component_storybook (0.8.0)
|
||||
view_component (>= 2.2)
|
||||
@@ -601,7 +649,7 @@ GEM
|
||||
addressable (>= 2.3.6)
|
||||
crack (>= 0.3.2)
|
||||
hashdiff (>= 0.4.0, < 2.0.0)
|
||||
websocket-driver (0.7.3)
|
||||
websocket-driver (0.7.4)
|
||||
websocket-extensions (>= 0.1.0)
|
||||
websocket-extensions (0.1.5)
|
||||
whenever (1.0.0)
|
||||
@@ -612,6 +660,7 @@ GEM
|
||||
xml-simple (1.1.8)
|
||||
xpath (3.2.0)
|
||||
nokogiri (~> 1.8)
|
||||
zeitwerk (2.4.2)
|
||||
|
||||
PLATFORMS
|
||||
ruby
|
||||
@@ -633,6 +682,7 @@ DEPENDENCIES
|
||||
awesome_nested_set
|
||||
awesome_print
|
||||
aws-sdk (= 1.67.0)
|
||||
bootsnap
|
||||
bugsnag
|
||||
bullet
|
||||
byebug
|
||||
@@ -651,19 +701,17 @@ DEPENDENCIES
|
||||
ddtrace
|
||||
debugger-linecache
|
||||
delayed_job_active_record
|
||||
delayed_job_web
|
||||
devise
|
||||
devise-encryptable
|
||||
devise-token_authenticatable
|
||||
dfc_provider!
|
||||
eventmachine (>= 1.2.3)
|
||||
factory_bot_rails (= 6.2.0)
|
||||
ffaker
|
||||
figaro
|
||||
flipper
|
||||
flipper-active_record
|
||||
flipper-ui
|
||||
fog-aws (>= 0.6.0)
|
||||
fog-aws (~> 2.0)
|
||||
foundation-icons-sass-rails
|
||||
foundation-rails (= 5.5.2.1)
|
||||
fuubar (~> 2.5.1)
|
||||
@@ -695,13 +743,14 @@ DEPENDENCIES
|
||||
paperclip (~> 3.4.1)
|
||||
paranoia (~> 2.4)
|
||||
paypal-sdk-merchant (= 1.117.2)
|
||||
pdf-reader
|
||||
pg (~> 1.2.3)
|
||||
pry
|
||||
pry-byebug
|
||||
rack-mini-profiler (< 3.0.0)
|
||||
rack-rewrite
|
||||
rack-ssl
|
||||
rails (~> 5.2)
|
||||
rails (~> 6.0.3.7)
|
||||
rails-controller-testing
|
||||
rails-i18n
|
||||
rails_safe_tasks (~> 1.0)
|
||||
@@ -709,18 +758,20 @@ DEPENDENCIES
|
||||
redcarpet
|
||||
redis (>= 4.0)
|
||||
responders
|
||||
roadie-rails (~> 2.2.0)
|
||||
roadie-rails
|
||||
roo (~> 2.8.3)
|
||||
rspec-rails (>= 3.5.2)
|
||||
rspec-retry
|
||||
rswag
|
||||
rubocop
|
||||
rubocop-rails
|
||||
sass (<= 4.7.1)
|
||||
sass-rails (< 6.0.0)
|
||||
sass (~> 3.4.0)
|
||||
sass-rails (< 5.1.0)
|
||||
select2-rails (~> 3.4.7)
|
||||
selenium-webdriver
|
||||
shoulda-matchers
|
||||
sidekiq
|
||||
sidekiq-scheduler
|
||||
simplecov
|
||||
spring
|
||||
spring-commands-rspec
|
||||
@@ -729,6 +780,7 @@ DEPENDENCIES
|
||||
stripe
|
||||
test-prof
|
||||
test-unit (~> 3.4)
|
||||
thor (~> 0.20)
|
||||
timecop
|
||||
uglifier (>= 1.0.3)
|
||||
unicorn-rails
|
||||
@@ -743,7 +795,7 @@ DEPENDENCIES
|
||||
wkhtmltopdf-binary
|
||||
|
||||
RUBY VERSION
|
||||
ruby 2.5.8p224
|
||||
ruby 2.5.9p229
|
||||
|
||||
BUNDLED WITH
|
||||
1.17.3
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
angular.module("admin.products").factory "UnitPrices", (VariantUnitManager, localizeCurrencyFilter) ->
|
||||
angular.module("admin.products").factory "UnitPrices", (VariantUnitManager, localizeCurrencyFilter, unlocalizeCurrencyFilter) ->
|
||||
class UnitPrices
|
||||
@displayableUnitPrice: (price, scale, unit_type, unit_value, variant_unit_name) ->
|
||||
price = unlocalizeCurrencyFilter(price)
|
||||
if price && !isNaN(price) && unit_type && unit_value
|
||||
value = localizeCurrencyFilter(UnitPrices.price(price, scale, unit_type, unit_value, variant_unit_name))
|
||||
unit = UnitPrices.unit(scale, unit_type, variant_unit_name)
|
||||
@@ -29,4 +30,4 @@ angular.module("admin.products").factory "UnitPrices", (VariantUnitManager, loca
|
||||
else if unit_type == "weight"
|
||||
"kg"
|
||||
else if unit_type == "volume"
|
||||
"L"
|
||||
"L"
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
angular.module("admin.utils").filter "unlocalizeCurrency", ()->
|
||||
# Convert string to number using injected currency configuration.
|
||||
(price) ->
|
||||
# used decimal and thousands separators from currency configuration
|
||||
decimal_separator = I18n.toCurrency(.1, {precision: 1, unit: ''}).substring(1,2)
|
||||
thousands_separator = I18n.toCurrency(1000, {precision: 1, unit: ''}).substring(1,2)
|
||||
|
||||
if (price.length > 4)
|
||||
# remove configured thousands separator if price is greater than 999
|
||||
price = price.replaceAll(thousands_separator, '')
|
||||
|
||||
if (decimal_separator == ",")
|
||||
price = price.replace(",", ".")
|
||||
|
||||
return parseFloat(price)
|
||||
@@ -44,9 +44,9 @@ module Api
|
||||
authorize! :update, @enterprise
|
||||
|
||||
if params[:logo] && @enterprise.update( logo: params[:logo] )
|
||||
render plain: @enterprise.logo.url(:medium), status: :ok
|
||||
render html: @enterprise.logo.url(:medium), status: :ok
|
||||
elsif params[:promo] && @enterprise.update( promo_image: params[:promo] )
|
||||
render plain: @enterprise.promo_image.url(:medium), status: :ok
|
||||
render html: @enterprise.promo_image.url(:medium), status: :ok
|
||||
else
|
||||
invalid_resource!(@enterprise)
|
||||
end
|
||||
|
||||
@@ -12,7 +12,7 @@ module Spree
|
||||
helper 'enterprise_fees'
|
||||
helper 'angular_form'
|
||||
|
||||
layout '/spree/layouts/admin'
|
||||
layout 'spree/layouts/admin'
|
||||
|
||||
include I18nHelper
|
||||
|
||||
|
||||
@@ -81,9 +81,7 @@ module Spree
|
||||
end
|
||||
|
||||
def invoice
|
||||
pdf = InvoiceRenderer.new.render_to_string(@order)
|
||||
|
||||
Spree::OrderMailer.invoice_email(@order.id, pdf).deliver_later
|
||||
Spree::OrderMailer.invoice_email(@order.id).deliver_later
|
||||
flash[:success] = t('admin.orders.invoice_email_sent')
|
||||
|
||||
respond_with(@order) { |format|
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
module Spree
|
||||
module PaymentMethodsHelper
|
||||
def payment_method_name(payment)
|
||||
def payment_method(payment)
|
||||
# hack to allow us to retrieve the name of a "deleted" payment method
|
||||
id = payment.payment_method_id
|
||||
Spree::PaymentMethod.find_with_destroyed(id).name
|
||||
Spree::PaymentMethod.find_with_destroyed(id)
|
||||
end
|
||||
|
||||
def payment_method_name(payment)
|
||||
payment_method(payment).name
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -49,8 +49,10 @@ module Spree
|
||||
end
|
||||
end
|
||||
|
||||
def invoice_email(order_or_order_id, pdf)
|
||||
def invoice_email(order_or_order_id)
|
||||
@order = find_order(order_or_order_id)
|
||||
pdf = InvoiceRenderer.new.render_to_string(@order)
|
||||
|
||||
attach_file("invoice-#{@order.number}.pdf", pdf)
|
||||
I18n.with_locale valid_locale(@order.user) do
|
||||
mail(to: @order.email,
|
||||
|
||||
@@ -152,7 +152,7 @@
|
||||
%th.final_weight_volume{ 'ng-show' => 'columns.final_weight_volume.visible' }
|
||||
= t("admin.orders.bulk_management.weight_volume")
|
||||
%th.price{ 'ng-show' => 'columns.price.visible' }
|
||||
= "#{t('admin.price')} (#{currency_symbol})"
|
||||
= "#{t('admin.price')} (#{Spree::Money.currency_symbol})"
|
||||
%th.actions
|
||||
%th.actions
|
||||
= t("admin.orders.bulk_management.ask")
|
||||
|
||||
@@ -17,8 +17,7 @@
|
||||
%th.cart-item-delete-header
|
||||
|
||||
%tbody#line_items{"data-hook" => ""}
|
||||
= order_form.fields_for :line_items do |item_form|
|
||||
= render :partial => 'line_item', :locals => { :variant => item_form.object.variant, :line_item => item_form.object, :item_form => item_form }
|
||||
= render partial: 'line_item', collection: order_form.object.line_items, locals: {order_form: order_form}
|
||||
|
||||
= render 'bought' if show_bought_items? && @order.cart?
|
||||
|
||||
|
||||
@@ -1,37 +1,39 @@
|
||||
%tr.line-item{class: "variant-#{variant.id}"}
|
||||
%td.cart-item-description{'data-hook' => "cart_item_description"}
|
||||
- variant = line_item.variant
|
||||
= order_form.fields_for :line_items, line_item do |item_form|
|
||||
%tr.line-item{class: "variant-#{variant.id}"}
|
||||
%td.cart-item-description{'data-hook' => "cart_item_description"}
|
||||
|
||||
%div.item-thumb-image{"data-hook" => "cart_item_image"}
|
||||
= render 'spree/shared/variant_thumbnail', variant: variant
|
||||
%div.item-thumb-image{"data-hook" => "cart_item_image"}
|
||||
= render 'spree/shared/variant_thumbnail', variant: variant
|
||||
|
||||
= render 'spree/shared/line_item_name', line_item: line_item
|
||||
= render 'spree/shared/line_item_name', line_item: line_item
|
||||
|
||||
- if @insufficient_stock_lines.andand.include? line_item
|
||||
%span.out-of-stock
|
||||
= variant.in_stock? ? t(".insufficient_stock", :on_hand => variant.on_hand) : t(".out_of_stock")
|
||||
%br/
|
||||
- if @insufficient_stock_lines.andand.include? line_item
|
||||
%span.out-of-stock
|
||||
= variant.in_stock? ? t(".insufficient_stock", :on_hand => variant.on_hand) : t(".out_of_stock")
|
||||
%br/
|
||||
|
||||
- if @unavailable_order_variants.andand.include? line_item.variant
|
||||
%span.out-of-stock
|
||||
= t(".unavailable_item")
|
||||
%br/
|
||||
- if @unavailable_order_variants.andand.include? line_item.variant
|
||||
%span.out-of-stock
|
||||
= t(".unavailable_item")
|
||||
%br/
|
||||
|
||||
%td.text-right.cart-item-price{"data-hook" => "cart_item_price"}
|
||||
= line_item.single_display_amount_with_adjustments.to_html
|
||||
- if feature? :unit_price, spree_current_user
|
||||
%br
|
||||
%span.unit-price
|
||||
= line_item.unit_price_price_and_unit
|
||||
%td.text-center.cart-item-quantity{"data-hook" => "cart_item_quantity"}
|
||||
- finalized_quantity = @order.completed? ? line_item.quantity : 0
|
||||
= item_form.number_field :quantity,
|
||||
:min => 0, "ofn-on-hand" => "#{variant.on_demand && 9999 || variant.on_hand}",
|
||||
"finalizedquantity" => finalized_quantity, :class => "line_item_quantity", :size => 5,
|
||||
"ng-model" => "line_item_#{line_item.id}",
|
||||
"validate-stock-quantity" => true
|
||||
%td.cart-item-total.text-right{"data-hook" => "cart_item_total"}
|
||||
= line_item.display_amount_with_adjustments.to_html unless line_item.quantity.nil?
|
||||
%td.text-right.cart-item-price{"data-hook" => "cart_item_price"}
|
||||
= line_item.single_display_amount_with_adjustments.to_html
|
||||
- if feature? :unit_price, spree_current_user
|
||||
%br
|
||||
%span.unit-price
|
||||
= line_item.unit_price_price_and_unit
|
||||
%td.text-center.cart-item-quantity{"data-hook" => "cart_item_quantity"}
|
||||
- finalized_quantity = @order.completed? ? line_item.quantity : 0
|
||||
= item_form.number_field :quantity,
|
||||
:min => 0, "ofn-on-hand" => "#{variant.on_demand && 9999 || variant.on_hand}",
|
||||
"finalizedquantity" => finalized_quantity, :class => "line_item_quantity", :size => 5,
|
||||
"ng-model" => "line_item_#{line_item.id}",
|
||||
"validate-stock-quantity" => true
|
||||
%td.cart-item-total.text-right{"data-hook" => "cart_item_total"}
|
||||
= line_item.display_amount_with_adjustments.to_html unless line_item.quantity.nil?
|
||||
|
||||
%td.cart-item-delete.text-center{"data-hook" => "cart_item_delete"}
|
||||
%a.delete{href: "#", id: "delete_#{dom_id(line_item)}"}
|
||||
%i.delete.ofn-i_026-trash
|
||||
%td.cart-item-delete.text-center{"data-hook" => "cart_item_delete"}
|
||||
%a.delete{href: "#", id: "delete_#{dom_id(line_item)}"}
|
||||
%i.delete.ofn-i_026-trash
|
||||
|
||||
@@ -13,3 +13,8 @@
|
||||
= t :email_payment_summary
|
||||
- if @order.payments.any?
|
||||
= render partial: 'spree/shared/payments_list', locals: { payments: @order.payments }
|
||||
- if last_payment_method(@order).present?
|
||||
%p.callout{style: "margin-top: 40px"}
|
||||
%strong
|
||||
= t :email_payment_description
|
||||
%p{style: "margin: 5px"}= last_payment_method(@order).description
|
||||
|
||||
@@ -1,6 +1,25 @@
|
||||
require_relative 'boot'
|
||||
|
||||
require 'rails/all'
|
||||
require "rails"
|
||||
[
|
||||
"active_record/railtie",
|
||||
#"active_storage/engine",
|
||||
"action_controller/railtie",
|
||||
"action_view/railtie",
|
||||
"action_mailer/railtie",
|
||||
"active_job/railtie",
|
||||
#"action_cable/engine", # Enable this when installing StimulusReflex
|
||||
#"action_mailbox/engine",
|
||||
#"action_text/engine",
|
||||
"rails/test_unit/railtie",
|
||||
"sprockets/railtie" # Disable this after migrating to Webpacker
|
||||
].each do |railtie|
|
||||
begin
|
||||
require railtie
|
||||
rescue LoadError
|
||||
end
|
||||
end
|
||||
|
||||
require_relative "../lib/open_food_network/i18n_config"
|
||||
|
||||
require_relative '../lib/spree/core/environment'
|
||||
@@ -189,7 +208,7 @@ module Openfoodnetwork
|
||||
|
||||
config.active_support.escape_html_entities_in_json = true
|
||||
|
||||
config.active_job.queue_adapter = :delayed_job
|
||||
config.active_job.queue_adapter = :sidekiq
|
||||
|
||||
config.action_controller.include_all_helpers = false
|
||||
|
||||
|
||||
@@ -4,3 +4,4 @@ require 'rubygems'
|
||||
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
|
||||
|
||||
require 'bundler/setup' if File.exists?(ENV['BUNDLE_GEMFILE'])
|
||||
require 'bootsnap/setup'
|
||||
|
||||
@@ -15,7 +15,6 @@ Openfoodnetwork::Application.configure do
|
||||
config.cache_store = :redis_cache_store, {
|
||||
driver: :hiredis,
|
||||
url: ENV.fetch("OFN_REDIS_URL", "redis://localhost:6379/0"),
|
||||
namespace: "cache",
|
||||
expires_in: 90.minutes
|
||||
}
|
||||
end
|
||||
|
||||
@@ -44,8 +44,7 @@ Openfoodnetwork::Application.configure do
|
||||
# Use a different cache store in production
|
||||
config.cache_store = :redis_cache_store, {
|
||||
driver: :hiredis,
|
||||
url: ENV.fetch("OFN_REDIS_URL", "redis://localhost:6379/0"),
|
||||
namespace: "cache",
|
||||
url: ENV.fetch("OFN_REDIS_URL", "redis://localhost:6380/0"),
|
||||
reconnect_attempts: 1
|
||||
}
|
||||
|
||||
|
||||
@@ -44,8 +44,7 @@ Openfoodnetwork::Application.configure do
|
||||
# Use a different cache store in production
|
||||
config.cache_store = :redis_cache_store, {
|
||||
driver: :hiredis,
|
||||
url: ENV.fetch("OFN_REDIS_URL", "redis://localhost:6379/0"),
|
||||
namespace: "cache",
|
||||
url: ENV.fetch("OFN_REDIS_URL", "redis://localhost:6380/0"),
|
||||
reconnect_attempts: 1
|
||||
}
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ Devise.setup do |config|
|
||||
config.stretches = Rails.env.test? ? 1 : 20
|
||||
|
||||
# Setup a pepper to generate the encrypted password.
|
||||
config.pepper = Rails.configuration.secret_token
|
||||
config.pepper = Rails.configuration.secret_key_base
|
||||
|
||||
# ==> Configuration for :confirmable
|
||||
# The time you want to give your user to confirm his account. During this time
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
Money.rounding_mode = BigDecimal::ROUND_HALF_EVEN
|
||||
Money.default_currency = Money::Currency.new(Spree::Config[:currency])
|
||||
Money.default_currency = Money::Currency.new(ENV.fetch('CURRENCY'))
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
PaperTrail.config.track_associations = false
|
||||
9
config/initializers/sidekiq.rb
Normal file
9
config/initializers/sidekiq.rb
Normal file
@@ -0,0 +1,9 @@
|
||||
redis_jobs_url = ENV.fetch("OFN_REDIS_JOBS_URL", "redis://localhost:6381/0")
|
||||
|
||||
Sidekiq.configure_server do |config|
|
||||
config.redis = { url: redis_jobs_url, network_timeout: 5 }
|
||||
end
|
||||
|
||||
Sidekiq.configure_client do |config|
|
||||
config.redis = { url: redis_jobs_url, network_timeout: 5 }
|
||||
end
|
||||
@@ -19,6 +19,7 @@ end
|
||||
|
||||
Spree.config do |config|
|
||||
config.site_url = ENV['SITE_URL'] if ENV['SITE_URL']
|
||||
config.site_name = ENV['SITE_NAME'] if ENV['SITE_NAME']
|
||||
config.shipping_instructions = true
|
||||
config.address_requires_state = true
|
||||
config.admin_interface_logo = '/default_images/ofn-logo.png'
|
||||
|
||||
@@ -1571,6 +1571,7 @@ ca:
|
||||
email_order_summary_includes_tax: "(inclou impostos):"
|
||||
email_payment_paid: PAGAT
|
||||
email_payment_not_paid: 'NO PAGAT '
|
||||
email_payment_description: Descripció del pagament de la comanda
|
||||
email_payment_summary: Resum del pagament
|
||||
email_payment_method: "Pagament a través de:"
|
||||
email_so_placement_intro_html: "Tens una nova comanda amb <strong> %{distributor}</strong>"
|
||||
|
||||
@@ -50,7 +50,7 @@ de_DE:
|
||||
variant_override:
|
||||
count_on_hand:
|
||||
using_producer_stock_settings_but_count_on_hand_set: "muss leer sein, da die Einstellungen des Produzentenbestands verwendet werden"
|
||||
on_demand_but_count_on_hand_set: "muss leer sein, wenn die Produktion auf Anfrage erfolgt"
|
||||
on_demand_but_count_on_hand_set: "muss leer sein, wenn unbegrenzt verfügbar oder die Produktion auf Bestellung erfolgt"
|
||||
limited_stock_but_no_count_on_hand: "muss angegeben werden, da nur begrenzte Lagerbestände verfügbar sind"
|
||||
activemodel:
|
||||
attributes:
|
||||
@@ -347,8 +347,8 @@ de_DE:
|
||||
ends_on: Endet am
|
||||
name: Name
|
||||
on_hand: Verfügbar
|
||||
on_demand: Auf Anfrage
|
||||
on_demand?: Auf Anfrage?
|
||||
on_demand: Unbegrenzt/auf Bestellung
|
||||
on_demand?: Unbegrenzt/auf Bestellung
|
||||
order_cycle: Bestellzyklus
|
||||
payment: Zahlung
|
||||
payment_method: Zahlungsart
|
||||
@@ -986,7 +986,7 @@ de_DE:
|
||||
add: Koordinatorgebühr hinzufügen
|
||||
filters:
|
||||
search_by_order_cycle_name: "Suche nach Name des Bestellzyklus ..."
|
||||
involving: "Betrifft"
|
||||
involving: "Unternehmen"
|
||||
any_enterprise: "Alle Unternehmen"
|
||||
any_schedule: "Alle Zeitpläne"
|
||||
form:
|
||||
@@ -1369,7 +1369,7 @@ de_DE:
|
||||
country: Land
|
||||
unauthorized: Nicht autorisiert
|
||||
terms_of_service: "AGB"
|
||||
on_demand: Auf Anfrage
|
||||
on_demand: Unbegrenzt/auf Bestellung
|
||||
none: Keine
|
||||
not_allowed: Nicht erlaubt
|
||||
no_shipping: keine Lieferoptionen
|
||||
@@ -1570,6 +1570,7 @@ de_DE:
|
||||
email_order_summary_includes_tax: "(inkl. Steuern):"
|
||||
email_payment_paid: BEZAHLT
|
||||
email_payment_not_paid: NICHT BEZAHLT
|
||||
email_payment_description: 'Hinweise zur Zahlung '
|
||||
email_payment_summary: Zahlungsübersicht
|
||||
email_payment_method: "Zahlungsart:"
|
||||
email_so_placement_intro_html: "Sie haben eine neue Bestellung bei <strong>%{distributor}</strong> erhalten!"
|
||||
@@ -2729,7 +2730,7 @@ de_DE:
|
||||
unit_price_tooltip: "Grundpreis: Er ermöglicht einen einfachen Preisvergleich von Produkten, unabhängig von Packungsgröße und -gewicht."
|
||||
variants:
|
||||
on_demand:
|
||||
'yes': "Auf Anfrage"
|
||||
'yes': "Unbegrenzt/auf Bestellung"
|
||||
variant_overrides:
|
||||
on_demand:
|
||||
use_producer_settings: "Einstellungen des Produzentenbestands verwenden"
|
||||
@@ -3021,7 +3022,7 @@ de_DE:
|
||||
location: "Ort"
|
||||
count_on_hand: "Verfügbar"
|
||||
quantity: "Menge"
|
||||
on_demand: "Unbegrenzt"
|
||||
on_demand: "Unbegrenzt/auf Bestellung"
|
||||
on_hand: "Verfügbar"
|
||||
package_from: "Paket von"
|
||||
item_description: "Artikelbeschreibung"
|
||||
@@ -3465,7 +3466,7 @@ de_DE:
|
||||
unit_price: "Grundpreis"
|
||||
unit_price_legend: "Berechnet aus Preis und Menge."
|
||||
on_hand: "Verfügbar"
|
||||
on_demand: "Unbegrenzt"
|
||||
on_demand: "Unbegrenzt/auf Bestellung"
|
||||
product_description: "Produktbeschreibung"
|
||||
image: "Bild"
|
||||
or: "oder"
|
||||
|
||||
@@ -1669,6 +1669,7 @@ See the %{link} to find out more about %{sitename}'s features and to start using
|
||||
email_order_summary_includes_tax: "(includes tax):"
|
||||
email_payment_paid: PAID
|
||||
email_payment_not_paid: NOT PAID
|
||||
email_payment_description: Payment Description at Checkout
|
||||
email_payment_summary: Payment summary
|
||||
email_payment_method: "Paying via:"
|
||||
email_so_placement_intro_html: "You have a new order with <strong>%{distributor}</strong>"
|
||||
|
||||
@@ -1568,6 +1568,7 @@ en_FR:
|
||||
email_order_summary_includes_tax: "(includes tax):"
|
||||
email_payment_paid: PAID
|
||||
email_payment_not_paid: NOT PAID
|
||||
email_payment_description: Payment Description at Checkout
|
||||
email_payment_summary: Payment summary
|
||||
email_payment_method: "Paying via:"
|
||||
email_so_placement_intro_html: "You have a new order with <strong>%{distributor}</strong>"
|
||||
|
||||
@@ -1568,6 +1568,7 @@ en_GB:
|
||||
email_order_summary_includes_tax: "(includes tax):"
|
||||
email_payment_paid: PAID
|
||||
email_payment_not_paid: NOT PAID
|
||||
email_payment_description: Payment Description at Checkout
|
||||
email_payment_summary: Payment summary
|
||||
email_payment_method: "Paying via:"
|
||||
email_so_placement_intro_html: "You have a new order with <strong>%{distributor}</strong>"
|
||||
|
||||
@@ -317,6 +317,8 @@ en_IE:
|
||||
height: "Height"
|
||||
width: "Width"
|
||||
depth: "Depth"
|
||||
payment_could_not_process: "The payment could not be processed"
|
||||
payment_could_not_complete: "The payment could not be completed"
|
||||
actions:
|
||||
create_and_add_another: "Create and Add Another"
|
||||
create: "Create"
|
||||
@@ -1566,6 +1568,7 @@ en_IE:
|
||||
email_order_summary_includes_tax: "(includes tax):"
|
||||
email_payment_paid: PAID
|
||||
email_payment_not_paid: NOT PAID
|
||||
email_payment_description: Payment Description at Checkout
|
||||
email_payment_summary: Payment summary
|
||||
email_payment_method: "Paying via:"
|
||||
email_so_placement_intro_html: "You have a new order with <strong>%{distributor}</strong>"
|
||||
|
||||
@@ -1568,6 +1568,7 @@ en_US:
|
||||
email_order_summary_includes_tax: "(includes tax):"
|
||||
email_payment_paid: PAID
|
||||
email_payment_not_paid: NOT PAID
|
||||
email_payment_description: Payment Description at Checkout
|
||||
email_payment_summary: Payment summary
|
||||
email_payment_method: "Paying via:"
|
||||
email_so_placement_intro_html: "You have a new order with <strong>%{distributor}</strong>"
|
||||
|
||||
@@ -1570,6 +1570,7 @@ es:
|
||||
email_order_summary_includes_tax: "(incluye impuestos):"
|
||||
email_payment_paid: PAGADO
|
||||
email_payment_not_paid: NO PAGADO
|
||||
email_payment_description: Descripción de pago de la compra
|
||||
email_payment_summary: Resumen de pago
|
||||
email_payment_method: "Pagando con:"
|
||||
email_so_placement_intro_html: "Tiene un nuevo pedido con <strong> %{distributor} </strong>"
|
||||
|
||||
@@ -119,6 +119,7 @@ es_US:
|
||||
updated_not_active: "Su contraseña ha sido restablecida, pero su correo electrónico aún no ha sido confirmado."
|
||||
updated: "Su contraseña ha sido cambiada con éxito. Ya tienes la sesión iniciada."
|
||||
send_instructions: "Recibirás un correo electrónico con instrucciones sobre cómo confirmar su cuenta en unos minutos."
|
||||
item_description: "Descripción del artículo"
|
||||
models:
|
||||
order_cycle:
|
||||
cloned_order_cycle_name: "COPIA DE %{order_cycle}"
|
||||
@@ -127,6 +128,9 @@ es_US:
|
||||
open_street_map_enabled: "Open Street Map activado"
|
||||
open_street_map_default_latitude: "latitud por defecto en Open Street Map"
|
||||
open_street_map_default_longitude: "longitud por defecto en Open Street Map"
|
||||
open_street_map_provider_name: "nombre del proveedor de Open Street Map"
|
||||
open_street_map_provider_options: "opciones de proveedor de Open Street Map"
|
||||
resume_order: "Reanudar pedido"
|
||||
sku: "SKU"
|
||||
subtotal: "Subtotal"
|
||||
tax_rate: "% Impuestos"
|
||||
@@ -155,6 +159,7 @@ es_US:
|
||||
producer_mailer:
|
||||
order_cycle:
|
||||
subject: "Informe Ciclo de Pedido para %{producer}"
|
||||
provider_settings: "Configuración de proveedor"
|
||||
shipment_mailer:
|
||||
shipped_email:
|
||||
dear_customer: "Estimada consumidora,"
|
||||
@@ -1082,6 +1087,7 @@ es_US:
|
||||
index:
|
||||
title: "Suscripciones"
|
||||
new: "Nueva suscripción"
|
||||
issue: "Asunto"
|
||||
new:
|
||||
title: "Nueva suscripción"
|
||||
edit:
|
||||
@@ -1195,8 +1201,11 @@ es_US:
|
||||
terms_and_conditions:
|
||||
message_html: "Acepto el %{terms_and_conditions_link} del vendedor."
|
||||
link_text: "Términos y Condiciones"
|
||||
platform_terms_of_service:
|
||||
terms_of_service: "La latitud y longitud son necesarias para mostrar su empresa en el mapa."
|
||||
all_terms_and_conditions:
|
||||
terms_and_conditions: "Términos y Condiciones"
|
||||
terms_of_service: "La latitud y longitud son necesarios para mostrar su empresa en el mapa."
|
||||
failed: "La finalización de compra falló, por favor comunicate con nosotros para procesar la orden."
|
||||
shops:
|
||||
hubs:
|
||||
@@ -1861,6 +1870,7 @@ es_US:
|
||||
details:
|
||||
title: "Detalles"
|
||||
headline: "Empecemos"
|
||||
enterprise: "Bueno! Primero necesitamos saber un poco más acerca de tu empresa"
|
||||
producer: "Primero necesitamos saber un poco sobre tu productora:"
|
||||
enterprise_name_field: "Nombre de la organización:"
|
||||
producer_name_field: "Nombre de la productora:"
|
||||
@@ -2436,6 +2446,7 @@ es_US:
|
||||
Ha habido un problema al añadir este producto en el carrito. Puede que haya
|
||||
dejado de estar disponible o que la tinda haya cerrado.
|
||||
admin:
|
||||
unit_price_tooltip: "El precio unitario aumenta la transparencia al permitir a sus clientes comparar fácilmente los precios entre diferentes productos y tamaños de empaque. Tenga en cuenta que el precio unitario final que se muestra en la tienda puede diferir, ya que incluye impuestos y comisiones."
|
||||
enterprise_limit_reached: "Has alcanzado el límite estándar de organizaciones por cuenta. Escriba a %{contact_email} si necesita aumentarlo."
|
||||
modals:
|
||||
got_it: "Lo entiendo"
|
||||
@@ -2914,18 +2925,48 @@ es_US:
|
||||
previous: "Anterior"
|
||||
last: "Último"
|
||||
spree:
|
||||
add_country: "Agregar país"
|
||||
add_state: "Agregar estado"
|
||||
all: "Todos"
|
||||
back_to_adjustments_list: "Regresar a ajustes"
|
||||
back_to_users_list: "Regresar a usuarios"
|
||||
back_to_zones_list: "Regresar a zonas"
|
||||
card_code: "Código de la tarjeta"
|
||||
card_number: "Número de tarjeta"
|
||||
category: "Categoría"
|
||||
created_successfully: "Creado con éxito"
|
||||
credit: "Crédito"
|
||||
editing_tax_category: "Editar categoría de impuestos"
|
||||
editing_tax_rate: "Editar tasa de impuestos"
|
||||
editing_zone: "Editar zona"
|
||||
expiration: "Vencimiento"
|
||||
invalid_payment_provider: "Proveedor de pago no válido"
|
||||
items_cannot_be_shipped: "Estos artículos no pueden ser enviados"
|
||||
gateway_config_unavailable: "Configuración de puerta de enlace no disponible"
|
||||
gateway_error: "Pago fallido"
|
||||
more: "Más"
|
||||
new_adjustment: "Nuevo ajuste"
|
||||
new_order_completed: "Nuevo pedido completado"
|
||||
new_tax_category: "Nueva categoría de impuestos"
|
||||
new_user: "Nuevo usuario"
|
||||
no_pending_payments: "No tiene pagos pendientes"
|
||||
none: "Ninguno"
|
||||
not_found: "no encontrado"
|
||||
notice_messages:
|
||||
variant_deleted: "Variante eliminada"
|
||||
or: "O"
|
||||
order_processed_successfully: "Pedido procesado con éxito"
|
||||
payment_method_not_supported: "Método de pago no admitido"
|
||||
resend_authorization_email: "Reenviar email de autorización"
|
||||
server_error: "Error del Servidor"
|
||||
tree: "Árbol"
|
||||
updating: "Actualizando"
|
||||
your_order_is_empty_add_product: "Su pedido está vacío, busque y añada un producto arriba"
|
||||
add_product: "Añadir Producto"
|
||||
name_or_sku: "Nombre o código SKU (ingrese al menos los primeros 4 caracteres del nombre del producto)"
|
||||
resend: "Reenviar"
|
||||
back_to_orders_list: "Volver a la lista de pedidos"
|
||||
back_to_payments_list: "Regresar a la lista de pagos"
|
||||
return_authorizations: "Autorizaciones de devolución"
|
||||
cannot_create_returns: "No se pueden crear devoluciones ya que este pedido no tiene unidades enviadas."
|
||||
select_stock: "Seleccionar stock"
|
||||
@@ -2947,6 +2988,7 @@ es_US:
|
||||
tracking_number: "Número de seguimiento"
|
||||
order_total: "Total del pedido"
|
||||
customer_details: "Detalles de la consumidora"
|
||||
customer_details_updated: "Detalles del consumir actualizados"
|
||||
customer_search: "Búsqueda de consumidores"
|
||||
choose_a_customer: "Elige una consumidora "
|
||||
account: "Cuenta"
|
||||
@@ -3098,6 +3140,7 @@ es_US:
|
||||
payment_processing_failed: "No se pudo procesar el pago, por favor verifique los detalles que introdujo"
|
||||
not_available: "No disponible"
|
||||
sku: "SKU"
|
||||
there_are_no_items_for_this_order: "No hay artículos para este pedido."
|
||||
order_populator:
|
||||
out_of_stock: '%{item} está agotado.'
|
||||
actions:
|
||||
@@ -3125,7 +3168,15 @@ es_US:
|
||||
login_nav:
|
||||
header:
|
||||
store: Tienda
|
||||
validation:
|
||||
must_be_int: "debe ser un entero"
|
||||
admin:
|
||||
mail_methods:
|
||||
send_testmail: "Enviar email de prueba"
|
||||
testmail:
|
||||
delivery_success: "email de prueba enviado"
|
||||
error: "Ha ocurrido un error para el envío del email de prueba."
|
||||
unit_price_tooltip: "El precio unitario aumenta la transparencia al permitir a sus clientes comparar fácilmente los precios entre diferentes productos y tamaños de empaque. Tenga en cuenta que el precio unitario final que se muestra en la tienda puede diferir, ya que incluye impuestos y comisiones."
|
||||
subscriptions:
|
||||
number: "Número"
|
||||
tab:
|
||||
@@ -3196,6 +3247,8 @@ es_US:
|
||||
received: "recibido"
|
||||
canceled: "cancelado"
|
||||
orders:
|
||||
add_product:
|
||||
cannot_add_item_to_canceled_order: "No se puede agregar un artículo a un pedido cancelado"
|
||||
index:
|
||||
listing_orders: "Pedidos de listado"
|
||||
new_order: "Nuevo pedido"
|
||||
@@ -3238,6 +3291,9 @@ es_US:
|
||||
overview:
|
||||
enterprises_header:
|
||||
ofn_with_tip: Las Organizaciones son Productoras y/o Grupos y son la unidad básica de organización dentro de la Open Food Network.
|
||||
enterprise_row:
|
||||
has_no_payment_methods: "no tiene métodos de pago"
|
||||
has_no_shipping_methods: "No tiene métodos de envío"
|
||||
products:
|
||||
active_products:
|
||||
zero: "No tienes ningún producto activo"
|
||||
@@ -3358,6 +3414,7 @@ es_US:
|
||||
unit_name: "Nombre de la unidad"
|
||||
price: "Precio"
|
||||
unit_price: "Precio por unidad"
|
||||
unit_price_legend: "Calculado a partir del precio del artículo"
|
||||
on_hand: "Disponibles"
|
||||
on_demand: "Bajo demanda"
|
||||
product_description: "Descripción del producto"
|
||||
@@ -3463,6 +3520,7 @@ es_US:
|
||||
cookies_consent_banner_toggle: "Mostrar el banner de consentimiento de cookies"
|
||||
privacy_policy_url: "Vínculo con la Política de privacidad"
|
||||
enterprises_require_tos: "Las organizaciones deben aceptar los Términos del Servicio"
|
||||
shoppers_require_tos: "Los compradores tienen que aceptar los Términos y Condiciones de Servicio"
|
||||
cookies_policy_matomo_section: "Mostrar la sección de Matomo en la página de política de cookies"
|
||||
footer_tos_url: "URL de términos y servicios"
|
||||
checkout:
|
||||
@@ -3500,6 +3558,7 @@ es_US:
|
||||
pending: pendiente
|
||||
ready: Listo
|
||||
shipped: enviado
|
||||
canceled: cancelado
|
||||
payment_states:
|
||||
balance_due: saldo debido
|
||||
completed: completado
|
||||
@@ -3621,6 +3680,8 @@ es_US:
|
||||
past_orders: Pedidos anteriores
|
||||
transactions:
|
||||
transaction_history: Historial de transacciones
|
||||
authorisation_required: Autorización requerida
|
||||
authorise: Autorizar
|
||||
open_orders:
|
||||
order: Pedido
|
||||
shop: Tienda
|
||||
@@ -3672,3 +3733,6 @@ es_US:
|
||||
spree/payment:
|
||||
one: Pago
|
||||
other: Pagos
|
||||
datetime:
|
||||
distance_in_words:
|
||||
half_a_minute: medio minuto
|
||||
|
||||
@@ -1570,6 +1570,7 @@ fr:
|
||||
email_order_summary_includes_tax: "(dont TVA)"
|
||||
email_payment_paid: RÉGLÉ
|
||||
email_payment_not_paid: NON RÉGLÉ
|
||||
email_payment_description: Informations concernant le mode de paiement
|
||||
email_payment_summary: Résumé du paiement
|
||||
email_payment_method: "Payer via :"
|
||||
email_so_placement_intro_html: "Une nouvelle commande automatique a été passée pour vous chez <strong>%{distributor}</strong>"
|
||||
|
||||
@@ -121,11 +121,23 @@ pt_BR:
|
||||
send_instructions: "Você receberá um e-mail com instruções sobre como confirmar sua conta em alguns minutos."
|
||||
home_page_alert_html: "HTML de alerta da página"
|
||||
item_description: "Descrição do item"
|
||||
menu_1_icon_name: "Nome do ícone do Menu 1"
|
||||
menu_2_icon_name: "Nome do ícone do Menu 2"
|
||||
menu_3_icon_name: "Nome do ícone do Menu 3"
|
||||
menu_4_icon_name: "Nome do ícone do Menu 4"
|
||||
menu_5_icon_name: "Nome do ícone do Menu 5"
|
||||
menu_6_icon_name: "Nome do ícone do Menu 6"
|
||||
menu_7_icon_name: "Nome do ícone do Menu 7"
|
||||
models:
|
||||
order_cycle:
|
||||
cloned_order_cycle_name: "COPIA DO %{order_cycle}"
|
||||
tax_rate:
|
||||
included_in_price: "Incluso no preço"
|
||||
open_street_map_enabled: "Open Street Map ativado"
|
||||
open_street_map_default_latitude: "Latitude padrão do Open Street Map"
|
||||
open_street_map_default_longitude: "Longitude padrão do Open Street Map"
|
||||
open_street_map_provider_name: "Nome do provedor do Open Street Map"
|
||||
open_street_map_provider_options: "Opções do provedor do Open Street Map"
|
||||
resume_order: "Retomar pedido"
|
||||
sku: "SKU"
|
||||
subtotal: "Subtotal"
|
||||
@@ -1328,6 +1340,12 @@ pt_BR:
|
||||
address2: Complemento
|
||||
city: Cidade
|
||||
city_placeholder: 'ex: República'
|
||||
latitude: Latitude
|
||||
latitude_placeholder: ex. -13.51772776
|
||||
latitude_longitude_tip: A Latitude e Longitude são necessárias para mostrar sua iniciativa no mapa.
|
||||
longitude: Longitude
|
||||
longitude_placeholder: ex. 46.40625
|
||||
use_geocoder: 'Calcular latitude e longitude automaticamente a partir do endereço? '
|
||||
postcode: CEP
|
||||
postcode_placeholder: 'ex: 05429-130'
|
||||
suburb: Cidade
|
||||
@@ -1536,6 +1554,7 @@ pt_BR:
|
||||
email_order_summary_includes_tax: "(inclui taxa):"
|
||||
email_payment_paid: PAGO
|
||||
email_payment_not_paid: NÃO PAGO
|
||||
email_payment_description: Descrição do Pagamento no Checkout
|
||||
email_payment_summary: Resumo do pagamento
|
||||
email_payment_method: "Pagando com:"
|
||||
email_so_placement_intro_html: "Você tem um novo pedido com <strong>%{distributor}</strong>"
|
||||
@@ -1881,6 +1900,11 @@ pt_BR:
|
||||
state_field_error: "Estado requerido"
|
||||
country_field: "País:"
|
||||
country_field_error: "Por favor, selecione um país"
|
||||
map_location: "Localização no Mapa"
|
||||
locate_address: "Localizar endereço no mapa"
|
||||
drag_pin: "Arraste e solte o marcador na localização correta, caso ele não esteja no lugar certo"
|
||||
confirm_address: "Eu confirmo que a localização da iniciativa no mapa está correta."
|
||||
drag_map_marker: "Ajude-nos a entender melhor onde você está localizado arrastando o marcador no mapa acima para uma localização mais precisa, com base no seu conhecimento."
|
||||
contact:
|
||||
title: "Contato"
|
||||
who_is_managing_enterprise: "Quem é responsável por gerenciar %{enterprise}? "
|
||||
@@ -3730,6 +3754,9 @@ pt_BR:
|
||||
other: Pagamentos
|
||||
datetime:
|
||||
distance_in_words:
|
||||
about_x_hours:
|
||||
one: cerca de 1 hora
|
||||
other: cerca de %{count}horas
|
||||
about_x_months:
|
||||
one: cerca de 1 mês
|
||||
other: cerca de %{count}mês
|
||||
|
||||
@@ -1238,7 +1238,7 @@ ru:
|
||||
mailers:
|
||||
powered_by:
|
||||
open_food_network: "Открытая Сеть Продуктов"
|
||||
powered_html: "Ваш опыт покупок обеспечивается %{open_food_network}."
|
||||
powered_html: "Ваш опыт покупок обеспечивает %{open_food_network}."
|
||||
menu:
|
||||
cart:
|
||||
cart: "Корзина"
|
||||
@@ -1368,7 +1368,7 @@ ru:
|
||||
suburb: Город
|
||||
state: Область
|
||||
country: Страна
|
||||
unauthorized: На разрешено
|
||||
unauthorized: Неавторизованный
|
||||
terms_of_service: "Условия Сервиса"
|
||||
on_demand: По запросу
|
||||
none: Ничего
|
||||
@@ -1571,6 +1571,7 @@ ru:
|
||||
email_order_summary_includes_tax: "(включает налог):"
|
||||
email_payment_paid: ОПЛАЧЕН
|
||||
email_payment_not_paid: НЕ ОПЛАЧЕН
|
||||
email_payment_description: Описание Платежа при Оформлении Заказа
|
||||
email_payment_summary: Статус оплаты
|
||||
email_payment_method: "Тип оплаты:"
|
||||
email_so_placement_intro_html: "У Вас есть новый заказ с <strong>%{distributor}</strong>"
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
require 'sidekiq/web'
|
||||
require 'sidekiq-scheduler/web'
|
||||
|
||||
Openfoodnetwork::Application.routes.draw do
|
||||
namespace :admin do
|
||||
|
||||
authenticated :spree_user, -> user { user.admin? } do
|
||||
mount DelayedJobWeb, at: '/delayed_job'
|
||||
mount Flipper::UI.app(Flipper) => '/feature-toggle'
|
||||
mount Sidekiq::Web, at: "/sidekiq"
|
||||
end
|
||||
|
||||
resources :bulk_line_items
|
||||
|
||||
@@ -9,7 +9,6 @@ env "MAILTO", app_config["SCHEDULE_NOTIFICATIONS"] if app_config["SCHEDULE_NOTIF
|
||||
|
||||
# If we use -e with a file containing specs, rspec interprets it and filters out our examples
|
||||
job_type :run_file, "cd :path; :environment_variable=:environment bundle exec script/rails runner :task :output"
|
||||
job_type :enqueue_job, "cd :path; :environment_variable=:environment bundle exec script/enqueue :task :priority :output"
|
||||
|
||||
every 1.month, at: '4:30am' do
|
||||
rake 'ofn:data:remove_transient_data'
|
||||
@@ -22,9 +21,3 @@ end
|
||||
every 4.hours do
|
||||
rake 'db2fog:backup' if app_config['S3_BACKUPS_BUCKET']
|
||||
end
|
||||
|
||||
every 5.minutes do
|
||||
enqueue_job 'HeartbeatJob', priority: 0
|
||||
enqueue_job 'SubscriptionPlacementJob', priority: 0
|
||||
enqueue_job 'SubscriptionConfirmJob', priority: 0
|
||||
end
|
||||
|
||||
16
config/sidekiq.yml
Normal file
16
config/sidekiq.yml
Normal file
@@ -0,0 +1,16 @@
|
||||
---
|
||||
|
||||
:verbose: false
|
||||
:concurrency: 5
|
||||
|
||||
:queues:
|
||||
- default
|
||||
- mailers
|
||||
|
||||
:schedule:
|
||||
HeartbeatJob:
|
||||
every: "5m"
|
||||
SubscriptionPlacementJob:
|
||||
every: "5m"
|
||||
SubscriptionConfirmJob:
|
||||
every: "5m"
|
||||
@@ -62,7 +62,7 @@ def create_admin_user
|
||||
role = Spree::Role.find_or_create_by(name: 'admin')
|
||||
admin.spree_roles << role
|
||||
admin.save
|
||||
say "Done!"
|
||||
say "New admin user persisted!"
|
||||
else
|
||||
say "There was some problems with persisting new admin user:"
|
||||
admin.errors.full_messages.each do |error|
|
||||
|
||||
@@ -12,6 +12,8 @@ services:
|
||||
- 5432:5432
|
||||
volumes:
|
||||
- 'postgres:/var/lib/postgresql/data'
|
||||
redis:
|
||||
image: redis
|
||||
web:
|
||||
tty: true
|
||||
stdin_open: true
|
||||
@@ -25,8 +27,11 @@ services:
|
||||
- ./config/application.yml.example:/usr/src/app/config/application.yml
|
||||
depends_on:
|
||||
- db
|
||||
- redis
|
||||
environment:
|
||||
OFN_DB_HOST: db
|
||||
OFN_REDIS_URL: redis://redis/
|
||||
OFN_REDIS_JOBS_URL: redis://redis
|
||||
command: >
|
||||
bash -c "wait-for-it -t 30 db:5432 &&
|
||||
rm -f tmp/pids/server.pid &&
|
||||
@@ -44,8 +49,11 @@ services:
|
||||
- ./config/application.yml.example:/usr/src/app/config/application.yml
|
||||
depends_on:
|
||||
- db
|
||||
- redis
|
||||
environment:
|
||||
OFN_DB_HOST: db
|
||||
OFN_REDIS_URL: redis://redis
|
||||
OFN_REDIS_JOBS_URL: redis://redis
|
||||
command: >
|
||||
bash -c "wait-for-it -t 30 db:5432 &&
|
||||
(bundle check || bundle install)
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails/all'
|
||||
require 'active_merchant'
|
||||
require 'acts_as_list'
|
||||
require 'awesome_nested_set'
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
"@storybook/addon-docs": "^6.2.9",
|
||||
"@storybook/server": "^6.2.9",
|
||||
"jasmine-core": "~2.4.1",
|
||||
"karma": "~6.3.2",
|
||||
"karma": "~6.3.3",
|
||||
"karma-chrome-launcher": "~3.1.0",
|
||||
"karma-coffee-preprocessor": "~1.0.1",
|
||||
"karma-jasmine": "~0.3.8"
|
||||
|
||||
@@ -6,7 +6,7 @@ describe Admin::StripeAccountsController, type: :controller do
|
||||
let(:enterprise) { create(:distributor_enterprise) }
|
||||
|
||||
before do
|
||||
allow(Stripe).to receive(:client_id) { "some_id" }
|
||||
Stripe.client_id = "some_id"
|
||||
end
|
||||
|
||||
describe "#connect" do
|
||||
@@ -86,7 +86,7 @@ describe Admin::StripeAccountsController, type: :controller do
|
||||
end
|
||||
|
||||
before do
|
||||
allow(Stripe).to receive(:api_key) { "sk_test_12345" }
|
||||
Stripe.api_key = "sk_test_12345"
|
||||
Spree::Config.set(stripe_connect_enabled: false)
|
||||
end
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ describe Admin::StripeConnectSettingsController, type: :controller do
|
||||
|
||||
context "when a Stripe API key is not set" do
|
||||
before do
|
||||
allow(Stripe).to receive(:api_key) { nil }
|
||||
Stripe.api_key = nil
|
||||
end
|
||||
|
||||
it "sets the account status to :empty_api_key_error_html" do
|
||||
@@ -42,7 +42,7 @@ describe Admin::StripeConnectSettingsController, type: :controller do
|
||||
|
||||
context "when a Stripe API key is set" do
|
||||
before do
|
||||
allow(Stripe).to receive(:api_key) { "sk_test_xxxx" }
|
||||
Stripe.api_key = "sk_test_xxxx"
|
||||
end
|
||||
|
||||
context "and the request to retrieve Stripe account info fails" do
|
||||
|
||||
@@ -75,15 +75,24 @@ describe Api::V0::EnterprisesController, type: :controller do
|
||||
end
|
||||
|
||||
describe "submitting a valid image" do
|
||||
let!(:logo) { fixture_file_upload("files/logo.png", "image/png") }
|
||||
before do
|
||||
allow(Enterprise)
|
||||
.to receive(:find_by).with({ permalink: enterprise.id.to_s }) { enterprise }
|
||||
allow(enterprise).to receive(:update).and_return(true)
|
||||
end
|
||||
|
||||
it "I can update enterprise image" do
|
||||
api_post :update_image, logo: 'a logo', id: enterprise.id
|
||||
it "I can update enterprise logo image" do
|
||||
api_post :update_image, logo: logo, id: enterprise.id
|
||||
expect(response.status).to eq 200
|
||||
expect(response.content_type).to eq "text/html"
|
||||
expect(response.body).to match %r{/images/enterprises/logos/\d*/medium/logo\.png\?\d*}
|
||||
end
|
||||
|
||||
it "I can update enterprise promo image" do
|
||||
api_post :update_image, promo: logo, id: enterprise.id
|
||||
expect(response.status).to eq 200
|
||||
expect(response.content_type).to eq "text/html"
|
||||
expect(response.body).to match %r{/images/enterprises/promo_images/\d*/medium/logo\.jpg\?\d*}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -153,7 +153,7 @@ describe CheckoutController, type: :controller do
|
||||
}
|
||||
|
||||
before do
|
||||
allow(Stripe).to receive(:api_key) { "sk_test_12345" }
|
||||
Stripe.api_key = "sk_test_12345"
|
||||
stub_payment_intent_get_request
|
||||
stub_successful_capture_request(order: order)
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ describe Spree::Admin::PaymentsController, type: :controller do
|
||||
end
|
||||
|
||||
before do
|
||||
allow(Stripe).to receive(:api_key) { "sk_test_12345" }
|
||||
Stripe.api_key = "sk_test_12345"
|
||||
end
|
||||
|
||||
context "where the request succeeds" do
|
||||
@@ -90,7 +90,7 @@ describe Spree::Admin::PaymentsController, type: :controller do
|
||||
end
|
||||
|
||||
before do
|
||||
allow(Stripe).to receive(:api_key) { "sk_test_12345" }
|
||||
Stripe.api_key = "sk_test_12345"
|
||||
end
|
||||
|
||||
context "where the request succeeds" do
|
||||
@@ -152,7 +152,7 @@ describe Spree::Admin::PaymentsController, type: :controller do
|
||||
let(:stripe_account) { create(:stripe_account, enterprise: shop) }
|
||||
|
||||
before do
|
||||
allow(Stripe).to receive(:api_key) { "sk_test_12345" }
|
||||
Stripe.api_key = "sk_test_12345"
|
||||
allow(StripeAccount).to receive(:find_by) { stripe_account }
|
||||
end
|
||||
|
||||
@@ -236,7 +236,7 @@ describe Spree::Admin::PaymentsController, type: :controller do
|
||||
end
|
||||
|
||||
before do
|
||||
allow(Stripe).to receive(:api_key) { "sk_test_12345" }
|
||||
Stripe.api_key = "sk_test_12345"
|
||||
|
||||
stub_payment_intent_get_request stripe_account_header: false
|
||||
end
|
||||
|
||||
@@ -7,7 +7,7 @@ describe Spree::CreditCardsController, type: :controller do
|
||||
let(:token) { "tok_234bd2c22" }
|
||||
|
||||
before do
|
||||
allow(Stripe).to receive(:api_key) { "sk_test_12345" }
|
||||
Stripe.api_key = "sk_test_12345"
|
||||
allow(controller).to receive(:spree_current_user) { user }
|
||||
end
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ require 'spec_helper'
|
||||
describe Spree::OrdersController, type: :controller do
|
||||
include OpenFoodNetwork::EmailHelper
|
||||
include CheckoutHelper
|
||||
include StripeStubs
|
||||
|
||||
let(:distributor) { double(:distributor) }
|
||||
let(:order) { create(:order) }
|
||||
@@ -163,7 +164,7 @@ describe Spree::OrdersController, type: :controller do
|
||||
it "does not complete the payment" do
|
||||
get :show, params: { id: order.number, payment_intent: payment_intent }
|
||||
|
||||
expect(response).to be_success
|
||||
expect(response.status).to eq 200
|
||||
expect(flash[:error]).to eq("#{I18n.t("payment_could_not_process")}. error message")
|
||||
payment.reload
|
||||
expect(payment.cvv_response_message).to eq("https://stripe.com/redirect")
|
||||
@@ -178,11 +179,11 @@ describe Spree::OrdersController, type: :controller do
|
||||
before do
|
||||
allow(payment).to receive(:response_code).and_return("invalid")
|
||||
allow(OrderPaymentFinder).to receive(:new).with(order).and_return(finder)
|
||||
|
||||
allow_any_instance_of(Stripe::PaymentIntentValidator)
|
||||
.to receive(:call)
|
||||
.with(payment_intent, kind_of(String))
|
||||
.and_return(payment_intent)
|
||||
stub_payment_intent_get_request(payment_intent_id: "valid")
|
||||
end
|
||||
|
||||
it "does not complete the payment" do
|
||||
|
||||
@@ -36,10 +36,8 @@ describe UserPasswordsController, type: :controller do
|
||||
|
||||
it "renders Darkswarm" do
|
||||
setup_email
|
||||
clear_jobs
|
||||
|
||||
user.send_reset_password_instructions
|
||||
flush_jobs # Send the reset password instructions
|
||||
|
||||
user.reload
|
||||
spree_get :edit, reset_password_token: user.reset_password_token
|
||||
|
||||
103
spec/features/admin/invoice_print_spec.rb
Normal file
103
spec/features/admin/invoice_print_spec.rb
Normal file
@@ -0,0 +1,103 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "spec_helper"
|
||||
|
||||
feature '
|
||||
As an administrator
|
||||
I want to print a invoice as PDF
|
||||
', js: false do
|
||||
include WebHelper
|
||||
include AuthenticationHelper
|
||||
|
||||
let(:user) { create(:user) }
|
||||
let(:product) { create(:simple_product) }
|
||||
let(:distributor) { create(:distributor_enterprise, owner: user, charges_sales_tax: true) }
|
||||
let(:order_cycle) do
|
||||
create(:simple_order_cycle, name: 'One', distributors: [distributor],
|
||||
variants: [product.variants.first])
|
||||
end
|
||||
|
||||
let(:order) do
|
||||
create(:order_with_totals_and_distribution, user: user, distributor: distributor,
|
||||
order_cycle: order_cycle, state: 'complete',
|
||||
payment_state: 'balance_due')
|
||||
end
|
||||
|
||||
describe "that contains right Payment Description at Checkout information" do
|
||||
let!(:payment_method1) do
|
||||
create(:stripe_sca_payment_method, distributors: [distributor], description: "description1")
|
||||
end
|
||||
let!(:payment_method2) do
|
||||
create(:stripe_sca_payment_method, distributors: [distributor], description: "description2")
|
||||
end
|
||||
|
||||
context "with no payment" do
|
||||
it "do not display the payment description information" do
|
||||
login_as_admin_and_visit spree.print_admin_order_path(order)
|
||||
convert_pdf_to_page
|
||||
expect(page).to have_no_content 'Payment Description at Checkout'
|
||||
end
|
||||
end
|
||||
|
||||
context "with one payment" do
|
||||
let!(:payment1) do
|
||||
create(:payment, order: order, state: 'completed', payment_method: payment_method1)
|
||||
end
|
||||
before do
|
||||
order.save!
|
||||
end
|
||||
|
||||
it "display the payment description section" do
|
||||
login_as_admin_and_visit spree.print_admin_order_path(order)
|
||||
convert_pdf_to_page
|
||||
expect(page).to have_content 'Payment Description at Checkout'
|
||||
expect(page).to have_content 'description1'
|
||||
end
|
||||
end
|
||||
|
||||
context "with two payments, and one that failed" do
|
||||
before do
|
||||
order.update payments: []
|
||||
order.payments << create(:payment, order: order, state: 'completed',
|
||||
payment_method: payment_method1, created_at: 1.day.ago)
|
||||
order.payments << create(:payment, order: order, state: 'failed',
|
||||
payment_method: payment_method2, created_at: 2.days.ago)
|
||||
order.save!
|
||||
end
|
||||
|
||||
it "display the payment description section and use the one from the completed payment" do
|
||||
login_as_admin_and_visit spree.print_admin_order_path(order)
|
||||
convert_pdf_to_page
|
||||
expect(page).to have_content 'Payment Description at Checkout'
|
||||
expect(page).to have_content 'description1'
|
||||
end
|
||||
end
|
||||
|
||||
context "with two completed payments" do
|
||||
before do
|
||||
order.update payments: []
|
||||
order.payments << create(:payment, order: order, state: 'completed',
|
||||
payment_method: payment_method1, created_at: 2.days.ago)
|
||||
order.payments << create(:payment, order: order, state: 'completed',
|
||||
payment_method: payment_method2, created_at: 1.day.ago)
|
||||
order.save!
|
||||
end
|
||||
|
||||
it "display the payment description section and use the one from the last payment" do
|
||||
login_as_admin_and_visit spree.print_admin_order_path(order)
|
||||
convert_pdf_to_page
|
||||
expect(page).to have_content 'Payment Description at Checkout'
|
||||
expect(page).to have_content 'description2'
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def convert_pdf_to_page
|
||||
temp_pdf = Tempfile.new('pdf')
|
||||
temp_pdf << page.source.force_encoding('UTF-8')
|
||||
reader = PDF::Reader.new(temp_pdf)
|
||||
pdf_text = reader.pages.map(&:text)
|
||||
temp_pdf.close
|
||||
page.driver.response.instance_variable_set('@body', pdf_text)
|
||||
end
|
||||
@@ -47,7 +47,7 @@ feature '
|
||||
|
||||
before do
|
||||
Spree::Config.set(stripe_connect_enabled: true)
|
||||
allow(Stripe).to receive(:api_key) { "sk_test_12345" }
|
||||
Stripe.api_key = "sk_test_12345"
|
||||
stub_request(:get, "https://api.stripe.com/v1/accounts/acc_connected123").to_return(body: JSON.generate(stripe_account_mock))
|
||||
stub_request(:get, "https://api.stripe.com/v1/accounts/acc_revoked123").to_return(status: 404)
|
||||
end
|
||||
|
||||
@@ -5,36 +5,36 @@ require 'spec_helper'
|
||||
feature '
|
||||
As an admin
|
||||
I want to check the unit price of my products/variants
|
||||
' do
|
||||
', js: true do
|
||||
include AuthenticationHelper
|
||||
include WebHelper
|
||||
|
||||
|
||||
let!(:stock_location) { create(:stock_location, backorderable_default: false) }
|
||||
|
||||
|
||||
before do
|
||||
allow(OpenFoodNetwork::FeatureToggle).to receive(:enabled?).with(:unit_price, anything) { true }
|
||||
end
|
||||
|
||||
describe "product", js: true do
|
||||
|
||||
describe "product" do
|
||||
scenario "creating a new product" do
|
||||
login_as_admin_and_visit spree.admin_products_path
|
||||
click_link 'New Product'
|
||||
select "Weight (kg)", from: 'product_variant_unit_with_scale'
|
||||
fill_in 'Value', with: '1'
|
||||
fill_in 'Price', with: '1'
|
||||
|
||||
|
||||
expect(find_field("Unit Price", disabled: true).value).to eq "$1.00 / kg"
|
||||
end
|
||||
end
|
||||
|
||||
describe "variant", js: true do
|
||||
describe "variant" do
|
||||
scenario "creating a new variant" do
|
||||
product = create(:simple_product, variant_unit: "weight", variant_unit_scale: "1")
|
||||
login_as_admin_and_visit spree.admin_product_variants_path product
|
||||
click_link 'New Variant'
|
||||
fill_in 'Weight (g)', with: '1'
|
||||
fill_in 'Price', with: '1'
|
||||
|
||||
|
||||
expect(find_field("Unit Price", disabled: true).value).to eq '$1,000.00 / kg'
|
||||
end
|
||||
|
||||
@@ -43,8 +43,42 @@ feature '
|
||||
variant = product.variants.first
|
||||
variant.update(price: 1.0)
|
||||
login_as_admin_and_visit spree.edit_admin_product_variant_path(product, variant)
|
||||
|
||||
|
||||
expect(find_field("Unit Price", disabled: true).value).to eq '$1,000.00 / kg'
|
||||
end
|
||||
end
|
||||
|
||||
describe "when admin use es as default language (and comma as decimal separator)", :debug do
|
||||
scenario "creating a new product with a comma separated decimal price" do
|
||||
login_as_admin_and_visit spree.admin_dashboard_path(locale: 'es')
|
||||
visit spree.admin_products_path
|
||||
click_link 'Nuevo producto'
|
||||
select "Peso (kg)", from: 'product_variant_unit_with_scale'
|
||||
fill_in 'Valor', with: '1'
|
||||
fill_in 'Precio', with: '1,5'
|
||||
|
||||
expect(find_field("Precio por unidad", disabled: true).value).to eq "1,50 $ / kg"
|
||||
end
|
||||
|
||||
scenario "creating a new variant with a comma separated decimal price" do
|
||||
product = create(:simple_product, variant_unit: "weight", variant_unit_scale: "1")
|
||||
login_as_admin_and_visit spree.admin_dashboard_path(locale: 'es')
|
||||
visit spree.admin_product_variants_path product
|
||||
click_link 'Nueva Variante'
|
||||
fill_in 'Peso (g)', with: '1'
|
||||
fill_in 'Precio', with: '1,5'
|
||||
|
||||
expect(find_field("Precio por unidad", disabled: true).value).to eq '1.500,00 $ / kg'
|
||||
end
|
||||
|
||||
scenario "editing a variant with a comma separated decimal price" do
|
||||
product = create(:simple_product, variant_unit: "weight", variant_unit_scale: "1")
|
||||
variant = product.variants.first
|
||||
variant.update(price: 1.5)
|
||||
login_as_admin_and_visit spree.admin_dashboard_path(locale: 'es')
|
||||
visit spree.edit_admin_product_variant_path(product, variant)
|
||||
|
||||
expect(find_field("Precio por unidad", disabled: true).value).to eq '1.500,00 $ / kg'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -22,8 +22,8 @@ feature "Credit Cards", js: true do
|
||||
before do
|
||||
login_as user
|
||||
|
||||
allow(Stripe).to receive(:api_key) { "sk_test_12345" }
|
||||
allow(Stripe).to receive(:publishable_key) { "some_token" }
|
||||
Stripe.api_key = "sk_test_12345"
|
||||
Stripe.publishable_key = "some_token"
|
||||
Spree::Config.set(stripe_connect_enabled: true)
|
||||
|
||||
stub_request(:get, "https://api.stripe.com/v1/customers/cus_AZNMJ").
|
||||
|
||||
@@ -100,10 +100,20 @@ feature "Registration", js: true do
|
||||
expect(e.charges_sales_tax).to be true
|
||||
|
||||
# Images
|
||||
# Upload logo image
|
||||
attach_file "image-select", Rails.root.join("spec/fixtures/files/logo.png"), visible: false
|
||||
expect(page).to have_no_css('#image-placeholder .loading')
|
||||
expect(page.find('#image-placeholder img')['src']).to_not be_empty
|
||||
|
||||
# Move from logo page
|
||||
click_button "Continue"
|
||||
expect(page).to have_content 'Step 3. Select Promo Image'
|
||||
|
||||
# Upload promo image
|
||||
attach_file "image-select", Rails.root.join("spec/fixtures/files/promo.png"), visible: false
|
||||
expect(page).to have_no_css('#image-placeholder .loading')
|
||||
expect(page.find('#image-placeholder img')['src']).to_not be_empty
|
||||
|
||||
# Move from promo page
|
||||
click_button "Continue"
|
||||
expect(page).to have_content 'How can people find My Awesome Enterprise online?'
|
||||
|
||||
BIN
spec/fixtures/files/logo.png
vendored
Normal file
BIN
spec/fixtures/files/logo.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 6.1 KiB |
BIN
spec/fixtures/files/promo.png
vendored
Normal file
BIN
spec/fixtures/files/promo.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.4 KiB |
@@ -266,7 +266,7 @@ describe EnterprisesHelper, type: :helper do
|
||||
|
||||
before do
|
||||
Spree::Config.set(stripe_connect_enabled: true)
|
||||
allow(Stripe).to receive(:publishable_key) { "some_key" }
|
||||
Stripe.publishable_key = "some_key"
|
||||
end
|
||||
|
||||
it "includes Stripe payment methods with a valid stripe accounts" do
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
describe 'convert string to number with configurated currency', ->
|
||||
filter = null
|
||||
|
||||
beforeEach ->
|
||||
module 'ofn.admin'
|
||||
inject ($filter) ->
|
||||
filter = $filter('unlocalizeCurrency')
|
||||
|
||||
describe "with point as decimal separator and comma as thousands separator for I18n service", ->
|
||||
|
||||
beforeEach ->
|
||||
spyOn(I18n,'toCurrency').and.callFake (arg) ->
|
||||
if (arg == 0.1)
|
||||
return "0.1"
|
||||
else if (arg == 1000)
|
||||
return "1,000"
|
||||
|
||||
it "handle point as decimal separator", ->
|
||||
expect(filter("1.00")).toEqual 1.0
|
||||
|
||||
it "handle point as decimal separator", ->
|
||||
expect(filter("1.000")).toEqual 1.0
|
||||
|
||||
it "also handle comma as decimal separator", ->
|
||||
expect(filter("1,00")).toEqual 1.0
|
||||
|
||||
it "handle point as decimal separator and comma as thousands separator", ->
|
||||
expect(filter("1,000,000.00")).toEqual 1000000
|
||||
|
||||
it "handle integer number", ->
|
||||
expect(filter("10")).toEqual 10
|
||||
|
||||
it "handle integer number with comma as thousands separator", ->
|
||||
expect(filter("1,000")).toEqual 1000
|
||||
|
||||
it "handle integer number with no thousands separator", ->
|
||||
expect(filter("1000")).toEqual 1000
|
||||
|
||||
describe "with comma as decimal separator and final point as thousands separator for I18n service", ->
|
||||
|
||||
beforeEach ->
|
||||
spyOn(I18n,'toCurrency').and.callFake (arg) ->
|
||||
if (arg == 0.1)
|
||||
return "0,1"
|
||||
else if (arg == 1000)
|
||||
return "1.000"
|
||||
|
||||
it "handle comma as decimal separator", ->
|
||||
expect(filter("1,00")).toEqual 1.0
|
||||
|
||||
it "also handle point as decimal separator", ->
|
||||
expect(filter("1.00")).toEqual 1.0
|
||||
|
||||
it "handle point as decimal separator and final point as thousands separator", ->
|
||||
expect(filter("1.000.000,00")).toEqual 1000000
|
||||
|
||||
it "handle integer number", ->
|
||||
expect(filter("10")).toEqual 10
|
||||
|
||||
it "handle integer number with final point as thousands separator", ->
|
||||
expect(filter("1.000")).toEqual 1000
|
||||
|
||||
it "handle integer number with no thousands separator", ->
|
||||
expect(filter("1000")).toEqual 1000
|
||||
|
||||
describe "with comma as decimal separator and space as thousands separator for I18n service", ->
|
||||
|
||||
beforeEach ->
|
||||
spyOn(I18n,'toCurrency').and.callFake (arg) ->
|
||||
if (arg == 0.1)
|
||||
return "0,1"
|
||||
else if (arg == 1000)
|
||||
return "1 000"
|
||||
|
||||
it "handle comma as decimal separator", ->
|
||||
expect(filter("1,00")).toEqual 1.0
|
||||
|
||||
it "also handle final point as decimal separator", ->
|
||||
expect(filter("1.00")).toEqual 1.0
|
||||
|
||||
it "handle point as decimal separator and space as thousands separator", ->
|
||||
expect(filter("1 000 000,00")).toEqual 1000000
|
||||
|
||||
it "handle integer number", ->
|
||||
expect(filter("10")).toEqual 10
|
||||
|
||||
it "handle integer number with space as thousands separator", ->
|
||||
expect(filter("1 000")).toEqual 1000
|
||||
|
||||
it "handle integer number with no thousands separator", ->
|
||||
expect(filter("1000")).toEqual 1000
|
||||
@@ -138,3 +138,19 @@ describe "UnitPrices service", ->
|
||||
unit_value = 453.6
|
||||
expect(UnitPrices.price(price, scale, unit_type, unit_value)).toEqual 1
|
||||
expect(UnitPrices.unit(scale, unit_type)).toEqual "lb"
|
||||
|
||||
describe "get unit price when price is a decimal string", ->
|
||||
unit_type = "weight"
|
||||
|
||||
it "with price: '1,0'", ->
|
||||
price = '1,0'
|
||||
scale = 1
|
||||
unit_value = 1
|
||||
expect(UnitPrices.displayableUnitPrice(price, scale, unit_type, unit_value)).toEqual "$1,000.00 / kg"
|
||||
|
||||
it "with price: '1.0'", ->
|
||||
price = '1.0'
|
||||
scale = 1
|
||||
unit_value = 1
|
||||
expect(UnitPrices.displayableUnitPrice(price, scale, unit_type, unit_value)).toEqual "$1,000.00 / kg"
|
||||
|
||||
@@ -13,16 +13,8 @@ describe HeartbeatJob do
|
||||
end
|
||||
|
||||
it "updates the last_job_queue_heartbeat_at config var" do
|
||||
run_job
|
||||
HeartbeatJob.perform_now
|
||||
expect(Time.parse(Spree::Config.last_job_queue_heartbeat_at).in_time_zone).to eq(run_time)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def run_job
|
||||
clear_jobs
|
||||
HeartbeatJob.perform_now
|
||||
flush_jobs ignore_exceptions: false
|
||||
end
|
||||
end
|
||||
|
||||
@@ -5,6 +5,11 @@ require 'open_food_network/i18n_config'
|
||||
|
||||
module OpenFoodNetwork
|
||||
describe I18nConfig do
|
||||
before do
|
||||
# Allow non-stubbed calls to ENV to proceed
|
||||
allow(ENV).to receive(:[]).and_call_original
|
||||
end
|
||||
|
||||
context "in default test configuration" do
|
||||
before do
|
||||
allow(ENV).to receive(:[]).with("LOCALE").and_return("en")
|
||||
|
||||
@@ -15,7 +15,7 @@ module Stripe
|
||||
let(:connector) { AccountConnector.new(user, params) }
|
||||
|
||||
before do
|
||||
allow(Stripe).to receive(:api_key) { "sk_test_12345" }
|
||||
Stripe.api_key = "sk_test_12345"
|
||||
end
|
||||
|
||||
context "when the connection was cancelled by the user" do
|
||||
|
||||
@@ -24,7 +24,7 @@ module Stripe
|
||||
}
|
||||
|
||||
before do
|
||||
allow(Stripe).to receive(:api_key) { "sk_test_12345" }
|
||||
Stripe.api_key = "sk_test_12345"
|
||||
|
||||
stub_customers_post_request email: credit_card.user.email,
|
||||
response: { customer_id: new_customer_id },
|
||||
|
||||
@@ -12,7 +12,7 @@ module Stripe
|
||||
let(:payment_intent_response_mock) { { status: 200, body: payment_intent_response_body } }
|
||||
|
||||
before do
|
||||
allow(Stripe).to receive(:api_key) { "sk_test_12345" }
|
||||
Stripe.api_key = "sk_test_12345"
|
||||
|
||||
stub_request(:get, "https://api.stripe.com/v1/payment_intents/#{payment_intent_id}")
|
||||
.with(headers: { 'Stripe-Account' => stripe_account_id })
|
||||
|
||||
@@ -14,7 +14,7 @@ module Stripe
|
||||
let(:customer_response_mock) { { status: 200, body: customer_response_body } }
|
||||
|
||||
before do
|
||||
allow(Stripe).to receive(:api_key) { "sk_test_12345" }
|
||||
Stripe.api_key = "sk_test_12345"
|
||||
|
||||
stub_request(:post, "https://api.stripe.com/v1/customers")
|
||||
.with(basic_auth: ["sk_test_12345", ""], body: { email: payment.order.email })
|
||||
|
||||
@@ -15,7 +15,7 @@ describe Spree::Gateway::StripeConnect, type: :model do
|
||||
let(:stripe_account_id) { "acct_123" }
|
||||
|
||||
before do
|
||||
allow(Stripe).to receive(:api_key) { "sk_test_123456" }
|
||||
Stripe.api_key = "sk_test_123456"
|
||||
allow(subject).to receive(:stripe_account_id) { stripe_account_id }
|
||||
allow(subject).to receive(:options_for_purchase_or_auth).and_return(['money', 'cc', 'opts'])
|
||||
allow(subject).to receive(:provider).and_return provider
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe Spree::Gateway::StripeSCA, type: :model do
|
||||
before { allow(Stripe).to receive(:api_key) { "sk_test_12345" } }
|
||||
before { Stripe.api_key = "sk_test_12345" }
|
||||
|
||||
describe "#purchase" do
|
||||
let(:order) { create(:order_with_totals_and_distribution) }
|
||||
|
||||
@@ -12,8 +12,8 @@ describe StripeAccount do
|
||||
let!(:stripe_account) { create(:stripe_account, enterprise: enterprise, stripe_user_id: stripe_user_id) }
|
||||
|
||||
before do
|
||||
allow(Stripe).to receive(:api_key) { "sk_test_12345" }
|
||||
allow(Stripe).to receive(:client_id) { client_id }
|
||||
Stripe.api_key = "sk_test_12345"
|
||||
Stripe.client_id = client_id
|
||||
end
|
||||
|
||||
context "when the Stripe API disconnect fails" do
|
||||
|
||||
@@ -68,7 +68,7 @@ describe "checking out an order with a Stripe Connect payment method", type: :re
|
||||
allow(OrderCycleDistributedVariants).to receive(:new) { order_cycle_distributed_variants }
|
||||
allow(order_cycle_distributed_variants).to receive(:distributes_order_variants?) { true }
|
||||
|
||||
allow(Stripe).to receive(:api_key) { "sk_test_12345" }
|
||||
Stripe.api_key = "sk_test_12345"
|
||||
order.update(distributor_id: enterprise.id, order_cycle_id: order_cycle.id)
|
||||
order.reload.update_totals
|
||||
set_order order
|
||||
|
||||
@@ -87,7 +87,7 @@ describe "checking out an order with a Stripe SCA payment method", type: :reques
|
||||
allow(OrderCycleDistributedVariants).to receive(:new) { order_cycle_distributed_variants }
|
||||
allow(order_cycle_distributed_variants).to receive(:distributes_order_variants?) { true }
|
||||
|
||||
allow(Stripe).to receive(:api_key) { "sk_test_12345" }
|
||||
Stripe.api_key = "sk_test_12345"
|
||||
order.update(distributor_id: enterprise.id, order_cycle_id: order_cycle.id)
|
||||
order.reload.update_totals
|
||||
set_order order
|
||||
|
||||
@@ -199,7 +199,6 @@ RSpec.configure do |config|
|
||||
config.include OpenFoodNetwork::DistributionHelper
|
||||
config.include OpenFoodNetwork::HtmlHelper
|
||||
config.include ActionView::Helpers::DateHelper
|
||||
config.include OpenFoodNetwork::DelayedJobHelper
|
||||
config.include OpenFoodNetwork::PerformanceHelper
|
||||
config.include DownloadsHelper, type: :feature
|
||||
config.include ActiveJob::TestHelper
|
||||
|
||||
@@ -1,70 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module OpenFoodNetwork
|
||||
module DelayedJobHelper
|
||||
# Process all pending Delayed jobs, keeping in mind jobs could spawn new
|
||||
# delayed job (so things might be added to the queue while processing)
|
||||
def flush_jobs(options = {})
|
||||
options[:ignore_exceptions] ||= false
|
||||
|
||||
Delayed::Worker.new.work_off(100)
|
||||
|
||||
unless options[:ignore_exceptions]
|
||||
Delayed::Job.all.each do |job|
|
||||
if job.last_error.present?
|
||||
throw "There was an error in a delayed job: #{job.last_error}"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def clear_jobs
|
||||
Delayed::Job.delete_all
|
||||
end
|
||||
|
||||
# expect { foo }.to enqueue_job MyJob, field1: 'foo', field2: 'bar'
|
||||
RSpec::Matchers.define :enqueue_job do |klass, options = {}|
|
||||
match do |event_proc|
|
||||
last_job_id_before = Delayed::Job.last.andand.id || 0
|
||||
|
||||
begin
|
||||
event_proc.call
|
||||
rescue StandardError => e
|
||||
@exception = e
|
||||
raise e
|
||||
end
|
||||
|
||||
@jobs_created = Delayed::Job.where('id > ?', last_job_id_before)
|
||||
|
||||
@jobs_created.any? do |job|
|
||||
job = job.payload_object
|
||||
|
||||
match = true
|
||||
match &= (job.class == klass)
|
||||
|
||||
options.each_pair do |k, v|
|
||||
begin
|
||||
match &= (job[k] == v)
|
||||
rescue NameError
|
||||
match = false
|
||||
end
|
||||
end
|
||||
|
||||
match
|
||||
end
|
||||
end
|
||||
|
||||
failure_message do |_event_proc|
|
||||
@exception || "expected #{klass} to be enqueued matching #{options.inspect} (#{@jobs_created.count} others enqueued)"
|
||||
end
|
||||
|
||||
failure_message_when_negated do |_event_proc|
|
||||
@exception || "expected #{klass} to not be enqueued matching #{options.inspect}"
|
||||
end
|
||||
|
||||
def supports_block_expectations?
|
||||
true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -30,8 +30,8 @@ module StripeHelper
|
||||
end
|
||||
|
||||
def setup_stripe
|
||||
allow(Stripe).to receive(:api_key) { "sk_test_12345" }
|
||||
allow(Stripe).to receive(:publishable_key) { "pk_test_12345" }
|
||||
Stripe.api_key = "sk_test_12345"
|
||||
Stripe.publishable_key = "pk_test_12345"
|
||||
Spree::Config.set(stripe_connect_enabled: true)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -14,8 +14,8 @@ module StripeStubs
|
||||
.to_return(payment_intent_redirect_response_mock(redirect_url))
|
||||
end
|
||||
|
||||
def stub_payment_intent_get_request(response: {}, stripe_account_header: true)
|
||||
stub = stub_request(:get, "https://api.stripe.com/v1/payment_intents/pi_123")
|
||||
def stub_payment_intent_get_request(response: {}, stripe_account_header: true, payment_intent_id: "pi_123")
|
||||
stub = stub_request(:get, "https://api.stripe.com/v1/payment_intents/#{payment_intent_id}")
|
||||
stub = stub.with(headers: { 'Stripe-Account' => 'abc123' }) if stripe_account_header
|
||||
stub.to_return(payment_intent_authorize_response_mock(response))
|
||||
end
|
||||
@@ -37,7 +37,6 @@ module StripeStubs
|
||||
|
||||
def stub_retrieve_payment_method_request(payment_method_id = "pm_1234")
|
||||
stub_request(:get, "https://api.stripe.com/v1/payment_methods/#{payment_method_id}")
|
||||
.with(headers: { 'Authorization' => 'Bearer sk_test_12345' })
|
||||
.to_return(retrieve_payment_method_response_mock({}))
|
||||
end
|
||||
|
||||
@@ -52,7 +51,7 @@ module StripeStubs
|
||||
def stub_list_customers_request(email:, response: {})
|
||||
stub = stub_request(:get, "https://api.stripe.com/v1/customers?email=#{email}&limit=100")
|
||||
stub = stub.with(
|
||||
headers: { 'Authorization' => 'Bearer sk_test_12345', 'Stripe-Account' => 'abc123' }
|
||||
headers: { 'Stripe-Account' => 'abc123' }
|
||||
)
|
||||
stub.to_return(list_customers_response_mock(response))
|
||||
end
|
||||
@@ -62,7 +61,7 @@ module StripeStubs
|
||||
:get, "https://api.stripe.com/v1/payment_methods?customer=#{customer}&limit=100&type=card"
|
||||
)
|
||||
stub = stub.with(
|
||||
headers: { 'Authorization' => 'Bearer sk_test_12345', 'Stripe-Account' => 'abc123' }
|
||||
headers: { 'Stripe-Account' => 'abc123' }
|
||||
)
|
||||
stub.to_return(get_customer_payment_methods_response_mock(response))
|
||||
end
|
||||
@@ -71,7 +70,7 @@ module StripeStubs
|
||||
stub = stub_request(:post, "https://api.stripe.com/v1/payment_methods/#{payment_method}")
|
||||
stub = stub.with(body: { metadata: { "ofn-clone": true } })
|
||||
stub = stub.with(
|
||||
headers: { 'Authorization' => 'Bearer sk_test_12345', 'Stripe-Account' => 'abc123' }
|
||||
headers: { 'Stripe-Account' => 'abc123' }
|
||||
)
|
||||
stub.to_return(add_metadata_response_mock(response))
|
||||
end
|
||||
|
||||
14
yarn.lock
14
yarn.lock
@@ -5838,10 +5838,10 @@ karma-jasmine@~0.3.8:
|
||||
resolved "https://registry.yarnpkg.com/karma-jasmine/-/karma-jasmine-0.3.8.tgz#5b6457791ad9b89aa173f079e3ebe1b8c805236c"
|
||||
integrity sha1-W2RXeRrZuJqhc/B54+vhuMgFI2w=
|
||||
|
||||
karma@~6.3.2:
|
||||
version "6.3.2"
|
||||
resolved "https://registry.yarnpkg.com/karma/-/karma-6.3.2.tgz#24b62fbae3e8b5218cc32a0dac49ad08a541e76d"
|
||||
integrity sha512-fo4Wt0S99/8vylZMxNj4cBFyOBBnC1bewZ0QOlePij/2SZVWxqbyLeIddY13q6URa2EpLRW8ixvFRUMjkmo1bw==
|
||||
karma@~6.3.3:
|
||||
version "6.3.3"
|
||||
resolved "https://registry.yarnpkg.com/karma/-/karma-6.3.3.tgz#bd04c7c533f8de99b3c3e85e191d0a6ae2621ad1"
|
||||
integrity sha512-JRAujkKWaOtO2LmyPH7K2XXRhrxuFAn9loIL9+iiah6vjz+ZLkqdKsySV9clRITGhj10t9baIfbCl6CJ5hu9gQ==
|
||||
dependencies:
|
||||
body-parser "^1.19.0"
|
||||
braces "^3.0.2"
|
||||
@@ -9255,9 +9255,9 @@ write-file-atomic@^3.0.0:
|
||||
typedarray-to-buffer "^3.1.5"
|
||||
|
||||
ws@~7.4.2:
|
||||
version "7.4.4"
|
||||
resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.4.tgz#383bc9742cb202292c9077ceab6f6047b17f2d59"
|
||||
integrity sha512-Qm8k8ojNQIMx7S+Zp8u/uHOx7Qazv3Yv4q68MiWWWOJhiwG5W3x7iqmRtJo8xxrciZUY4vRxUTJCKuRnF28ZZw==
|
||||
version "7.4.6"
|
||||
resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.6.tgz#5654ca8ecdeee47c33a9a4bf6d28e2be2980377c"
|
||||
integrity sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==
|
||||
|
||||
xtend@^4.0.0, xtend@^4.0.1, xtend@~4.0.1:
|
||||
version "4.0.2"
|
||||
|
||||
Reference in New Issue
Block a user