mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-01-13 18:46:49 +00:00
Compare commits
68 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b1bfac5144 | ||
|
|
01f8aff3e0 | ||
|
|
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 | ||
|
|
ed6b7f1ab4 | ||
|
|
4453123944 | ||
|
|
122ba385f7 |
@@ -1 +1 @@
|
||||
2.5.8
|
||||
2.5.9
|
||||
|
||||
25
Dockerfile
25
Dockerfile
@@ -7,7 +7,23 @@ 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
|
||||
@@ -19,11 +35,10 @@ 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
|
||||
|
||||
|
||||
@@ -47,7 +47,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:
|
||||
|
||||
|
||||
11
Gemfile
11
Gemfile
@@ -1,7 +1,7 @@
|
||||
# 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'
|
||||
@@ -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'
|
||||
|
||||
@@ -84,6 +83,8 @@ gem 'roadie-rails', '~> 2.2.0'
|
||||
|
||||
gem 'redis', '>= 4.0', require: ['redis', 'redis/connection/hiredis']
|
||||
gem 'hiredis'
|
||||
gem 'sidekiq'
|
||||
gem 'sidekiq-scheduler'
|
||||
|
||||
gem 'combine_pdf'
|
||||
gem 'wicked_pdf'
|
||||
@@ -155,6 +156,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 +173,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
|
||||
|
||||
57
Gemfile.lock
57
Gemfile.lock
@@ -47,6 +47,7 @@ PATH
|
||||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
Ascii85 (1.1.0)
|
||||
actioncable (5.2.6)
|
||||
actionpack (= 5.2.6)
|
||||
nio4r (~> 2.0)
|
||||
@@ -113,6 +114,7 @@ GEM
|
||||
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)
|
||||
@@ -184,6 +186,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)
|
||||
@@ -201,11 +204,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,8 +216,10 @@ 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)
|
||||
et-orbi (1.2.4)
|
||||
tzinfo
|
||||
excon (0.79.0)
|
||||
execjs (2.7.0)
|
||||
factory_bot (6.2.0)
|
||||
@@ -267,6 +267,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 +286,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)
|
||||
@@ -352,8 +356,6 @@ 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)
|
||||
mini_portile2 (~> 2.5.0)
|
||||
@@ -384,6 +386,12 @@ 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)
|
||||
@@ -393,6 +401,7 @@ GEM
|
||||
byebug (~> 11.0)
|
||||
pry (~> 0.13.0)
|
||||
public_suffix (4.0.6)
|
||||
raabro (1.4.0)
|
||||
racc (1.5.2)
|
||||
rack (2.2.3)
|
||||
rack-mini-profiler (2.3.2)
|
||||
@@ -519,6 +528,8 @@ GEM
|
||||
ruby-rc4 (0.1.5)
|
||||
ruby2_keywords (0.0.2)
|
||||
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)
|
||||
@@ -534,17 +545,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)
|
||||
spring (2.1.1)
|
||||
spring-commands-rspec (1.0.4)
|
||||
spring (>= 0.9.1)
|
||||
@@ -566,12 +583,15 @@ GEM
|
||||
stripe (5.30.0)
|
||||
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)
|
||||
@@ -587,7 +607,7 @@ GEM
|
||||
get_process_mem (~> 0)
|
||||
unicorn (>= 4, < 7)
|
||||
uniform_notifier (1.14.1)
|
||||
view_component (2.31.1)
|
||||
view_component (2.32.0)
|
||||
activesupport (>= 5.0.0, < 7.0)
|
||||
view_component_storybook (0.8.0)
|
||||
view_component (>= 2.2)
|
||||
@@ -651,12 +671,10 @@ 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
|
||||
@@ -695,6 +713,7 @@ DEPENDENCIES
|
||||
paperclip (~> 3.4.1)
|
||||
paranoia (~> 2.4)
|
||||
paypal-sdk-merchant (= 1.117.2)
|
||||
pdf-reader
|
||||
pg (~> 1.2.3)
|
||||
pry
|
||||
pry-byebug
|
||||
@@ -721,6 +740,8 @@ DEPENDENCIES
|
||||
select2-rails (~> 3.4.7)
|
||||
selenium-webdriver
|
||||
shoulda-matchers
|
||||
sidekiq
|
||||
sidekiq-scheduler
|
||||
simplecov
|
||||
spring
|
||||
spring-commands-rspec
|
||||
@@ -743,7 +764,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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -189,7 +189,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
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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'))
|
||||
|
||||
11
config/initializers/sidekiq.rb
Normal file
11
config/initializers/sidekiq.rb
Normal file
@@ -0,0 +1,11 @@
|
||||
if Rails.env.production? || Rails.env.staging?
|
||||
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
|
||||
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>"
|
||||
|
||||
@@ -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>"
|
||||
|
||||
@@ -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|
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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 |
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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