mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-01-17 19:26:48 +00:00
Compare commits
158 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
74f27544f7 | ||
|
|
5868765087 | ||
|
|
545d64a2e5 | ||
|
|
c69dee4c96 | ||
|
|
b367001b95 | ||
|
|
120fc4ca42 | ||
|
|
e4756a523a | ||
|
|
46843a5efa | ||
|
|
6377736f43 | ||
|
|
e90403dbbe | ||
|
|
3dc3581e6b | ||
|
|
ff82f70e9a | ||
|
|
560f462f7b | ||
|
|
23b2b5ba56 | ||
|
|
11cb8cbbdc | ||
|
|
41799b2663 | ||
|
|
2f842bcbdd | ||
|
|
336a8b5825 | ||
|
|
d2f54f5bd2 | ||
|
|
8c81c14c8d | ||
|
|
1f6d872fa5 | ||
|
|
ae1b9b8dd5 | ||
|
|
1e1706d371 | ||
|
|
5ccaa521cf | ||
|
|
90bb9870ab | ||
|
|
70ac719725 | ||
|
|
08d540a761 | ||
|
|
304a3804bc | ||
|
|
f7726e552a | ||
|
|
a1ac4e85ed | ||
|
|
f8e5370b0b | ||
|
|
fb560089b9 | ||
|
|
341f6c9f62 | ||
|
|
b2e97fe1d2 | ||
|
|
e73584fef7 | ||
|
|
45ad4bbcf1 | ||
|
|
096847ea07 | ||
|
|
faf6a37c9f | ||
|
|
d4ec1bda54 | ||
|
|
5560a99423 | ||
|
|
0c4e191f3b | ||
|
|
2bb38619ea | ||
|
|
4b352da402 | ||
|
|
75243b8e6a | ||
|
|
7df2915fbd | ||
|
|
6427a3846b | ||
|
|
5169ee91ea | ||
|
|
5917accdd2 | ||
|
|
5dd24623f7 | ||
|
|
befb6f632f | ||
|
|
92e0f8349c | ||
|
|
ffbba01c41 | ||
|
|
5f9679655c | ||
|
|
6ded80d2c6 | ||
|
|
eb3c33b091 | ||
|
|
794216713a | ||
|
|
a2862e604c | ||
|
|
8429da3d2a | ||
|
|
381b0e78d5 | ||
|
|
2e63cd8116 | ||
|
|
52e0d84238 | ||
|
|
5725535715 | ||
|
|
05ed98aa0c | ||
|
|
fd021d4778 | ||
|
|
2b9f9fce86 | ||
|
|
81aac442f2 | ||
|
|
16e3af9b49 | ||
|
|
227bdd7d4c | ||
|
|
471a7903f6 | ||
|
|
37177e7207 | ||
|
|
5805104d13 | ||
|
|
e686a4f627 | ||
|
|
c7f80d86a8 | ||
|
|
19187583e1 | ||
|
|
f2c3b096a0 | ||
|
|
816d752dc8 | ||
|
|
0a880a2bf3 | ||
|
|
d6b3b0a3d3 | ||
|
|
ca38948e21 | ||
|
|
fe67c01e57 | ||
|
|
37053239c0 | ||
|
|
2bb5a4b11f | ||
|
|
cea3ee4ef9 | ||
|
|
90db52e5f5 | ||
|
|
b1896733ca | ||
|
|
a949422ac9 | ||
|
|
0243e5cbb8 | ||
|
|
ebdbfe0027 | ||
|
|
b680697af6 | ||
|
|
2e248744c0 | ||
|
|
82a6befce7 | ||
|
|
ccef65039a | ||
|
|
e4a670da5a | ||
|
|
c930b2ee60 | ||
|
|
4932e1dcb5 | ||
|
|
536281ec80 | ||
|
|
367cee593f | ||
|
|
99cf23df26 | ||
|
|
f49d4592a0 | ||
|
|
7f27544acb | ||
|
|
2aac44d95e | ||
|
|
8f921b8b08 | ||
|
|
dfe485b079 | ||
|
|
ad9096b5a8 | ||
|
|
e60a513c88 | ||
|
|
1f8e731594 | ||
|
|
d69ef31bf9 | ||
|
|
9ae7c5efbc | ||
|
|
902bbf7dc4 | ||
|
|
d29ef0d7b1 | ||
|
|
d2a3d9049f | ||
|
|
0cd6c53e0d | ||
|
|
5475b79cde | ||
|
|
8e24c655b0 | ||
|
|
bb5452ad26 | ||
|
|
85b8e9b51f | ||
|
|
3239c893ba | ||
|
|
17a0063b40 | ||
|
|
75dc7af0ed | ||
|
|
cb15e28cef | ||
|
|
cbefa5f882 | ||
|
|
231f01dad2 | ||
|
|
c14ccdc21c | ||
|
|
fcf70c242e | ||
|
|
a0476be2c9 | ||
|
|
24a5407c8f | ||
|
|
66da72ccc2 | ||
|
|
6a342ae368 | ||
|
|
dd851edbdc | ||
|
|
e485a4a8ef | ||
|
|
026942dd72 | ||
|
|
237ebd6ec4 | ||
|
|
a4d6e69309 | ||
|
|
29e04dd8c8 | ||
|
|
5a8e271037 | ||
|
|
43e41f4980 | ||
|
|
fd5e0fd60f | ||
|
|
de000228cf | ||
|
|
a2de86c23e | ||
|
|
00c4a28d22 | ||
|
|
8e10f7af0e | ||
|
|
135a311c05 | ||
|
|
13bb5aa8dd | ||
|
|
a476416dc4 | ||
|
|
19768e1398 | ||
|
|
7c2d77a3ee | ||
|
|
2560757ea2 | ||
|
|
e290c128bf | ||
|
|
95a73704a2 | ||
|
|
b843b871f6 | ||
|
|
925676f136 | ||
|
|
d3f41f14c7 | ||
|
|
045ce73c83 | ||
|
|
932d000c9d | ||
|
|
84285ff985 | ||
|
|
8b06a735ac | ||
|
|
153ec268b7 | ||
|
|
92eaf5fbaa |
5
.github/codecov.yml
vendored
Normal file
5
.github/codecov.yml
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
coverage:
|
||||
status:
|
||||
project:
|
||||
default:
|
||||
informational: true
|
||||
2
.github/workflows/build.yml
vendored
2
.github/workflows/build.yml
vendored
@@ -322,4 +322,4 @@ jobs:
|
||||
run: bundle exec rspec --profile --pattern "engines/*/spec/{,/*/**}/*_spec.rb,spec/features/admin/*/*_spec.rb,spec/lib/{,/*/**}/*_spec.rb"
|
||||
|
||||
- name: Codecov
|
||||
uses: codecov/codecov-action@v1.3.1
|
||||
uses: codecov/codecov-action@v1.5.0
|
||||
|
||||
@@ -1 +1 @@
|
||||
5.12.0
|
||||
14.16.1
|
||||
|
||||
@@ -6,7 +6,7 @@ This is a general guide to setting up an Open Food Network **development environ
|
||||
|
||||
The fastest way to make it work locally is to use Docker, you only need to setup git, see the [Docker setup guide](docker/README.md).
|
||||
Otherwise, for a local setup you will need:
|
||||
* Ruby 2.4.4 and bundler (check current Ruby version in [.ruby-version](https://github.com/openfoodfoundation/openfoodnetwork/blob/master/.ruby-version) file)
|
||||
* Ruby and bundler (check current Ruby version in [.ruby-version](https://github.com/openfoodfoundation/openfoodnetwork/blob/master/.ruby-version) file)
|
||||
* PostgreSQL database
|
||||
* Chrome (for testing)
|
||||
|
||||
@@ -78,8 +78,6 @@ Note: If your OS is not explicitly supported in the setup guides then not all te
|
||||
|
||||
Note: The time zone on your machine should match the one defined in `config/application.yml`.
|
||||
|
||||
The project is configured to use [Zeus][zeus] to reduce the pre-test startup time while Rails loads. See the [Zeus GitHub page][zeus] for usage instructions.
|
||||
|
||||
Once [npm dependencies are installed][karma], AngularJS tests can be run with:
|
||||
|
||||
./script/karma run
|
||||
@@ -119,7 +117,6 @@ If these commands succeed, you should be able to [continue the setup process](#g
|
||||
[ubuntu]: https://github.com/openfoodfoundation/openfoodnetwork/wiki/Development-Environment-Setup:-Ubuntu
|
||||
[debian]: https://github.com/openfoodfoundation/openfoodnetwork/wiki/Development-Environment-Setup:-Debian
|
||||
[wiki]: https://github.com/openfoodfoundation/openfoodnetwork/wiki
|
||||
[zeus]: https://github.com/burke/zeus
|
||||
[rubocop]: https://rubocop.readthedocs.io/en/latest/
|
||||
[karma]: https://github.com/openfoodfoundation/openfoodnetwork/wiki/Karma
|
||||
[slack-dev]: https://openfoodnetwork.slack.com/messages/C2GQ45KNU
|
||||
|
||||
8
Gemfile
8
Gemfile
@@ -15,7 +15,7 @@ gem 'sass', '<= 4.7.1'
|
||||
gem 'sass-rails', '< 6.0.0'
|
||||
|
||||
gem 'i18n'
|
||||
gem 'i18n-js', '~> 3.8.2'
|
||||
gem 'i18n-js', '~> 3.8.3'
|
||||
gem 'rails-i18n'
|
||||
gem 'rails_safe_tasks', '~> 1.0'
|
||||
|
||||
@@ -82,6 +82,9 @@ gem 'rack-rewrite'
|
||||
gem 'rack-ssl', require: 'rack/ssl'
|
||||
gem 'roadie-rails', '~> 2.2.0'
|
||||
|
||||
gem 'redis', '>= 4.0', require: ['redis', 'redis/connection/hiredis']
|
||||
gem 'hiredis'
|
||||
|
||||
gem 'combine_pdf'
|
||||
gem 'wicked_pdf'
|
||||
gem 'wkhtmltopdf-binary'
|
||||
@@ -127,12 +130,11 @@ end
|
||||
|
||||
group :test, :development do
|
||||
# Pretty printed test output
|
||||
gem 'atomic'
|
||||
gem 'awesome_print'
|
||||
gem 'bullet'
|
||||
gem 'capybara'
|
||||
gem 'database_cleaner', require: false
|
||||
gem "factory_bot_rails", '6.1.0', require: false
|
||||
gem "factory_bot_rails", '6.2.0', require: false
|
||||
gem 'fuubar', '~> 2.5.1'
|
||||
gem 'json_spec', '~> 1.1.4'
|
||||
gem 'knapsack'
|
||||
|
||||
34
Gemfile.lock
34
Gemfile.lock
@@ -64,7 +64,7 @@ GEM
|
||||
rack-test (>= 0.6.3)
|
||||
rails-dom-testing (~> 2.0)
|
||||
rails-html-sanitizer (~> 1.0, >= 1.0.2)
|
||||
actionpack-action_caching (1.2.1)
|
||||
actionpack-action_caching (1.2.2)
|
||||
actionpack (>= 4.0.0)
|
||||
actionview (5.2.6)
|
||||
activesupport (= 5.2.6)
|
||||
@@ -88,7 +88,7 @@ GEM
|
||||
activemodel (= 5.2.6)
|
||||
activesupport (= 5.2.6)
|
||||
arel (>= 9.0)
|
||||
activerecord-import (1.0.8)
|
||||
activerecord-import (1.1.0)
|
||||
activerecord (>= 3.2)
|
||||
activerecord-postgresql-adapter (0.0.1)
|
||||
pg
|
||||
@@ -124,7 +124,6 @@ GEM
|
||||
angularjs-rails (1.5.5)
|
||||
arel (9.0.0)
|
||||
ast (2.4.2)
|
||||
atomic (1.1.101)
|
||||
awesome_nested_set (3.4.0)
|
||||
activerecord (>= 4.0.0, < 7.0)
|
||||
awesome_print (1.9.2)
|
||||
@@ -193,7 +192,7 @@ GEM
|
||||
daemons (1.4.0)
|
||||
dalli (2.7.11)
|
||||
database_cleaner (1.99.0)
|
||||
ddtrace (0.48.0)
|
||||
ddtrace (0.49.0)
|
||||
ffi (~> 1.0)
|
||||
msgpack
|
||||
debugger-linecache (1.2.0)
|
||||
@@ -223,10 +222,10 @@ GEM
|
||||
eventmachine (1.2.7)
|
||||
excon (0.79.0)
|
||||
execjs (2.7.0)
|
||||
factory_bot (6.1.0)
|
||||
factory_bot (6.2.0)
|
||||
activesupport (>= 5.0.0)
|
||||
factory_bot_rails (6.1.0)
|
||||
factory_bot (~> 6.1.0)
|
||||
factory_bot_rails (6.2.0)
|
||||
factory_bot (~> 6.2.0)
|
||||
railties (>= 5.0.0)
|
||||
faraday (1.3.0)
|
||||
faraday-net_http (~> 1.0)
|
||||
@@ -285,9 +284,10 @@ GEM
|
||||
tilt
|
||||
hashdiff (1.0.1)
|
||||
highline (2.0.3)
|
||||
hiredis (0.6.3)
|
||||
i18n (1.8.10)
|
||||
concurrent-ruby (~> 1.0)
|
||||
i18n-js (3.8.2)
|
||||
i18n-js (3.8.3)
|
||||
i18n (>= 0.6.6)
|
||||
immigrant (0.3.6)
|
||||
activerecord (>= 3.0)
|
||||
@@ -305,7 +305,7 @@ GEM
|
||||
json_spec (1.1.5)
|
||||
multi_json (~> 1.0)
|
||||
rspec (>= 2.0, < 4.0)
|
||||
jwt (2.2.2)
|
||||
jwt (2.2.3)
|
||||
kaminari (1.2.1)
|
||||
activesupport (>= 4.1.0)
|
||||
kaminari-actionview (= 1.2.1)
|
||||
@@ -355,7 +355,7 @@ GEM
|
||||
mustermann (1.1.1)
|
||||
ruby2_keywords (~> 0.0.1)
|
||||
nio4r (2.5.7)
|
||||
nokogiri (1.11.3)
|
||||
nokogiri (1.11.4)
|
||||
mini_portile2 (~> 2.5.0)
|
||||
racc (~> 1.4)
|
||||
oauth2 (1.4.7)
|
||||
@@ -447,6 +447,7 @@ GEM
|
||||
rb-inotify (0.10.1)
|
||||
ffi (~> 1.0)
|
||||
redcarpet (3.5.1)
|
||||
redis (4.2.5)
|
||||
regexp_parser (2.1.1)
|
||||
request_store (1.5.0)
|
||||
rack (>= 1.4)
|
||||
@@ -499,7 +500,7 @@ GEM
|
||||
rswag-ui (2.4.0)
|
||||
actionpack (>= 3.1, < 7.0)
|
||||
railties (>= 3.1, < 7.0)
|
||||
rubocop (1.14.0)
|
||||
rubocop (1.15.0)
|
||||
parallel (~> 1.10)
|
||||
parser (>= 3.0.0.0)
|
||||
rainbow (>= 2.2.2, < 4.0)
|
||||
@@ -564,7 +565,7 @@ GEM
|
||||
stringex (2.8.5)
|
||||
stripe (5.30.0)
|
||||
temple (0.8.2)
|
||||
test-prof (1.0.3)
|
||||
test-prof (1.0.5)
|
||||
test-unit (3.4.1)
|
||||
power_assert
|
||||
thor (0.20.3)
|
||||
@@ -596,7 +597,7 @@ GEM
|
||||
nokogiri (~> 1.6)
|
||||
rubyzip (>= 1.3.0)
|
||||
selenium-webdriver (>= 3.0, < 4.0)
|
||||
webmock (3.12.2)
|
||||
webmock (3.13.0)
|
||||
addressable (>= 2.3.6)
|
||||
crack (>= 0.3.2)
|
||||
hashdiff (>= 0.4.0, < 2.0.0)
|
||||
@@ -629,7 +630,6 @@ DEPENDENCIES
|
||||
angular_rails_csrf
|
||||
angularjs-file-upload-rails (~> 2.4.1)
|
||||
angularjs-rails (= 1.5.5)
|
||||
atomic
|
||||
awesome_nested_set
|
||||
awesome_print
|
||||
aws-sdk (= 1.67.0)
|
||||
@@ -657,7 +657,7 @@ DEPENDENCIES
|
||||
devise-token_authenticatable
|
||||
dfc_provider!
|
||||
eventmachine (>= 1.2.3)
|
||||
factory_bot_rails (= 6.1.0)
|
||||
factory_bot_rails (= 6.2.0)
|
||||
ffaker
|
||||
figaro
|
||||
flipper
|
||||
@@ -672,8 +672,9 @@ DEPENDENCIES
|
||||
good_migrations
|
||||
haml
|
||||
highline (= 2.0.3)
|
||||
hiredis
|
||||
i18n
|
||||
i18n-js (~> 3.8.2)
|
||||
i18n-js (~> 3.8.3)
|
||||
immigrant
|
||||
jquery-migrate-rails
|
||||
jquery-rails (= 4.4.0)
|
||||
@@ -706,6 +707,7 @@ DEPENDENCIES
|
||||
rails_safe_tasks (~> 1.0)
|
||||
ransack (= 2.4.1)
|
||||
redcarpet
|
||||
redis (>= 4.0)
|
||||
responders
|
||||
roadie-rails (~> 2.2.0)
|
||||
roo (~> 2.8.3)
|
||||
|
||||
@@ -3,7 +3,7 @@ Darkswarm.controller "EditBoughtOrderController", ($scope, $resource, $timeout,
|
||||
$scope.removeEnabled = true
|
||||
|
||||
$scope.deleteLineItem = (id) ->
|
||||
if Cart.has_one_line_item()
|
||||
if Cart.isOnlyItemInOrder(id)
|
||||
Messages.error(t 'orders_cannot_remove_the_final_item')
|
||||
$scope.removeEnabled = false
|
||||
$timeout (->
|
||||
|
||||
@@ -115,8 +115,9 @@ Darkswarm.factory 'Cart', (CurrentOrder, Variants, $timeout, $http, $modal, $roo
|
||||
@line_items = []
|
||||
localStorageService.clearAll() # One day this will have to be moar GRANULAR
|
||||
|
||||
has_one_line_item: =>
|
||||
@line_items_finalised.length == 1
|
||||
isOnlyItemInOrder: (id) =>
|
||||
deletedItem = @line_items_finalised.find((item) -> item.id == id)
|
||||
@line_items_finalised.filter((item) -> item.order_id == deletedItem.order_id).length == 1
|
||||
|
||||
removeFinalisedLineItem: (id) =>
|
||||
@line_items_finalised = @line_items_finalised.filter (item) ->
|
||||
|
||||
@@ -10,7 +10,7 @@ Darkswarm.service "GmapsGeo", ->
|
||||
# console.log "Error: #{status}"
|
||||
geocode: (address, callback) ->
|
||||
geocoder = new google.maps.Geocoder()
|
||||
geocoder.geocode {'address': address, 'region': "<%= Spree::Country.find_by(id: Spree::Config[:default_country_id]).iso %>"}, callback
|
||||
geocoder.geocode {'address': address, 'region': "<%= DefaultCountry.code %>"}, callback
|
||||
|
||||
distanceBetween: (src, dst) ->
|
||||
google.maps.geometry.spherical.computeDistanceBetween @toLatLng(src), @toLatLng(dst)
|
||||
@@ -20,4 +20,4 @@ Darkswarm.service "GmapsGeo", ->
|
||||
if locatable.lat?
|
||||
locatable
|
||||
else
|
||||
new google.maps.LatLng locatable.latitude, locatable.longitude
|
||||
new google.maps.LatLng locatable.latitude, locatable.longitude
|
||||
|
||||
@@ -35,7 +35,7 @@ module Admin
|
||||
if @line_item.update(line_item_params)
|
||||
order.update_line_item_fees! @line_item
|
||||
order.update_order_fees!
|
||||
order.update!
|
||||
order.update_order!
|
||||
render body: nil, status: :no_content # No Content, does not trigger ng resource auto-update
|
||||
else
|
||||
render json: { errors: @line_item.errors }, status: :precondition_failed
|
||||
|
||||
@@ -28,9 +28,7 @@ module Admin
|
||||
def build_resource
|
||||
enterprise_group = super
|
||||
enterprise_group.address = Spree::Address.new
|
||||
enterprise_group.address.country = Spree::Country.find_by(
|
||||
id: Spree::Config[:default_country_id]
|
||||
)
|
||||
enterprise_group.address.country = DefaultCountry.country
|
||||
enterprise_group
|
||||
end
|
||||
|
||||
|
||||
@@ -119,7 +119,7 @@ module Admin
|
||||
def build_resource
|
||||
enterprise = super
|
||||
enterprise.address ||= Spree::Address.new
|
||||
enterprise.address.country ||= Spree::Country.find_by(id: Spree::Config[:default_country_id])
|
||||
enterprise.address.country ||= DefaultCountry.country
|
||||
enterprise
|
||||
end
|
||||
|
||||
|
||||
@@ -31,10 +31,12 @@ module Api
|
||||
unlock = params[:shipment].delete(:unlock)
|
||||
|
||||
if unlock == 'yes'
|
||||
@shipment.fee_adjustment.open
|
||||
@shipment.fee_adjustment.fire_events(:open)
|
||||
end
|
||||
|
||||
@shipment.update(shipment_params[:shipment])
|
||||
if @shipment.update(shipment_params)
|
||||
@order.updater.update_totals_and_states
|
||||
end
|
||||
|
||||
if unlock == 'yes'
|
||||
@shipment.fee_adjustment.close
|
||||
@@ -94,7 +96,7 @@ module Api
|
||||
|
||||
def find_and_update_shipment
|
||||
@shipment = @order.shipments.find_by!(number: params[:id])
|
||||
@shipment.update(shipment_params[:shipment]) if shipment_params[:shipment].present?
|
||||
@shipment.update(shipment_params)
|
||||
@shipment.reload
|
||||
end
|
||||
|
||||
@@ -113,10 +115,9 @@ module Api
|
||||
end
|
||||
|
||||
def shipment_params
|
||||
params.permit(
|
||||
[:id, :order_id, :variant_id, :quantity,
|
||||
{ shipment: [:tracking, :selected_shipping_rate_id] }]
|
||||
)
|
||||
return {} unless params.has_key? :shipment
|
||||
|
||||
params.require(:shipment).permit(:tracking, :selected_shipping_rate_id)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -55,7 +55,7 @@ class CheckoutController < ::BaseController
|
||||
flash[:error] = I18n.t("checkout.failed")
|
||||
action_failed(e)
|
||||
ensure
|
||||
@order.update!
|
||||
@order.update_order!
|
||||
end
|
||||
|
||||
# Clears the cached order. Required for #current_order to return a new order
|
||||
|
||||
@@ -43,7 +43,7 @@ class LineItemsController < BaseController
|
||||
order.update_shipping_fees!
|
||||
order.update_payment_fees!
|
||||
order.update_order_fees!
|
||||
order.update!
|
||||
order.update_order!
|
||||
order.create_tax_charge!
|
||||
end
|
||||
end
|
||||
|
||||
@@ -14,7 +14,7 @@ module Spree
|
||||
|
||||
def update_order
|
||||
@order.reload
|
||||
@order.update!
|
||||
@order.update_order!
|
||||
end
|
||||
|
||||
def collection
|
||||
|
||||
@@ -9,6 +9,10 @@ module Spree
|
||||
before_action :load_payment, only: [:fire, :show]
|
||||
before_action :load_data
|
||||
before_action :can_transition_to_payment
|
||||
# We ensure that items are in stock before all screens if the order is in the Payment state.
|
||||
# This way, we don't allow someone to enter credit card details for an order only to be told
|
||||
# that it can't be processed.
|
||||
before_action :ensure_sufficient_stock_lines
|
||||
|
||||
respond_to :html
|
||||
|
||||
@@ -142,6 +146,20 @@ module Spree
|
||||
redirect_to spree.edit_admin_order_customer_url(@order)
|
||||
end
|
||||
|
||||
def ensure_sufficient_stock_lines
|
||||
return if !@order.payment? || @order.insufficient_stock_lines.blank?
|
||||
|
||||
flash[:error] = I18n.t("spree.orders.line_item.insufficient_stock",
|
||||
on_hand: "0 #{out_of_stock_item_names}")
|
||||
redirect_to spree.edit_admin_order_url(@order)
|
||||
end
|
||||
|
||||
def out_of_stock_item_names
|
||||
@order.insufficient_stock_lines.map do |line_item|
|
||||
line_item.variant.name
|
||||
end.join(", ")
|
||||
end
|
||||
|
||||
def load_order
|
||||
@order = Order.find_by!(number: params[:order_id])
|
||||
authorize! action, @order
|
||||
|
||||
@@ -14,7 +14,7 @@ module Spree
|
||||
respond_to :html
|
||||
respond_to :json
|
||||
|
||||
before_action :update_distribution, only: :update
|
||||
before_action :set_current_order, only: :update
|
||||
before_action :filter_order_params, only: :update
|
||||
before_action :enable_embedded_shopfront
|
||||
|
||||
@@ -27,13 +27,7 @@ module Spree
|
||||
def show
|
||||
@order = Spree::Order.find_by!(number: params[:id])
|
||||
|
||||
if params.key?("payment_intent")
|
||||
result = ProcessPaymentIntent.new(params["payment_intent"], @order).call!
|
||||
unless result.ok?
|
||||
flash[:error] = "#{I18n.t("payment_could_not_process")}. #{result.error}"
|
||||
end
|
||||
@order.reload
|
||||
end
|
||||
handle_stripe_response
|
||||
end
|
||||
|
||||
def empty
|
||||
@@ -68,7 +62,7 @@ module Spree
|
||||
associate_user
|
||||
|
||||
if @order.insufficient_stock_lines.present? || @unavailable_order_variants.present?
|
||||
flash[:error] = t("spree.orders.error_flash_for_unavailable_items")
|
||||
flash.now[:error] = t("spree.orders.error_flash_for_unavailable_items")
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -101,7 +95,7 @@ module Spree
|
||||
@order.next_transition.run_callbacks if @order.cart?
|
||||
redirect_to main_app.checkout_state_path(@order.checkout_steps.first)
|
||||
elsif @order.complete?
|
||||
redirect_to order_path(@order)
|
||||
redirect_to main_app.order_path(@order)
|
||||
else
|
||||
redirect_to main_app.cart_path
|
||||
end
|
||||
@@ -115,24 +109,8 @@ module Spree
|
||||
end
|
||||
end
|
||||
|
||||
def update_distribution
|
||||
def set_current_order
|
||||
@order = current_order(true)
|
||||
|
||||
if params[:commit] == 'Choose Hub'
|
||||
distributor = Enterprise.is_distributor.find params[:order][:distributor_id]
|
||||
@order.set_distributor! distributor
|
||||
|
||||
flash[:notice] = I18n.t(:order_choosing_hub_notice)
|
||||
redirect_to request.referer
|
||||
|
||||
elsif params[:commit] == 'Choose Order Cycle'
|
||||
@order.empty! # empty cart
|
||||
order_cycle = OrderCycle.active.find params[:order][:order_cycle_id]
|
||||
@order.set_order_cycle! order_cycle
|
||||
|
||||
flash[:notice] = I18n.t(:order_choosing_hub_notice)
|
||||
redirect_to request.referer
|
||||
end
|
||||
end
|
||||
|
||||
def filter_order_params
|
||||
@@ -157,11 +135,24 @@ module Spree
|
||||
else
|
||||
flash[:error] = I18n.t(:orders_could_not_cancel)
|
||||
end
|
||||
redirect_to request.referer || order_path(@order)
|
||||
redirect_to request.referer || main_app.order_path(@order)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Stripe can redirect here after a payment is processed in the backoffice.
|
||||
# We verify if it was successful here and persist the changes.
|
||||
def handle_stripe_response
|
||||
return unless params.key?("payment_intent")
|
||||
|
||||
result = ProcessPaymentIntent.new(params["payment_intent"], @order).call!
|
||||
|
||||
unless result.ok?
|
||||
flash.now[:error] = "#{I18n.t("payment_could_not_process")}. #{result.error}"
|
||||
end
|
||||
@order.reload
|
||||
end
|
||||
|
||||
def discard_empty_line_items
|
||||
@order.line_items = @order.line_items.select { |li| li.quantity > 0 }
|
||||
end
|
||||
@@ -197,7 +188,7 @@ module Spree
|
||||
|
||||
if items.empty?
|
||||
flash[:error] = I18n.t(:orders_cannot_remove_the_final_item)
|
||||
redirect_to order_path(order_to_update)
|
||||
redirect_to main_app.order_path(order_to_update)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ module Spree
|
||||
|
||||
def show
|
||||
@payments_requiring_action = PaymentsRequiringAction.new(spree_current_user).query
|
||||
@orders = orders_collection
|
||||
@orders = orders_collection.includes(:line_items)
|
||||
|
||||
customers = spree_current_user.customers
|
||||
@shops = Enterprise
|
||||
|
||||
@@ -90,13 +90,13 @@ class SubscriptionConfirmJob < ActiveJob::Base
|
||||
end
|
||||
|
||||
def send_confirmation_email(order)
|
||||
order.update!
|
||||
order.update_order!
|
||||
record_success(order)
|
||||
SubscriptionMailer.confirmation_email(order).deliver_now
|
||||
end
|
||||
|
||||
def send_failed_payment_email(order, error_message = nil)
|
||||
order.update!
|
||||
order.update_order!
|
||||
record_and_log_error(:failed_payment, order, error_message)
|
||||
SubscriptionMailer.failed_payment_email(order).deliver_now
|
||||
rescue StandardError => e
|
||||
|
||||
@@ -77,7 +77,7 @@ class SubscriptionPlacementJob < ActiveJob::Base
|
||||
|
||||
def handle_empty_order(order, changes)
|
||||
order.reload.all_adjustments.destroy_all
|
||||
order.update!
|
||||
order.update_order!
|
||||
send_empty_email(order, changes)
|
||||
end
|
||||
|
||||
|
||||
@@ -105,7 +105,7 @@ class Enterprise < ApplicationRecord
|
||||
after_touch :touch_distributors
|
||||
after_create :set_default_contact
|
||||
after_create :relate_to_owners_enterprises
|
||||
after_create :send_welcome_email
|
||||
after_create_commit :send_welcome_email
|
||||
|
||||
after_rollback :restore_permalink
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ module Spree
|
||||
|
||||
def self.default
|
||||
country = begin
|
||||
Spree::Country.find(Spree::Config[:default_country_id])
|
||||
DefaultCountry.country
|
||||
rescue StandardError
|
||||
Spree::Country.first
|
||||
end
|
||||
|
||||
@@ -96,7 +96,7 @@ module Spree
|
||||
# more than on line items at once via accepted_nested_attributes the order
|
||||
# object on the association would be in a old state and therefore the
|
||||
# adjustment calculations would not performed on proper values
|
||||
def update!(calculable = nil, force: false)
|
||||
def update_adjustment!(calculable = nil, force: false)
|
||||
return amount if immutable? && !force
|
||||
|
||||
if originator.present?
|
||||
@@ -127,11 +127,7 @@ module Spree
|
||||
end
|
||||
|
||||
def set_absolute_included_tax!(tax)
|
||||
# This rubocop issue can now fixed by renaming Adjustment#update! to something else,
|
||||
# then AR's update! can be used instead of update_attributes!
|
||||
# rubocop:disable Rails/ActiveRecordAliases
|
||||
update_attributes! included_tax: tax.round(2)
|
||||
# rubocop:enable Rails/ActiveRecordAliases
|
||||
update! included_tax: tax.round(2)
|
||||
end
|
||||
|
||||
def display_included_tax
|
||||
|
||||
@@ -87,7 +87,7 @@ module Spree
|
||||
)
|
||||
refund_transaction_response = provider.refund_transaction(refund_transaction)
|
||||
if refund_transaction_response.success?
|
||||
payment.source.update_attributes(
|
||||
payment.source.update(
|
||||
refunded_at: Time.now,
|
||||
refund_transaction_id: refund_transaction_response.RefundTransactionID,
|
||||
state: "refunded",
|
||||
|
||||
@@ -129,7 +129,19 @@ module Spree
|
||||
payment = fetch_payment(creditcard, gateway_options)
|
||||
raise Stripe::StripeError, I18n.t(:no_pending_payments) unless payment&.response_code
|
||||
|
||||
Stripe::PaymentIntentValidator.new.call(payment.response_code, stripe_account_id)
|
||||
payment_intent_response = Stripe::PaymentIntentValidator.new.
|
||||
call(payment.response_code, stripe_account_id)
|
||||
|
||||
raise_if_not_in_capture_state(payment_intent_response)
|
||||
|
||||
payment.response_code
|
||||
end
|
||||
|
||||
def raise_if_not_in_capture_state(payment_intent_response)
|
||||
state = payment_intent_response.status
|
||||
return if state == 'requires_capture'
|
||||
|
||||
raise Stripe::StripeError, I18n.t(:invalid_payment_state, state: state)
|
||||
end
|
||||
|
||||
def fetch_payment(creditcard, gateway_options)
|
||||
|
||||
@@ -66,7 +66,7 @@ module Spree
|
||||
end
|
||||
|
||||
def update_order
|
||||
order.update!
|
||||
order.update_order!
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -17,9 +17,9 @@ module Spree
|
||||
end
|
||||
|
||||
def update_adjustments
|
||||
adjustment_total = adjustments.additional.map(&:update!).compact.sum
|
||||
included_tax_total = tax_adjustments.inclusive.reload.map(&:update!).compact.sum
|
||||
additional_tax_total = tax_adjustments.additional.reload.map(&:update!).compact.sum
|
||||
adjustment_total = adjustments.additional.map(&:update_adjustment!).compact.sum
|
||||
included_tax_total = tax_adjustments.inclusive.reload.map(&:update_adjustment!).compact.sum
|
||||
additional_tax_total = tax_adjustments.additional.reload.map(&:update_adjustment!).compact.sum
|
||||
|
||||
item.update_columns(
|
||||
included_tax_total: included_tax_total,
|
||||
|
||||
@@ -230,7 +230,7 @@ module Spree
|
||||
|
||||
# update the order totals, etc.
|
||||
order.create_tax_charge!
|
||||
order.update!
|
||||
order.update_order!
|
||||
end
|
||||
|
||||
def update_inventory_before_destroy
|
||||
|
||||
@@ -212,7 +212,7 @@ module Spree
|
||||
@updater ||= OrderManagement::Order::Updater.new(self)
|
||||
end
|
||||
|
||||
def update!
|
||||
def update_order!
|
||||
updater.update
|
||||
end
|
||||
|
||||
@@ -748,8 +748,8 @@ module Spree
|
||||
def update_adjustment!(adjustment)
|
||||
return if adjustment.finalized?
|
||||
|
||||
adjustment.update!(force: true)
|
||||
update!
|
||||
adjustment.update_adjustment!(force: true)
|
||||
update_order!
|
||||
end
|
||||
|
||||
# object_params sets the payment amount to the order total, but it does this
|
||||
|
||||
@@ -50,6 +50,7 @@ module Spree
|
||||
scope :failed, -> { with_state('failed') }
|
||||
scope :valid, -> { where('state NOT IN (?)', %w(failed invalid)) }
|
||||
scope :authorization_action_required, -> { where.not(cvv_response_message: nil) }
|
||||
scope :with_payment_intent, ->(code) { where(response_code: code) }
|
||||
|
||||
# order state machine (see http://github.com/pluginaweek/state_machine/tree/master for details)
|
||||
state_machine initial: :checkout do
|
||||
@@ -205,7 +206,7 @@ module Spree
|
||||
end
|
||||
|
||||
def update_order
|
||||
order.update!
|
||||
OrderManagement::Order::Updater.new(order).after_payment_update(self)
|
||||
end
|
||||
|
||||
# Necessary because some payment gateways will refuse payments with
|
||||
|
||||
@@ -66,7 +66,7 @@ module Spree
|
||||
order.shipped_shipments.collect{ |s| s.inventory_units.to_a }.flatten
|
||||
end
|
||||
|
||||
# Used when Adjustment#update! wants to update the related adjustment
|
||||
# Used when Adjustment#update_adjustment! wants to update the related adjustment
|
||||
def compute_amount(*_args)
|
||||
-amount.abs
|
||||
end
|
||||
@@ -105,7 +105,7 @@ module Spree
|
||||
)
|
||||
|
||||
order.return if inventory_units.all?(&:returned?)
|
||||
order.update!
|
||||
order.update_order!
|
||||
end
|
||||
|
||||
def allow_receive?
|
||||
|
||||
@@ -50,7 +50,7 @@ module Spree
|
||||
category = TaxCategory.includes(:tax_rates).find_by(is_default: true)
|
||||
return 0 unless category
|
||||
|
||||
address ||= Address.new(country_id: Spree::Config[:default_country_id])
|
||||
address ||= Address.new(country_id: DefaultCountry.id)
|
||||
rate = category.tax_rates.detect { |tax_rate| tax_rate.zone.include? address }.try(:amount)
|
||||
|
||||
rate || 0
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
class Api::LineItemSerializer < ActiveModel::Serializer
|
||||
attributes :id, :quantity, :max_quantity, :price
|
||||
attributes :id, :quantity, :max_quantity, :price, :order_id
|
||||
|
||||
has_one :variant, serializer: Api::VariantSerializer
|
||||
end
|
||||
|
||||
@@ -22,7 +22,7 @@ module Api
|
||||
end
|
||||
|
||||
def item_count
|
||||
object.line_items.sum(:quantity)
|
||||
object.line_items.sum(&:quantity)
|
||||
end
|
||||
|
||||
def completed_at
|
||||
|
||||
13
app/services/default_country.rb
Normal file
13
app/services/default_country.rb
Normal file
@@ -0,0 +1,13 @@
|
||||
class DefaultCountry
|
||||
def self.id
|
||||
country.id
|
||||
end
|
||||
|
||||
def self.code
|
||||
country.iso
|
||||
end
|
||||
|
||||
def self.country
|
||||
Spree::Country.find_by(iso: ENV["DEFAULT_COUNTRY_CODE"]) || Spree::Country.first
|
||||
end
|
||||
end
|
||||
@@ -2,9 +2,8 @@
|
||||
# by setting entries on the Spree Config
|
||||
# and initializing Spree:MailSettings that uses the Spree::Config.
|
||||
class MailConfiguration
|
||||
# @param entries [Hash] Spree Config entries
|
||||
def self.entries=(entries)
|
||||
entries.each do |name, value|
|
||||
def self.apply!
|
||||
configuration.each do |name, value|
|
||||
Spree::Config[name] = value
|
||||
end
|
||||
apply_mail_settings
|
||||
@@ -12,6 +11,21 @@ class MailConfiguration
|
||||
|
||||
private
|
||||
|
||||
def self.configuration
|
||||
{
|
||||
mail_host: ENV.fetch('MAIL_HOST'),
|
||||
mail_domain: ENV.fetch('MAIL_DOMAIN'),
|
||||
mail_port: ENV.fetch('MAIL_PORT'),
|
||||
mail_auth_type: ENV.fetch('MAIL_AUTH_TYPE', 'login'),
|
||||
smtp_username: ENV.fetch('SMTP_USERNAME'),
|
||||
smtp_password: ENV.fetch('SMTP_PASSWORD'),
|
||||
secure_connection_type: ENV.fetch('MAIL_SECURE_CONNECTION', 'None'),
|
||||
mails_from: ENV.fetch('MAILS_FROM', "no-reply@#{ENV.fetch('MAIL_DOMAIN')}"),
|
||||
mail_bcc: ENV.fetch('MAIL_BCC', ''),
|
||||
intercept_email: ''
|
||||
}
|
||||
end
|
||||
|
||||
def self.apply_mail_settings
|
||||
Spree::Core::MailSettings.init
|
||||
end
|
||||
|
||||
@@ -13,7 +13,7 @@ class OrderCheckoutRestart
|
||||
clear_shipments
|
||||
clear_payments
|
||||
|
||||
order.reload.update!
|
||||
order.reload.update_order!
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
@@ -24,7 +24,7 @@ class OrderFeesHandler
|
||||
order.updater.persist_totals
|
||||
end
|
||||
|
||||
order.update!
|
||||
order.update_order!
|
||||
end
|
||||
|
||||
def create_line_item_fees!
|
||||
@@ -43,13 +43,13 @@ class OrderFeesHandler
|
||||
|
||||
def update_line_item_fees!(line_item)
|
||||
line_item.adjustments.enterprise_fee.each do |fee|
|
||||
fee.update!(line_item, force: true)
|
||||
fee.update_adjustment!(line_item, force: true)
|
||||
end
|
||||
end
|
||||
|
||||
def update_order_fees!
|
||||
order.adjustments.enterprise_fee.where(adjustable_type: 'Spree::Order').each do |fee|
|
||||
fee.update!(order, force: true)
|
||||
fee.update_adjustment!(order, force: true)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ module Permissions
|
||||
def filtered_orders(orders)
|
||||
return orders unless filter_orders?
|
||||
|
||||
orders.complete.not_state(:canceled).search(search_params).result
|
||||
orders.complete.not_state(:canceled).ransack(search_params).result
|
||||
end
|
||||
|
||||
def filter_orders?
|
||||
|
||||
@@ -23,21 +23,20 @@ class ProcessPaymentIntent
|
||||
end
|
||||
end
|
||||
|
||||
def initialize(payment_intent, order, last_payment = nil)
|
||||
def initialize(payment_intent, order)
|
||||
@payment_intent = payment_intent
|
||||
@order = order
|
||||
@last_payment = last_payment.presence || OrderPaymentFinder.new(order).last_payment
|
||||
@payment = order.payments.pending.with_payment_intent(payment_intent).first
|
||||
end
|
||||
|
||||
def call!
|
||||
validate_intent!
|
||||
return Result.new(ok: false) unless valid?
|
||||
return Result.new(ok: false) unless payment.present? && ready_for_capture?
|
||||
return Result.new(ok: true) if already_processed?
|
||||
|
||||
OrderWorkflow.new(order).next
|
||||
process_payment
|
||||
|
||||
if last_payment.can_complete?
|
||||
last_payment.complete!
|
||||
last_payment.mark_as_processed
|
||||
if payment.reload.completed?
|
||||
payment.mark_as_processed
|
||||
|
||||
Result.new(ok: true)
|
||||
else
|
||||
@@ -50,18 +49,29 @@ class ProcessPaymentIntent
|
||||
|
||||
private
|
||||
|
||||
attr_reader :order, :payment_intent, :last_payment
|
||||
attr_reader :order, :payment_intent, :payment
|
||||
|
||||
def valid?
|
||||
order.present? && matches_last_payment?
|
||||
def process_payment
|
||||
if order.state == "payment"
|
||||
# Moves the order to completed, which calls #process_payments!
|
||||
OrderWorkflow.new(order).next
|
||||
else
|
||||
order.process_payments!
|
||||
end
|
||||
end
|
||||
|
||||
def validate_intent!
|
||||
Stripe::PaymentIntentValidator.new.call(payment_intent, stripe_account_id)
|
||||
def ready_for_capture?
|
||||
payment_intent_status == 'requires_capture'
|
||||
end
|
||||
|
||||
def matches_last_payment?
|
||||
last_payment&.state == "pending" && last_payment&.response_code == payment_intent
|
||||
def already_processed?
|
||||
payment_intent_status == 'succeeded'
|
||||
end
|
||||
|
||||
def payment_intent_status
|
||||
@payment_intent_status ||= Stripe::PaymentIntentValidator.new.
|
||||
call(payment_intent, stripe_account_id).
|
||||
status
|
||||
end
|
||||
|
||||
def stripe_account_id
|
||||
@@ -69,6 +79,6 @@ class ProcessPaymentIntent
|
||||
end
|
||||
|
||||
def preferred_enterprise_id
|
||||
last_payment.payment_method.preferred_enterprise_id
|
||||
payment.payment_method.preferred_enterprise_id
|
||||
end
|
||||
end
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
= "admin.enterprises"
|
||||
|
||||
= admin_inject_available_countries(module: 'admin.enterprises')
|
||||
= admin_inject_json "admin.enterprises", "defaultCountryID", Spree::Config[:default_country_id]
|
||||
= admin_inject_json "admin.enterprises", "defaultCountryID", DefaultCountry.id
|
||||
|
||||
-# Form
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
= validated_input t(:postcode), "order.bill_address.zipcode"
|
||||
|
||||
.small-6.columns.right
|
||||
= validated_select t(:country), "order.bill_address.country_id", {}, {"ng-init" => "order.bill_address.country_id = order.bill_address.country_id || #{Spree::Config[:default_country_id]}", "ng-options" => "c.id as c.name for c in countries"}
|
||||
= validated_select t(:country), "order.bill_address.country_id", {}, {"ng-init" => "order.bill_address.country_id = order.bill_address.country_id || #{DefaultCountry.id}", "ng-options" => "c.id as c.name for c in countries"}
|
||||
|
||||
.row
|
||||
.small-12.columns.text-right
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
.small-6.columns
|
||||
= validated_input t(:postcode), "order.ship_address.zipcode"
|
||||
.small-6.columns.right
|
||||
= validated_select t(:country), "order.ship_address.country_id", {}, {"ng-init" => "order.ship_address.country_id = order.ship_address.country_id || #{Spree::Config[:default_country_id]}", "ng-options" => "c.id as c.name for c in countries"}
|
||||
= validated_select t(:country), "order.ship_address.country_id", {}, {"ng-init" => "order.ship_address.country_id = order.ship_address.country_id || #{DefaultCountry.id}", "ng-options" => "c.id as c.name for c in countries"}
|
||||
.row
|
||||
.small-6.columns
|
||||
= validated_input t(:phone), "order.ship_address.phone"
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
.small-12.medium-8.large-8.columns
|
||||
.field
|
||||
%label{ for: 'enterprise_country' }= t(".country_field")
|
||||
%select.chunky{ id: 'enterprise_country', name: 'country', required: true, ng: { init: "setDefaultCountry(#{Spree::Config[:default_country_id]})", model: 'enterprise.country', options: 'c as c.name for c in countries' } }
|
||||
%select.chunky{ id: 'enterprise_country', name: 'country', required: true, ng: { init: "setDefaultCountry(#{DefaultCountry.id})", model: 'enterprise.country', options: 'c as c.name for c in countries' } }
|
||||
%span.error{ ng: { show: "details.country.$error.required && submitted" } }
|
||||
= t(".country_field_error")
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
- if Rails.env.test?
|
||||
%script{type: "text/javascript"}
|
||||
= render file: "spec/support/fixtures/stripejs-mock.js"
|
||||
= raw render file: "spec/support/fixtures/stripejs-mock.js"
|
||||
- else
|
||||
%script{src: "https://js.stripe.com/v3/", type: "text/javascript"}
|
||||
|
||||
@@ -26,4 +26,4 @@
|
||||
var shipments = [];
|
||||
- @order.shipments.each do |shipment|
|
||||
shipments.push(#{shipment.to_json(:root => false, :include => [:inventory_units, :stock_location]).html_safe});
|
||||
= render :partial => 'spree/admin/shared/update_order_state', :handlers => [:erb]
|
||||
= render :partial => 'spree/admin/shared/update_order_state', :handlers => [:erb], :formats => [:js]
|
||||
|
||||
@@ -25,8 +25,7 @@
|
||||
%span.centered.three.columns
|
||||
= t "spree_admin_enterprises_fees"
|
||||
%div.sixteen.columns.alpha.list
|
||||
- @enterprises.each do |enterprise|
|
||||
= render 'enterprise_row', { enterprise: enterprise }
|
||||
= render partial: 'enterprise_row', collection: @enterprises, as: :enterprise
|
||||
|
||||
%a.sixteen.columns.alpha.button.bottom.blue{ href: "#{main_app.admin_enterprises_path}" }
|
||||
= t "spree_admin_overview_enterprises_footer"
|
||||
|
||||
@@ -11,8 +11,8 @@
|
||||
= configurations_sidebar_menu_item Spree.t(:tax_settings), edit_admin_tax_settings_path
|
||||
= configurations_sidebar_menu_item Spree.t(:zones), admin_zones_path
|
||||
= configurations_sidebar_menu_item Spree.t(:countries), admin_countries_path
|
||||
- if Spree::Config[:default_country_id]
|
||||
= configurations_sidebar_menu_item Spree.t(:states), admin_country_states_path(Spree::Config[:default_country_id])
|
||||
- if DefaultCountry.id
|
||||
= configurations_sidebar_menu_item Spree.t(:states), admin_country_states_path(DefaultCountry.id)
|
||||
= configurations_sidebar_menu_item Spree.t(:payment_methods), admin_payment_methods_path
|
||||
= configurations_sidebar_menu_item Spree.t(:taxonomies), admin_taxonomies_path
|
||||
= configurations_sidebar_menu_item Spree.t(:shipping_methods), admin_shipping_methods_path
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
- if order.changes_allowed?
|
||||
.columns.show-for-medium-up.medium-3
|
||||
.columns.small-12.medium-3
|
||||
= link_to cancel_order_path(@order), method: :put, :class => "button secondary expand", "confirm-link-click" => t('orders_confirm_cancel') do
|
||||
= link_to main_app.cancel_order_path(@order), method: :put, :class => "button secondary expand", "confirm-link-click" => t('orders_confirm_cancel') do
|
||||
%i.ofn-i_009-close
|
||||
= t(:cancel_order)
|
||||
.columns.small-12.medium-3
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
= t(:orders_changeable_orders_alert_html, oc_close: l(order.order_cycle.orders_close_at, format: "%b %d, %Y %H:%M"))
|
||||
%a.close{ "ng-click" => "close()" } ×
|
||||
|
||||
= form_for order, url: order_path(order), html: {id: 'update-order', name: 'update_order_form' } do |order_form|
|
||||
= form_for order, url: main_app.order_path(order), html: {id: 'update-order', name: 'update_order_form' } do |order_form|
|
||||
- if order.changes_allowed?
|
||||
= render 'spree/orders/form', order_form: order_form
|
||||
-else
|
||||
|
||||
@@ -75,13 +75,6 @@ module Openfoodnetwork
|
||||
initializer 'ofn.spree_locale_settings', before: 'spree.promo.environment' do |app|
|
||||
Spree::Config['checkout_zone'] = ENV['CHECKOUT_ZONE']
|
||||
Spree::Config['currency'] = ENV['CURRENCY']
|
||||
|
||||
if ActiveRecord::Base.connected? && Spree::Country.table_exists?
|
||||
country = Spree::Country.find_by(iso: ENV['DEFAULT_COUNTRY_CODE'])
|
||||
Spree::Config['default_country_id'] = country.id if country.present?
|
||||
else
|
||||
Spree::Config['default_country_id'] = 12 # Australia
|
||||
end
|
||||
end
|
||||
|
||||
# Register Spree calculators
|
||||
|
||||
@@ -66,5 +66,3 @@ SMTP_PASSWORD: 'f00d'
|
||||
# config/initializers/feature_toggles.rb for details.
|
||||
#
|
||||
# BETA_TESTERS: ofn@example.com,superadmin@example.com
|
||||
|
||||
MEMCACHED_VALUE_MAX_MEGABYTES: '4'
|
||||
|
||||
@@ -11,7 +11,14 @@ Openfoodnetwork::Application.configure do
|
||||
config.cache_classes = !!ENV["PROFILE"]
|
||||
|
||||
# :file_store is used by default when no cache store is specifically configured.
|
||||
config.cache_store = :memory_store if !!ENV["PROFILE"]
|
||||
if !!ENV["PROFILE"]
|
||||
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
|
||||
|
||||
config.eager_load = false
|
||||
|
||||
|
||||
@@ -42,9 +42,12 @@ Openfoodnetwork::Application.configure do
|
||||
config.log_formatter = Logger::Formatter.new.tap { |f| f.datetime_format = "%Y-%m-%d %H:%M:%S" }
|
||||
|
||||
# Use a different cache store in production
|
||||
memcached_value_max_megabytes = ENV.fetch("MEMCACHED_VALUE_MAX_MEGABYTES", 1).to_i
|
||||
memcached_value_max_bytes = memcached_value_max_megabytes * 1024 * 1024
|
||||
config.cache_store = :mem_cache_store, { value_max_bytes: memcached_value_max_bytes }
|
||||
config.cache_store = :redis_cache_store, {
|
||||
driver: :hiredis,
|
||||
url: ENV.fetch("OFN_REDIS_URL", "redis://localhost:6379/0"),
|
||||
namespace: "cache",
|
||||
reconnect_attempts: 1
|
||||
}
|
||||
|
||||
# Enable serving of images, stylesheets, and JavaScripts from an asset server
|
||||
# config.action_controller.asset_host = "http://assets.example.com"
|
||||
|
||||
@@ -42,9 +42,12 @@ Openfoodnetwork::Application.configure do
|
||||
config.log_formatter = Logger::Formatter.new.tap { |f| f.datetime_format = "%Y-%m-%d %H:%M:%S" }
|
||||
|
||||
# Use a different cache store in production
|
||||
memcached_value_max_megabytes = ENV.fetch("MEMCACHED_VALUE_MAX_MEGABYTES", 1).to_i
|
||||
memcached_value_max_bytes = memcached_value_max_megabytes * 1024 * 1024
|
||||
config.cache_store = :mem_cache_store, { value_max_bytes: memcached_value_max_bytes }
|
||||
config.cache_store = :redis_cache_store, {
|
||||
driver: :hiredis,
|
||||
url: ENV.fetch("OFN_REDIS_URL", "redis://localhost:6379/0"),
|
||||
namespace: "cache",
|
||||
reconnect_attempts: 1
|
||||
}
|
||||
|
||||
# Enable serving of images, stylesheets, and JavaScripts from an asset server
|
||||
# config.action_controller.asset_host = "http://assets.example.com"
|
||||
|
||||
@@ -50,11 +50,6 @@ Openfoodnetwork::Application.configure do
|
||||
# Print deprecation notices to the stderr
|
||||
config.active_support.deprecation = :stderr
|
||||
|
||||
# To block requests before running the database cleaner
|
||||
require 'open_food_network/rack_request_blocker'
|
||||
# Make sure the middleware is inserted first in middleware chain
|
||||
config.middleware.insert_before(ActionDispatch::Static, RackRequestBlocker)
|
||||
|
||||
config.active_job.queue_adapter = :test
|
||||
end
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
if defined?(Bullet) && ENV.fetch("ENABLE_BULLET", false)
|
||||
Rails.application.config.after_initialize do
|
||||
Bullet.enable = true
|
||||
Bullet.add_footer = true
|
||||
Bullet.bullet_logger = true
|
||||
Bullet.rails_logger = true
|
||||
end
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
Delayed::Worker.logger = Logger.new(Rails.root.join('log', 'delayed_job.log'))
|
||||
Delayed::Worker.destroy_failed_jobs = false
|
||||
Delayed::Worker.max_run_time = 15.minutes
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ Spree::Gateway.class_eval do
|
||||
end
|
||||
|
||||
Spree.config do |config|
|
||||
config.site_url = ENV['SITE_URL'] if ENV['SITE_URL']
|
||||
config.shipping_instructions = true
|
||||
config.address_requires_state = true
|
||||
config.admin_interface_logo = '/default_images/ofn-logo.png'
|
||||
@@ -31,6 +32,10 @@ Spree.config do |config|
|
||||
config.s3_protocol = ENV.fetch('S3_PROTOCOL', 'https')
|
||||
end
|
||||
|
||||
# Read mail configuration from ENV vars at boot time and ensure the values are
|
||||
# applied correctly in Spree::Config.
|
||||
MailConfiguration.apply!
|
||||
|
||||
# Attachments settings
|
||||
Spree::Image.set_attachment_attribute(:path, ENV['ATTACHMENT_PATH']) if ENV['ATTACHMENT_PATH']
|
||||
Spree::Image.set_attachment_attribute(:url, ENV['ATTACHMENT_URL']) if ENV['ATTACHMENT_URL']
|
||||
|
||||
@@ -163,7 +163,7 @@ de_DE:
|
||||
confirmation_instructions:
|
||||
subject: "Bitte bestätigen Sie die E-Mail-Adresse von %{enterprise} im Open Food Network"
|
||||
welcome:
|
||||
subject: "%{enterprise} ist jetzt im Open Food Network"
|
||||
subject: "%{enterprise} ist jetzt Teil des Open Food Network"
|
||||
email_welcome: "Willkommen"
|
||||
email_registered: "ist jetzt Teil des"
|
||||
email_userguide_html: "Das Benutzerhandbuch mit detaillierter Unterstützung für die Einrichtung Ihres Profils, Produzentenladens oder Hubs finden Sie hier: %{link}"
|
||||
@@ -710,7 +710,7 @@ de_DE:
|
||||
name: Name der Gebühr
|
||||
fee_type: Art der Gebühr
|
||||
manage_fees: Unternehmensgebühren verwalten
|
||||
no_fees_yet: Sie haben noch keine Unternehmensgebühren.
|
||||
no_fees_yet: Sie erheben noch keine Unternehmensgebühren.
|
||||
create_button: Jetzt erstellen
|
||||
images:
|
||||
logo: Logo
|
||||
@@ -735,7 +735,7 @@ de_DE:
|
||||
name: Name der Zahlungsart
|
||||
applies: Aktiv?
|
||||
manage: Zahlungsarten verwalten
|
||||
no_method_yet: Sie haben noch keine Zahlungsarten. Bitte erstellen Sie eine.
|
||||
no_method_yet: Sie haben noch keine Zahlungsart angelegt. Bitte erstellen Sie eine.
|
||||
create_button: Neue Zahlungsart
|
||||
create_one_button: Jetzt erstellen
|
||||
primary_details:
|
||||
@@ -768,7 +768,7 @@ de_DE:
|
||||
manage: "Lieferoptionen verwalten"
|
||||
create_button: "Neue Lieferoption"
|
||||
create_one_button: "Jetzt erstellen"
|
||||
no_method_yet: "Sie haben noch keine Lieferoptionen angelegt."
|
||||
no_method_yet: "Sie haben noch keine Lieferoption angelegt. Bitte erstellen Sie eine."
|
||||
shop_preferences:
|
||||
shopfront_requires_login: "Öffentlich sichtbarer Laden?"
|
||||
shopfront_requires_login_tip: "Wählen Sie aus, ob sich Kunden einloggen müssen, um den Laden zu sehen oder ob er für alle sichtbar ist."
|
||||
@@ -794,7 +794,7 @@ de_DE:
|
||||
shopfront_message: "'Willkommen'-Nachricht im Laden"
|
||||
shopfront_message_placeholder: >
|
||||
Eine optionale Nachricht, um Kunden willkommen zu heißen und zu erklären,
|
||||
wie Sie bei Ihnen einkaufen können. Wenn hier Text eingegeben wird,
|
||||
wie sie bei Ihnen einkaufen können. Wenn hier Text eingegeben wird,
|
||||
wird dieser auf einer Startseite in Ihrem Laden angezeigt, wenn Kunden
|
||||
ihn zum ersten Mal besuchen.
|
||||
shopfront_message_link_tooltip: "Link einfügen/bearbeiten"
|
||||
@@ -862,7 +862,7 @@ de_DE:
|
||||
shipping_methods: Lieferoptionen
|
||||
shipping_methods_tip: Dieses Unternehmen hat Lieferoptionen.
|
||||
enterprise_fees: Unternehmensgebühren
|
||||
enterprise_fees_tip: Dieses Unternehmen hat keine Gebühren.
|
||||
enterprise_fees_tip: Dieses Unternehmen erhebt keine Gebühren.
|
||||
admin_index:
|
||||
name: Name
|
||||
role: Rolle
|
||||
@@ -1044,7 +1044,7 @@ de_DE:
|
||||
enterprises_hubs_tabs:
|
||||
has_no_payment_methods: "%{enterprise} hat keine Zahlungsarten."
|
||||
has_no_shipping_methods: "%{enterprise} hat keine Lieferoptionen."
|
||||
has_no_enterprise_fees: "%{enterprise} hat keine Gebühren."
|
||||
has_no_enterprise_fees: "%{enterprise} erhebt keine Gebühren."
|
||||
enterprise_issues:
|
||||
create_new: Erstellen
|
||||
resend_email: E-Mail erneut senden
|
||||
@@ -1208,7 +1208,7 @@ de_DE:
|
||||
enterprise_logo:
|
||||
destroy_attachment_does_not_exist: "Logo existiert nicht"
|
||||
enterprise_promo_image:
|
||||
destroy_attachment_does_not_exist: "Werbebild existiert nicht."
|
||||
destroy_attachment_does_not_exist: "Hintergrundbild existiert nicht."
|
||||
enterprise_terms_and_conditions:
|
||||
destroy_attachment_does_not_exist: "AGB-Datei existiert nicht."
|
||||
orders:
|
||||
@@ -1237,10 +1237,10 @@ de_DE:
|
||||
mailers:
|
||||
powered_by:
|
||||
open_food_network: "Open Food Network"
|
||||
powered_html: "Dieser Einkauf wurde ermöglicht durch das %{open_food_network}."
|
||||
powered_html: "Ermöglicht durch das %{open_food_network}."
|
||||
menu:
|
||||
cart:
|
||||
cart: "Warenkorb"
|
||||
cart: "Warenkorb/Kasse"
|
||||
cart_sidebar:
|
||||
checkout: "Zur Kasse"
|
||||
edit_cart: "Warenkorb bearbeiten"
|
||||
@@ -1252,7 +1252,7 @@ de_DE:
|
||||
signed_in:
|
||||
profile: "Profil"
|
||||
mobile_menu:
|
||||
cart: "Warenkorb"
|
||||
cart: "Warenkorb/Kasse"
|
||||
register_call:
|
||||
selling_on_ofn: "Sie möchten selbst im Open Food Network verkaufen?"
|
||||
register: "Hier registrieren!"
|
||||
@@ -1472,7 +1472,7 @@ de_DE:
|
||||
brandstory_part2: "Kaufen Sie ein in Hofläden, auf Bauernmärkten, in Food-Hubs oder schließen Sie sich zu Einkaufsgemeinschaften, Kooperativen, Genossenschaften oder einer solidarischen Landwirtschaft zusammen."
|
||||
brandstory_part3: "Die Anbieter bilden gemeinsam ein regionales Netzwerk, in dem sich Käufer und Verkäufer wieder kennen und mit Vertrauen wertschätzend umgegangen wird."
|
||||
brandstory_part4: "Der Programmcode dieser Internet-Plattform ist öffentlich frei verfügbar (Open Source), sie gehört also auch Ihnen und ist unverkäuflich. Alle Einnahmen werden wieder in die Weiterentwicklung des Netzwerks investiert!"
|
||||
brandstory_part5_strong: "Wir nennen es Open Food Network."
|
||||
brandstory_part5_strong: "Das ist das Open Food Network."
|
||||
brandstory_part6: "Sie lieben Ihr Essen! Jetzt können Sie auch Ihr regionales Lebensmittelsystem lieben!"
|
||||
learn_body: "Erkunden Sie Modelle, Geschichten und Ressourcen, um Sie bei der Entwicklung Ihres Fair-Food-Geschäfts oder Ihrer Organisation zu unterstützen. Finden Sie Schulungen, Veranstaltungen und andere Möglichkeiten, um von Gleichgesinnten zu lernen."
|
||||
learn_cta: "Lassen Sie sich inspirieren"
|
||||
@@ -1484,7 +1484,7 @@ de_DE:
|
||||
system_step2: "2. Welche regionalen Lebensmittel kann ich online kaufen?"
|
||||
system_step2_text: "Im Online-Shop des Ladens finden Sie ein großes Sortiment regionaler und saisonaler Produkte. Von Obst und Gemüse über Eier, Milch, Käse, Wurst und Fleisch bis hin zu Backwaren, Süßigkeiten und Fertiggerichten werden Sie fündig. Nutzen Sie die Suche oder die Filter nach Kategorien und Eigenschaften, wie bio, unverpackt oder fair gehandelt."
|
||||
system_step3: "3. Wie kommen regionale Lebensmittel zu mir nach Hause?"
|
||||
system_step3_text: "Jeder Laden kann seine Lieferoptionen selbst festlegen. Viele bieten einen Lieferservice an, oft ist auch die Abholung vor Ort oder an einer Abholstation möglich. Wählen Sie die gewünschte Option einfach beim Abschluss der Bestellung aus. Im Open Food Network kennt man sich - auch das Abstellen der Lieferung auf der Terrasse oder im Gartenhaus lässt sich sicher organisieren. "
|
||||
system_step3_text: "Jeder Laden kann seine Lieferoptionen selbst festlegen. Viele bieten einen Lieferservice an, oft ist auch die Abholung vor Ort oder an einer Abholstation möglich. Wählen Sie die gewünschte Option einfach beim Abschluss der Bestellung aus. Im Open Food Network kennt man sich - auch das Vereinbaren eines Ablageortes lässt sich sicher organisieren. "
|
||||
cta_headline: "Machen Sie die Welt mit Ihrem Einkauf ein kleines bisschen besser."
|
||||
cta_label: "Jetzt regional einkaufen"
|
||||
stats_headline: "Wir erschaffen ein neues Ernährungssystem."
|
||||
@@ -1552,7 +1552,7 @@ de_DE:
|
||||
email_social: "Verbinden Sie sich mit uns:"
|
||||
email_contact: "Schreiben Sie uns eine E-Mail:"
|
||||
email_signoff: "Viele Grüße,"
|
||||
email_signature: "das Team vom Open Food Network"
|
||||
email_signature: "das Team des Open Food Network"
|
||||
email_confirm_customer_greeting: "Hallo %{name},"
|
||||
email_confirm_customer_intro_html: "vielen Dank für Ihren Einkauf bei <strong>%{distributor}</strong>!"
|
||||
email_confirm_customer_number_html: "<strong>Bestellbestätigung #%{number}</strong>"
|
||||
@@ -1763,7 +1763,7 @@ de_DE:
|
||||
sell_user_guide: "Erfahren Sie mehr in unserem Benutzerhandbuch."
|
||||
sell_listing_price: "Die Aufnahme ins Open Food Network ist kostenlos. Das Eröffnen und Betreiben eines Online-Shops ist für Unternehmen mit einem monatlichen Umsatz unter 500 € kostenlos. Bei höherem Umsatz erlauben wir uns nach einer 3-monatigen kostenlosen Testphase die Berechnung von 3 % Gebühr, um unsere Kosten zu decken."
|
||||
sell_embed: "Wir bieten noch weitere Dienste rund um Ihr Unternehmen an."
|
||||
sell_ask_services: "Fragen Sie uns nach OFN-Dienstleistungen."
|
||||
sell_ask_services: "Fragen Sie uns nach Dienstleistungen rund um das Open Food Network."
|
||||
shops_title: Regional Einkaufen
|
||||
shops_headline: Wählen Sie einen Laden aus der Liste.
|
||||
shops_text: Pflanzen wachsen in Zyklen, Landwirte ernten in Zyklen und bei uns bestellen Sie Lebensmittel in Zyklen. Ist ein Bestellzyklus gerade geschlossen, wählen Sie einen anderen Laden oder schauen Sie später wieder vorbei.
|
||||
@@ -1879,23 +1879,23 @@ de_DE:
|
||||
steps:
|
||||
introduction:
|
||||
registration_greeting: "Herzlich willkommen!"
|
||||
registration_intro: "Sie können jetzt ein Profil als Produzent oder Hub erstellen!"
|
||||
registration_intro: "Erstellen Sie zunächst ein Profil um sich oder Ihre Produkte zu präsentieren!"
|
||||
registration_checklist: "Was brauche ich?"
|
||||
registration_time: "5-10 Minuten Zeit"
|
||||
registration_enterprise_address: "Unternehmensadresse"
|
||||
registration_contact_details: "Kontaktdaten (Ansprechpartner, E-Mail-Adresse, Telefonnummer)"
|
||||
registration_logo: "Ihr Logo"
|
||||
registration_promo_image: "Hintergrundbild für Ihr Profil"
|
||||
registration_about_us: "\"Über uns\" Text"
|
||||
registration_enterprise_address: "Unternehmensname und -adresse"
|
||||
registration_contact_details: "Kontaktdaten (Ansprechpartner, E-Mail-Adresse)"
|
||||
registration_logo: "Ihr Logo (empfohlen)"
|
||||
registration_promo_image: "Hintergrundbild für Ihr Profil (empfohlen)"
|
||||
registration_about_us: "\"Über uns\" Text (empfohlen)"
|
||||
registration_outcome_headline: "Was bekomme ich?"
|
||||
registration_outcome1_html: "Ihr Profil hilft dabei, Sie im Open Food Network zu <strong>finden</strong> und zu <strong>kontaktieren</strong>."
|
||||
registration_outcome2: "Nutzen Sie Ihr Profil, um die Geschichte Ihres Unternehmens zu erzählen und verknüpfen Sie Ihren Social-Media- und Web-Auftritt."
|
||||
registration_outcome3: "Ihr Profil ist auch der erste Schritt, um im Open Food Network Produkte zu handeln oder einen Laden zu eröffnen."
|
||||
registration_outcome3: "Ihr Profil ist auch der erste Schritt, um im Open Food Network Produkte zu handeln oder einen Online-Shop zu eröffnen."
|
||||
registration_action: "Los geht's!"
|
||||
details:
|
||||
title: "Ihr Unternehmen"
|
||||
headline: "Ihr Unternehmen"
|
||||
enterprise: "Woot! Zuerst müssen wir ein wenig über Ihr Unternehmen wissen:"
|
||||
enterprise: "Nennen Sie uns zunächst bitte den Namen und die Adresse Ihres Unternehmens."
|
||||
producer: "Nennen Sie uns zunächst bitte den Namen und die Adresse Ihres Betriebs."
|
||||
enterprise_name_field: "Name des Unternehmens:"
|
||||
producer_name_field: "Name des Betriebs:"
|
||||
@@ -1926,80 +1926,80 @@ de_DE:
|
||||
contact_field: "Hauptansprechpartner"
|
||||
contact_field_placeholder: "Vorname Nachname"
|
||||
contact_field_required: "Bitte geben Sie einen Hauptansprechpartner ein."
|
||||
phone_field: "Telefonnummer"
|
||||
phone_field: "Telefonnummer (optional)"
|
||||
phone_field_placeholder: "z. B. 030 1234 5678"
|
||||
type:
|
||||
title: "Art"
|
||||
headline: "Wählen Sie bitte die Profilart von %{enterprise} aus!"
|
||||
question: "Sind Sie ein Produzent?"
|
||||
yes_producer: "Ja, ich bin ein Produzent."
|
||||
no_producer: "Nein, ich bin kein Produzent."
|
||||
producer_field_error: "Bitte wählen Sie: Sind Sie ein Produzent?"
|
||||
title: "Art des Profils"
|
||||
headline: "Wählen Sie bitte die Profilart für %{enterprise} aus!"
|
||||
question: "Ist das Unternehmen ein Produzent?"
|
||||
yes_producer: "Ja, es ist ein Produzent."
|
||||
no_producer: "Nein, es ist kein Produzent."
|
||||
producer_field_error: "Bitte wählen Sie: Ist das Unternehmen ein Produzent?"
|
||||
yes_producer_help: "Produzenten stellen leckere Lebensmittel oder Getränke her. Sie sind ein Produzent, wenn Sie anbauen, brauen, backen, fermentieren, melken oder sonst wie Lebenmittel produzieren."
|
||||
no_producer_help: "Wenn Sie kein Produzent sind, sind Sie wahrscheinlich jemand, der Lebensmittel verkauft und verteilt. Sie könnten ein Foodhub, eine Lebensmittelkooperative, eine Einkaufsgemeinschaft, ein Einzelhändler, Hofladen, Großhändler oder Vergleichbares sein."
|
||||
no_producer_help: "Wenn Sie kein Produzent sind, sind Sie wahrscheinlich jemand, der Lebensmittel verkauft und verteilt. Sie könnten ein Food Hub, eine Lebensmittelkooperative, eine Einkaufsgemeinschaft, ein Einzelhändler, Hofladen, Großhändler oder Vergleichbares sein."
|
||||
create_profile: "Profil erstellen"
|
||||
about:
|
||||
title: "Über uns"
|
||||
headline: "Sehr gut!"
|
||||
message: "Lassen Sie uns nun die Details Ihres Profils bearbeiten:"
|
||||
headline: "Über uns"
|
||||
message: "Beschreiben Sie nun "
|
||||
success: "Sehr gut! %{enterprise} wurde dem Open Food Network hinzugefügt."
|
||||
registration_exit_message: "Wenn Sie diesen Assistenten zu einem beliebigen Zeitpunkt beenden, können Sie mit der Erstellung Ihres Profils fortfahren, indem Sie in das Menü \"Verwaltung\" gehen."
|
||||
enterprise_description: "Kurzbeschreibung"
|
||||
registration_exit_message: "Wenn Sie diesen Assistenten zu einem beliebigen Zeitpunkt beenden, können Sie mit der Erstellung Ihres Profils fortfahren, indem Sie sich einloggen und zum Menü \"Verwaltung\" wechseln."
|
||||
enterprise_description: "Kurzbeschreibung (empfohlen)"
|
||||
enterprise_description_placeholder: "Ein kurzer Satz, der Ihr Unternehmen beschreibt."
|
||||
enterprise_long_desc: "Ausführliche Beschreibung"
|
||||
enterprise_long_desc: "Ausführliche Beschreibung (empfohlen)"
|
||||
enterprise_long_desc_placeholder: "Erzählen Sie hier die Geschichte Ihres Unternehmens - was macht Sie anders und wunderbar? Wir empfehlen, die Beschreibung unter 600 Zeichen oder 150 Wörtern zu halten."
|
||||
enterprise_long_desc_length: "%{num} Zeichen/bis zu 600 empfohlen"
|
||||
enterprise_abn: "USt-IdNr."
|
||||
enterprise_abn: "USt-IdNr. (optional für Rechnungserstellung)"
|
||||
enterprise_abn_placeholder: "z. B. DE999999999"
|
||||
enterprise_acn: "St.-Nr."
|
||||
enterprise_acn: "St.-Nr. (optional für Rechnungserstellung)"
|
||||
enterprise_acn_placeholder: "z. B. 93815/08152"
|
||||
enterprise_tax_required: "Bitte treffen Sie eine Auswahl."
|
||||
images:
|
||||
title: "Bilder"
|
||||
headline: "Vielen Dank!"
|
||||
headline: "Bilder"
|
||||
description: "Laden Sie einige schöne Bilder hoch, um ein ansprechendes Profil zu gestalten!"
|
||||
uploading: "Wird hochgeladen ..."
|
||||
continue: "Weiter"
|
||||
back: "Zurück"
|
||||
logo:
|
||||
select_logo: "Schritt 1. Wählen Sie ein Bild als Ihr Logo aus"
|
||||
select_logo: "Schritt 1: Laden Sie Ihr Logo hoch (empfohlen)"
|
||||
logo_tip: "Tipp: Am besten funktionieren quadratische Bilder, vorzugsweise mindestens 300 × 300 Pixel."
|
||||
logo_label: "Wählen Sie ein Logo aus"
|
||||
logo_label: "Bilddatei auswählen"
|
||||
logo_drag: "Ziehen Sie Ihr Logo hierher."
|
||||
review_logo: "Schritt 2. Überprüfen Sie Ihr Logo"
|
||||
review_logo: "Schritt 2: Überprüfen Sie Ihr Logo"
|
||||
review_logo_tip: "Tipp: Um das schönste Ergebnis zu erzielen, sollte Ihr Logo den gesamten verfügbaren Platz ausfüllen."
|
||||
logo_placeholder: "Ihr Logo wird hier zur Überprüfung angezeigt, sobald es hochgeladen wurde."
|
||||
promo:
|
||||
select_promo_image: "Schritt 3. Wählen Sie ein Werbebild"
|
||||
select_promo_image: "Schritt 3: Laden Sie ein Hintergrundbild hoch (empfohlen)"
|
||||
promo_image_tip: "Tipp: Die als Banner dargestellte bevorzugte Größe beträgt 1200 × 260 Pixel."
|
||||
promo_image_label: "Wählen Sie ein Werbebild"
|
||||
promo_image_label: "Bilddatei auswählen"
|
||||
promo_image_drag: "Ziehen Sie Ihr Bild hierher."
|
||||
review_promo_image: "Schritt 4. Überprüfen Sie Ihr Werbebild"
|
||||
review_promo_image_tip: "Tipp: Für ein optimales Ergebnis sollte Ihr Werbebild den verfügbaren Platz ausfüllen."
|
||||
review_promo_image: "Schritt 4: Überprüfen Sie Ihr Hintergrundbild"
|
||||
review_promo_image_tip: "Tipp: Für ein optimales Ergebnis sollte Ihr Hintergrundbild den verfügbaren Platz ausfüllen."
|
||||
promo_image_placeholder: "Ihr Logo wird hier zur Überprüfung angezeigt, sobald es hochgeladen wurde."
|
||||
social:
|
||||
title: "Soziale Medien"
|
||||
enterprise_final_step: "Letzter Schritt!"
|
||||
enterprise_social_text: "Wie ist %{enterprise} im Internet erreichbar?"
|
||||
website: "Homepage"
|
||||
website: "Homepage (empfohlen)"
|
||||
website_placeholder: "z. B. openfoodnetwork.de"
|
||||
facebook: "Facebook"
|
||||
facebook: "Facebook (optional)"
|
||||
facebook_placeholder: "z. B. www.facebook.com/IhrNameHier"
|
||||
linkedin: "LinkedIn"
|
||||
linkedin: "LinkedIn (optional)"
|
||||
linkedin_placeholder: "z. B. www.linkedin.com/IhrNameHier"
|
||||
twitter: "Twitter"
|
||||
twitter: "Twitter (optional)"
|
||||
twitter_placeholder: "z. B. @twitter_name"
|
||||
instagram: "Instagram"
|
||||
instagram: "Instagram (optional)"
|
||||
instagram_placeholder: "z. B. @instagram_name"
|
||||
limit_reached:
|
||||
headline: "Oh nein!"
|
||||
message: "Sie haben das Limit erreicht!"
|
||||
text: "Sie haben die maximale Anzahl der Unternehmen erreicht, die Sie besitzen dürfen im"
|
||||
text: "Sie haben die maximale Anzahl der Unternehmen erreicht, die Sie verwalten dürfen im"
|
||||
action: "Zurück zur Startseite"
|
||||
finished:
|
||||
headline: "Fertig!"
|
||||
thanks: "Vielen Dank, dass Sie die Details für %{enterprise} ausgefüllt haben."
|
||||
login: "Sie können die Angaben Ihres Unternehmens jederzeit ändern oder aktualisieren, indem Sie sich bei Open Food Network einloggen und zum Menü \"Verwaltung\" wechseln."
|
||||
login: "Sie können die Angaben Ihres Unternehmens jederzeit ändern oder aktualisieren, indem Sie sich einloggen und zum Menü \"Verwaltung\" wechseln."
|
||||
action: "Zur Übersicht der Unternehmen"
|
||||
back: "Zurück"
|
||||
continue: "Weiter"
|
||||
@@ -2972,7 +2972,7 @@ de_DE:
|
||||
back_to_zones_list: "Zurück zur Zonenliste"
|
||||
card_code: "Kartenprüfnummer (3-stellig)"
|
||||
card_number: "Kreditkartennummer"
|
||||
category: "Produktkategorie"
|
||||
category: "Steuerkategorie"
|
||||
created_successfully: "Erfolgreich erstellt"
|
||||
credit: "Guthaben"
|
||||
editing_tax_category: "Steuerkategorie bearbeiten"
|
||||
@@ -3089,7 +3089,7 @@ de_DE:
|
||||
display_currency: "Währung anzeigen"
|
||||
choose_currency: "Währung auswählen"
|
||||
mail_method_settings: "E-Mail-Methodeneinstellungen"
|
||||
mail_settings_notice_html: "Einige der folgenden Einstellungen können nicht geändert werden und werden hier nur zu Zwecken der Fehlerbehebung aufgeführt. Änderungen können vorgenommen werden, indem die Einstellungen der deutschen Instanz aktualisiert und mithilfe von <a href='https://github.com/openfoodfoundation/ofn-install'>ofn-install</a> bereitgestellt werden. Wenden Sie sich an das globale OFN-Team, um weitere Informationen zu erhalten."
|
||||
mail_settings_notice_html: "Einige der folgenden Einstellungen können nicht geändert werden und werden hier nur zu Zwecken der Fehlerbehebung aufgeführt. Änderungen können vorgenommen werden, indem die Einstellungen der deutschen Instanz aktualisiert und mithilfe von <a href='https://github.com/openfoodfoundation/ofn-install'>ofn-install</a> bereitgestellt werden. Wenden Sie sich an das globale Team des Open Food Network, um weitere Informationen zu erhalten."
|
||||
general: "Allgemeines"
|
||||
enable_mail_delivery: "E-Mail-Versand aktivieren"
|
||||
send_mails_as: "E-Mails senden als"
|
||||
@@ -3340,7 +3340,7 @@ de_DE:
|
||||
enterprises_header:
|
||||
ofn_with_tip: Unternehmen sind Produzenten und/oder Hubs und sind die grundlegende Organisationseinheit innerhalb des Open Food Network.
|
||||
enterprise_row:
|
||||
has_no_enterprise_fees: "hat keine Unternehmensgebühren"
|
||||
has_no_enterprise_fees: "erhebt keine Unternehmensgebühren"
|
||||
has_no_payment_methods: "hat keine Zahlungsarten"
|
||||
has_no_shipping_methods: "hat keine Lieferoptionen"
|
||||
products:
|
||||
|
||||
@@ -317,6 +317,8 @@ en_GB:
|
||||
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"
|
||||
|
||||
@@ -317,6 +317,8 @@ en_US:
|
||||
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"
|
||||
|
||||
@@ -85,6 +85,10 @@ es_US:
|
||||
no_default_card: "^ Ninguna tarjeta predeterminada disponible para esta consumidora"
|
||||
shipping_method:
|
||||
not_available_to_shop: "no está disponible para %{shop}"
|
||||
card_details: "Detalles de la tarjeta"
|
||||
card_type: "Tipo de tarjeta"
|
||||
cardholder_name: "Nombre del titular de la tarjeta"
|
||||
community_forum_url: "Liga URL para el foro de la comunidad"
|
||||
customer_instructions: "Instrucciones del Consumidor"
|
||||
devise:
|
||||
confirmations:
|
||||
@@ -120,7 +124,11 @@ es_US:
|
||||
cloned_order_cycle_name: "COPIA DE %{order_cycle}"
|
||||
tax_rate:
|
||||
included_in_price: "Incluido en el precio"
|
||||
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"
|
||||
sku: "SKU"
|
||||
subtotal: "Subtotal"
|
||||
tax_rate: "% Impuestos"
|
||||
validators:
|
||||
date_time_string_validator:
|
||||
@@ -285,6 +293,8 @@ es_US:
|
||||
height: "Altura"
|
||||
width: "Anchura"
|
||||
depth: "Profundidad"
|
||||
payment_could_not_process: "El pago no pudo procesarse"
|
||||
payment_could_not_complete: "El pago no pudo completarse"
|
||||
actions:
|
||||
create_and_add_another: "Crear y agregar otro"
|
||||
create: "Crear"
|
||||
@@ -300,8 +310,12 @@ es_US:
|
||||
destroy: "Eliminar"
|
||||
rename: "Renombrar"
|
||||
admin:
|
||||
adjustments:
|
||||
skipped_changing_canceled_order: "No puede modificar un pedido cancelado."
|
||||
begins_at: Empieza en
|
||||
begins_on: Comienza en
|
||||
bill_address: "Dirección de facturación"
|
||||
ship_address: "Dirección de envío"
|
||||
customer: Consumidora
|
||||
date: Fecha
|
||||
email: Email
|
||||
@@ -1311,6 +1325,9 @@ es_US:
|
||||
address2: Dirección (cont.)
|
||||
city: Ciudad
|
||||
city_placeholder: ej. Barcelona
|
||||
latitude: Latitud
|
||||
longitude: Longitud
|
||||
use_geocoder: ¿Calcular la latitud y longitud automáticamente a partir de la dirección?
|
||||
postcode: Código postal
|
||||
postcode_placeholder: ej. 08025
|
||||
suburb: Barrio
|
||||
@@ -1863,6 +1880,9 @@ es_US:
|
||||
state_field_error: "Región requerida"
|
||||
country_field: "País:"
|
||||
country_field_error: "Por favor selecciona un país"
|
||||
locate_address: "Localizar una dirección en el mapa"
|
||||
confirm_address: "Confirmo que la posición indicada de la empresa en el mapa es correcta."
|
||||
drag_map_marker: "Debido a que muchos productores operan en áreas rurales, la precisión de los mapas siempre se puede ir mejorando. Ayúdanos a comprender mejor dónde está ubicada/o interactuando con el mapa de arriba para mover el marcador haciendo clic o seleccionando el marcador y luego arrastrando a la ubicación que sea más precisa de acuerdo a su conocimiento."
|
||||
contact:
|
||||
title: "Contacto"
|
||||
who_is_managing_enterprise: "¿Quién es responsable de administrar %{enterprise}?"
|
||||
@@ -2813,6 +2833,7 @@ es_US:
|
||||
reports:
|
||||
bulk_coop:
|
||||
filters:
|
||||
date_range: "Rango de fecha"
|
||||
generate_report: "Generar informe"
|
||||
enterprise_fee_summaries:
|
||||
filters:
|
||||
|
||||
@@ -318,6 +318,8 @@ ru:
|
||||
height: "Высота"
|
||||
width: "Ширина"
|
||||
depth: "Глубина"
|
||||
payment_could_not_process: "Платеж не может быть обработан"
|
||||
payment_could_not_complete: "Платеж не может быть завершен"
|
||||
actions:
|
||||
create_and_add_another: "Создать и Добавить Другой"
|
||||
create: "Создать"
|
||||
|
||||
@@ -227,4 +227,3 @@ Spree::Country.create!([
|
||||
{ name: "Saint Kitts and Nevis", iso3: "KNA", iso: "KN", iso_name: "SAINT KITTS AND NEVIS", numcode: "659" },
|
||||
{ name: "Serbia", iso3: "SRB", iso: "RS", "iso_name" => "SERBIA", numcode: "999" }
|
||||
])
|
||||
Spree::Config[:default_country_id] = Spree::Country.find_by(iso: ENV.fetch("DEFAULT_COUNTRY_CODE", "US")).id
|
||||
|
||||
1540
db/schema.rb
1540
db/schema.rb
File diff suppressed because it is too large
Load Diff
16
db/seeds.rb
16
db/seeds.rb
@@ -2,22 +2,8 @@
|
||||
# The data can then be loaded with the rake db:seed (or created alongside the db with db:setup).
|
||||
require 'yaml'
|
||||
|
||||
def set_mail_configuration
|
||||
MailConfiguration.entries= {
|
||||
mail_host: ENV.fetch('MAIL_HOST'),
|
||||
mail_domain: ENV.fetch('MAIL_DOMAIN'),
|
||||
mail_port: ENV.fetch('MAIL_PORT'),
|
||||
mail_auth_type: ENV.fetch('MAIL_AUTH_TYPE', 'login'),
|
||||
smtp_username: ENV.fetch('SMTP_USERNAME'),
|
||||
smtp_password: ENV.fetch('SMTP_PASSWORD'),
|
||||
secure_connection_type: ENV.fetch('MAIL_SECURE_CONNECTION', 'None'),
|
||||
mails_from: ENV.fetch('MAILS_FROM', "no-reply@#{ENV.fetch('MAIL_DOMAIN')}"),
|
||||
mail_bcc: ENV.fetch('MAIL_BCC', ''),
|
||||
intercept_email: ''
|
||||
}
|
||||
end
|
||||
# We need mail_configuration to create a user account, because it sends a confirmation email.
|
||||
set_mail_configuration
|
||||
MailConfiguration.apply!
|
||||
|
||||
puts "[db:seed] Seeding Roles"
|
||||
Spree::Role.where(:name => "admin").first_or_create
|
||||
|
||||
@@ -20,6 +20,10 @@ module OrderManagement
|
||||
# associations try to save and then in turn try to call +update!+ again.)
|
||||
def update
|
||||
update_all_adjustments
|
||||
update_totals_and_states
|
||||
end
|
||||
|
||||
def update_totals_and_states
|
||||
update_totals
|
||||
|
||||
if order.completed?
|
||||
@@ -38,7 +42,7 @@ module OrderManagement
|
||||
# - adjustment_total - total value of all adjustments
|
||||
# - total - order total, it's the equivalent to item_total plus adjustment_total
|
||||
def update_totals
|
||||
order.payment_total = payments.completed.sum(:amount)
|
||||
update_payment_total
|
||||
update_item_total
|
||||
update_adjustment_total
|
||||
update_order_total
|
||||
@@ -49,6 +53,10 @@ module OrderManagement
|
||||
shipments.each { |shipment| shipment.update!(order) }
|
||||
end
|
||||
|
||||
def update_payment_total
|
||||
order.payment_total = payments.completed.sum(:amount)
|
||||
end
|
||||
|
||||
def update_item_total
|
||||
order.item_total = line_items.sum('price * quantity')
|
||||
update_order_total
|
||||
@@ -121,7 +129,7 @@ module OrderManagement
|
||||
end
|
||||
|
||||
def update_all_adjustments
|
||||
order.all_adjustments.reload.each(&:update!)
|
||||
order.all_adjustments.reload.each(&:update_adjustment!)
|
||||
end
|
||||
|
||||
def before_save_hook
|
||||
@@ -137,6 +145,22 @@ module OrderManagement
|
||||
order.ship_address = order.address_from_distributor
|
||||
end
|
||||
|
||||
def after_payment_update(payment)
|
||||
if payment.completed? || payment.void?
|
||||
update_payment_total
|
||||
end
|
||||
|
||||
if order.completed?
|
||||
update_payment_state
|
||||
update_shipments
|
||||
update_shipment_state
|
||||
end
|
||||
|
||||
if payment.completed? || order.completed?
|
||||
persist_totals
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def round_money(value)
|
||||
|
||||
@@ -17,7 +17,7 @@ describe OrderManagement::Reports::BulkCoopController, type: :controller do
|
||||
it "renders the report form" do
|
||||
get :new
|
||||
|
||||
expect(response).to be_success
|
||||
expect(response.status).to eq 200
|
||||
expect(response).to render_template(new_template_path)
|
||||
end
|
||||
end
|
||||
@@ -32,7 +32,7 @@ describe OrderManagement::Reports::BulkCoopController, type: :controller do
|
||||
}, report_format: "csv"
|
||||
}
|
||||
|
||||
expect(response).to be_success
|
||||
expect(response.status).to eq 200
|
||||
expect(response.body).not_to be_blank
|
||||
expect(response.header["Content-Type"]).to eq("text/csv")
|
||||
end
|
||||
|
||||
@@ -17,7 +17,7 @@ describe OrderManagement::Reports::EnterpriseFeeSummariesController, type: :cont
|
||||
it "renders the report form" do
|
||||
get :new
|
||||
|
||||
expect(response).to be_success
|
||||
expect(response.status).to eq 200
|
||||
expect(response).to render_template(new_template_path)
|
||||
end
|
||||
end
|
||||
@@ -29,7 +29,7 @@ describe OrderManagement::Reports::EnterpriseFeeSummariesController, type: :cont
|
||||
report: { start_at: "2018-10-09 07:30:00" }, report_format: "csv"
|
||||
}
|
||||
|
||||
expect(response).to be_success
|
||||
expect(response.status).to eq 200
|
||||
expect(response.body).not_to be_blank
|
||||
expect(response.header["Content-Type"]).to eq("text/csv")
|
||||
end
|
||||
|
||||
@@ -28,7 +28,7 @@ module OrderManagement
|
||||
let(:payment_method) { create(:payment_method) }
|
||||
|
||||
it "returns the pending payment with no change" do
|
||||
expect(payment).to_not receive(:update_attributes)
|
||||
expect(payment).to_not receive(:update)
|
||||
expect(payment_setup.call!).to eq payment
|
||||
end
|
||||
end
|
||||
@@ -38,7 +38,7 @@ module OrderManagement
|
||||
|
||||
context "and the card is already set (the payment source is a credit card)" do
|
||||
it "returns the pending payment with no change" do
|
||||
expect(payment).to_not receive(:update_attributes)
|
||||
expect(payment).to_not receive(:update)
|
||||
expect(payment_setup.call!).to eq payment
|
||||
end
|
||||
end
|
||||
@@ -54,7 +54,7 @@ module OrderManagement
|
||||
it "adds an error to the order and does not update the payment" do
|
||||
payment_setup.call!
|
||||
|
||||
expect(payment).to_not receive(:update_attributes)
|
||||
expect(payment).to_not receive(:update)
|
||||
expect(payment_setup.call!).to eq payment
|
||||
expect(order.errors[:base].first).to eq "There are no authorised "\
|
||||
"credit cards available to charge"
|
||||
@@ -80,7 +80,7 @@ module OrderManagement
|
||||
it "adds an error to the order and does not update the payment" do
|
||||
payment_setup.call!
|
||||
|
||||
expect(payment).to_not receive(:update_attributes)
|
||||
expect(payment).to_not receive(:update)
|
||||
expect(payment_setup.call!).to eq payment
|
||||
expect(order.errors[:base].first).to eq "There are no authorised "\
|
||||
"credit cards available to charge"
|
||||
|
||||
@@ -36,7 +36,7 @@ module OpenFoodNetwork
|
||||
def search
|
||||
@permissions.visible_orders.select("DISTINCT spree_orders.*").
|
||||
complete.not_state(:canceled).
|
||||
search(@params[:q])
|
||||
ransack(@params[:q])
|
||||
end
|
||||
|
||||
def table
|
||||
|
||||
@@ -51,7 +51,7 @@ module OpenFoodNetwork
|
||||
not_state(:canceled).
|
||||
distributed_by_user(@user).
|
||||
managed_by(@user).
|
||||
search(params[:q])
|
||||
ransack(params[:q])
|
||||
end
|
||||
|
||||
def orders
|
||||
|
||||
@@ -36,7 +36,7 @@ module OpenFoodNetwork
|
||||
end
|
||||
|
||||
def search
|
||||
Spree::Order.complete.not_state(:canceled).managed_by(@user).search(params[:q])
|
||||
Spree::Order.complete.not_state(:canceled).managed_by(@user).ransack(params[:q])
|
||||
end
|
||||
|
||||
def table_items
|
||||
|
||||
@@ -1,76 +0,0 @@
|
||||
# Copied from http://blog.salsify.com/engineering/tearing-capybara-ajax-tests
|
||||
# https://gist.github.com/jturkel/9317269/raw/ff7838684370fd8a468ffe1e5ce1f3e46ba39951/rack_request_blocker.rb
|
||||
|
||||
require 'atomic'
|
||||
|
||||
# Rack middleware that keeps track of the number of active requests and can block new requests.
|
||||
class RackRequestBlocker
|
||||
@@num_active_requests = Atomic.new(0)
|
||||
@@block_requests = Atomic.new(false)
|
||||
|
||||
# Returns the number of requests the server is currently processing.
|
||||
def self.num_active_requests
|
||||
@@num_active_requests.value
|
||||
end
|
||||
|
||||
# Prevents the server from accepting new requests. Any new requests will return an HTTP
|
||||
# 503 status.
|
||||
def self.block_requests!
|
||||
@@block_requests.value = true
|
||||
end
|
||||
|
||||
# Allows the server to accept requests again.
|
||||
def self.allow_requests!
|
||||
@@block_requests.value = false
|
||||
end
|
||||
|
||||
def initialize(app)
|
||||
@app = app
|
||||
end
|
||||
|
||||
def call(env)
|
||||
increment_active_requests
|
||||
if block_requests?
|
||||
block_request(env)
|
||||
else
|
||||
@app.call(env)
|
||||
end
|
||||
ensure
|
||||
decrement_active_requests
|
||||
end
|
||||
|
||||
def self.wait_for_requests_complete
|
||||
block_requests!
|
||||
max_wait_time = 30
|
||||
polling_interval = 0.01
|
||||
wait_until = Time.now.in_time_zone + max_wait_time.seconds
|
||||
loop do
|
||||
return if num_active_requests == 0
|
||||
if Time.now.in_time_zone > wait_until
|
||||
raise "Failed waiting for completing requests, #{num_active_requests} running."
|
||||
else
|
||||
sleep(polling_interval)
|
||||
end
|
||||
end
|
||||
ensure
|
||||
allow_requests!
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def block_requests?
|
||||
@@block_requests.value
|
||||
end
|
||||
|
||||
def block_request(_env)
|
||||
[503, {}, []]
|
||||
end
|
||||
|
||||
def increment_active_requests
|
||||
@@num_active_requests.update { |v| v + 1 }
|
||||
end
|
||||
|
||||
def decrement_active_requests
|
||||
@@num_active_requests.update { |v| v - 1 }
|
||||
end
|
||||
end
|
||||
@@ -38,7 +38,7 @@ module OpenFoodNetwork
|
||||
attr_reader :orders_relation, :order_permissions
|
||||
|
||||
def search_orders
|
||||
orders_relation.search(@params[:q])
|
||||
orders_relation.ransack(@params[:q])
|
||||
end
|
||||
|
||||
# From the line_items given, returns the ones that are editable by the user
|
||||
|
||||
@@ -20,7 +20,7 @@ module OpenFoodNetwork
|
||||
|
||||
def search
|
||||
permissions = ::Permissions::Order.new(@user)
|
||||
permissions.editable_orders.complete.not_state(:canceled).search(@opts[:q])
|
||||
permissions.editable_orders.complete.not_state(:canceled).ransack(@opts[:q])
|
||||
end
|
||||
|
||||
def orders
|
||||
|
||||
@@ -12,7 +12,7 @@ module Spree
|
||||
end
|
||||
|
||||
def override!
|
||||
ActionMailer::Base.default_url_options[:host] ||= Config.site_url
|
||||
ActionMailer::Base.default_url_options[:host] ||= ENV.fetch("SITE_URL", Config.site_url)
|
||||
ActionMailer::Base.smtp_settings = mail_server_settings
|
||||
ActionMailer::Base.perform_deliveries = true
|
||||
end
|
||||
|
||||
13
lib/spree/licence.md
Normal file
13
lib/spree/licence.md
Normal file
@@ -0,0 +1,13 @@
|
||||
Spree License
|
||||
=============
|
||||
|
||||
Copyright © 2007-2014, Spree Commerce Inc. and other contributors.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of Spree Commerce Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
_This software is provided by the copyright holders and contributors "as is" and any express or implied warranties, including, but not limited to, the implied warranties of merchantability and fitness for a particular purpose are disclaimed. In no event shall the copyright owner of contributors be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this software, even if advised of the possibility of such damage._
|
||||
@@ -8,9 +8,8 @@ module Stripe
|
||||
stripe_account: stripe_account_id)
|
||||
|
||||
raise_if_last_payment_error_present(payment_intent_response)
|
||||
raise_if_not_in_capture_state(payment_intent_response)
|
||||
|
||||
payment_intent_id
|
||||
payment_intent_response
|
||||
end
|
||||
|
||||
private
|
||||
@@ -21,12 +20,5 @@ module Stripe
|
||||
|
||||
raise Stripe::StripeError, payment_intent_response.last_payment_error.message
|
||||
end
|
||||
|
||||
def raise_if_not_in_capture_state(payment_intent_response)
|
||||
state = payment_intent_response.status
|
||||
return unless state != 'requires_capture'
|
||||
|
||||
raise Stripe::StripeError, I18n.t(:invalid_payment_state, state: state)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -18,56 +18,49 @@ module SampleData
|
||||
fruit = Spree::Taxon.find_by(name: 'Fruit')
|
||||
fungi = Spree::Taxon.find_by(name: 'Fungi')
|
||||
producers = enterprises.select(&:is_primary_producer)
|
||||
distributors = enterprises.select(&:is_distributor)
|
||||
[
|
||||
{
|
||||
name: 'Garlic',
|
||||
price: 20.00,
|
||||
supplier: producers[0],
|
||||
taxons: [vegetables],
|
||||
distributor: distributors[0]
|
||||
},
|
||||
{
|
||||
name: 'Fuji Apple',
|
||||
price: 5.00,
|
||||
supplier: producers[1],
|
||||
taxons: [fruit],
|
||||
distributor: distributors[0]
|
||||
},
|
||||
{
|
||||
name: 'Mushrooms',
|
||||
price: 50.00,
|
||||
supplier: producers[1],
|
||||
taxons: [fungi],
|
||||
distributor: distributors[0]
|
||||
},
|
||||
{
|
||||
name: 'Carrots',
|
||||
price: 3.00,
|
||||
supplier: producers[2],
|
||||
taxons: [vegetables],
|
||||
distributor: distributors[0]
|
||||
},
|
||||
{
|
||||
name: 'Potatoes',
|
||||
price: 2.00,
|
||||
supplier: producers[2],
|
||||
taxons: [vegetables],
|
||||
distributor: distributors[0]
|
||||
},
|
||||
{
|
||||
name: 'Tomatoes',
|
||||
price: 2.00,
|
||||
supplier: producers[2],
|
||||
taxons: [vegetables],
|
||||
distributor: distributors[0]
|
||||
}
|
||||
]
|
||||
end
|
||||
|
||||
def create_product(hash)
|
||||
log "- #{hash[:name]}"
|
||||
params = hash.merge(
|
||||
params = hash.slice(:name, :price).merge(
|
||||
supplier_id: hash[:supplier].id,
|
||||
primary_taxon_id: hash[:taxons].first.id,
|
||||
variant_unit: "weight",
|
||||
|
||||
@@ -25,11 +25,7 @@ Usage: $0 openfoodnetwork@openfoodnetwork.org.au" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if hash zeus 2>/dev/null && [ -e .zeus.sock ]; then
|
||||
RAILS_RUN='zeus r'
|
||||
else
|
||||
RAILS_RUN='bundle exec rails runner'
|
||||
fi
|
||||
RAILS_RUN='bundle exec rails runner'
|
||||
|
||||
# -- Mirror database
|
||||
echo "Mirroring database..."
|
||||
|
||||
15
script/setup
15
script/setup
@@ -18,7 +18,6 @@ RED='\033[0;31m'
|
||||
NO_COLOR='\033[0m'
|
||||
|
||||
RUBY_VERSION=$(cat .ruby-version)
|
||||
NODE_VERSION=$(cat .node-version)
|
||||
|
||||
# Check ruby version
|
||||
if ! ruby --version | grep $RUBY_VERSION > /dev/null; then
|
||||
@@ -26,12 +25,6 @@ if ! ruby --version | grep $RUBY_VERSION > /dev/null; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check node version
|
||||
if ! node --version | grep $NODE_VERSION > /dev/null; then
|
||||
printf "${RED}Open Food Network requires node ${NODE_VERSION}${NO_COLOR}. Have a look at: https://github.com/nodenv/nodenv\n"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Set up Ruby dependencies via Bundler
|
||||
if ! command -v bundle > /dev/null; then
|
||||
./script/install-bundler
|
||||
@@ -39,7 +32,7 @@ fi
|
||||
|
||||
# Install all dependencies
|
||||
bundle check || bundle install
|
||||
npm install
|
||||
yarn install
|
||||
|
||||
# Set up configurable environment variables
|
||||
if [ ! -f config/application.yml ]; then
|
||||
@@ -47,12 +40,6 @@ if [ ! -f config/application.yml ]; then
|
||||
printf "${YELLOW}Copied config/application.yml Make sure to fill it with the appropriate configuration values.\n\n${NO_COLOR}"
|
||||
fi
|
||||
|
||||
# Set up newrelic.yml for development environment, used by the newrelic_rpm gem
|
||||
if [ ! -f config/newrelic.yml ]; then
|
||||
cp config/newrelic.yml.example config/newrelic.yml
|
||||
printf "${YELLOW}Copied config/newrelic.yml which configures the development environment for the newrelic_rpm gem.\n\n${NO_COLOR}"
|
||||
fi
|
||||
|
||||
# Set up the database for both development and test
|
||||
# Confirming the default user and password
|
||||
printf '\n\n' | bundle exec rake db:setup db:test:prepare
|
||||
|
||||
@@ -212,7 +212,7 @@ describe Admin::BulkLineItemsController, type: :controller do
|
||||
expect(line_item1.order).to receive(:reload).with(lock: true)
|
||||
expect(line_item1.order).to receive(:update_line_item_fees!)
|
||||
expect(line_item1.order).to receive(:update_order_fees!)
|
||||
expect(line_item1.order).to receive(:update!).twice
|
||||
expect(line_item1.order).to receive(:update_order!).twice
|
||||
|
||||
spree_put :update, params
|
||||
end
|
||||
@@ -287,6 +287,112 @@ describe Admin::BulkLineItemsController, type: :controller do
|
||||
end
|
||||
end
|
||||
|
||||
context "updating the order's taxes, fees, and states" do
|
||||
let(:distributor) { create(:distributor_enterprise_with_tax) }
|
||||
let!(:order_cycle) {
|
||||
create(:order_cycle, distributors: [distributor],
|
||||
coordinator_fees: [line_item_fee1, line_item_fee2, order_fee])
|
||||
}
|
||||
let(:outgoing_exchange) { order_cycle.exchanges.outgoing.first }
|
||||
|
||||
let!(:order) {
|
||||
create(:order_with_line_items, line_items_count: 2, distributor: distributor, order_cycle: order_cycle)
|
||||
}
|
||||
let(:line_item1) { order.line_items.first }
|
||||
let(:line_item2) { order.line_items.last }
|
||||
|
||||
let!(:zone) { create(:zone_with_member) }
|
||||
let(:tax_included) { true }
|
||||
let(:tax_rate5) { create(:tax_rate, amount: 0.05, zone: zone, included_in_price: tax_included) }
|
||||
let(:tax_rate10) { create(:tax_rate, amount: 0.10, zone: zone, included_in_price: tax_included) }
|
||||
let(:tax_rate15) { create(:tax_rate, amount: 0.15, zone: zone, included_in_price: tax_included) }
|
||||
let(:tax_cat5) { create(:tax_category, tax_rates: [tax_rate5]) }
|
||||
let(:tax_cat10) { create(:tax_category, tax_rates: [tax_rate10]) }
|
||||
let(:tax_cat15) { create(:tax_category, tax_rates: [tax_rate15]) }
|
||||
|
||||
let!(:shipping_method) {
|
||||
create(:shipping_method_with, :shipping_fee, tax_category: tax_cat5, name: "Shiperoo",
|
||||
distributors: [distributor])
|
||||
}
|
||||
let!(:payment_method) { create(:payment_method, :per_item, distributors: [distributor]) }
|
||||
|
||||
let(:line_item_fee1) {
|
||||
create(:enterprise_fee, :per_item, amount: 1, inherits_tax_category: false, tax_category: tax_cat15)
|
||||
}
|
||||
let(:line_item_fee2) {
|
||||
create(:enterprise_fee, :per_item, amount: 2, inherits_tax_category: true)
|
||||
}
|
||||
let(:order_fee) { create(:enterprise_fee, :flat_rate, amount: 3, tax_category: tax_cat15 ) }
|
||||
|
||||
before do
|
||||
outgoing_exchange.variants << [line_item1.variant, line_item2.variant]
|
||||
allow(order).to receive(:tax_zone) { zone }
|
||||
line_item1.product.update_columns(tax_category_id: tax_cat5.id)
|
||||
line_item2.product.update_columns(tax_category_id: tax_cat10.id)
|
||||
|
||||
order.refresh_shipment_rates
|
||||
order.select_shipping_method(shipping_method.id)
|
||||
order.finalize!
|
||||
order.recreate_all_fees!
|
||||
order.create_tax_charge!
|
||||
order.update_order!
|
||||
order.payments << create(:payment, payment_method: payment_method, amount: order.total, state: "completed")
|
||||
|
||||
allow(controller).to receive(:spree_current_user) { distributor.owner }
|
||||
allow(Spree::LineItem).to receive(:find) { line_item1 }
|
||||
allow(line_item1).to receive(:order) { order }
|
||||
end
|
||||
|
||||
describe "updating a line item" do
|
||||
let(:line_item_params) { { quantity: 3 } }
|
||||
let(:params) { { id: line_item1.id, order_id: order.number, line_item: line_item_params } }
|
||||
|
||||
it "correctly updates order totals and states" do
|
||||
expect(order.total).to eq 35.0
|
||||
expect(order.item_total).to eq 20.0
|
||||
expect(order.adjustment_total).to eq 15.0
|
||||
expect(order.included_tax_total).to eq 1.22
|
||||
expect(order.payment_state).to eq "paid"
|
||||
|
||||
expect(order).to receive(:update_order!).at_least(:once).and_call_original
|
||||
expect(order).to receive(:create_tax_charge!).at_least(:once).and_call_original
|
||||
|
||||
spree_put :update, params
|
||||
order.reload
|
||||
|
||||
expect(order.total).to eq 61.0
|
||||
expect(order.item_total).to eq 40.0
|
||||
expect(order.adjustment_total).to eq 21.0
|
||||
expect(order.included_tax_total).to eq 2.65 # Pending: this should be 3.10!
|
||||
expect(order.payment_state).to eq "balance_due"
|
||||
end
|
||||
end
|
||||
|
||||
describe "deleting a line item" do
|
||||
let(:params) { { id: line_item1.id, order_id: order.number } }
|
||||
|
||||
it "correctly updates order totals and states" do
|
||||
expect(order.total).to eq 35.0
|
||||
expect(order.item_total).to eq 20.0
|
||||
expect(order.adjustment_total).to eq 15.0
|
||||
expect(order.included_tax_total).to eq 1.22
|
||||
expect(order.payment_state).to eq "paid"
|
||||
|
||||
expect(order).to receive(:update_order!).at_least(:once).and_call_original
|
||||
expect(order).to receive(:create_tax_charge!).at_least(:once).and_call_original
|
||||
|
||||
spree_delete :destroy, params
|
||||
order.reload
|
||||
|
||||
expect(order.total).to eq 22.0
|
||||
expect(order.item_total).to eq 10.0
|
||||
expect(order.adjustment_total).to eq 12.0
|
||||
expect(order.included_tax_total).to eq 0.99
|
||||
expect(order.payment_state).to eq "credit_owed"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def line_item_ids
|
||||
|
||||
@@ -31,7 +31,7 @@ describe Api::V0::EnterprisesController, type: :controller do
|
||||
|
||||
it "creates as sells=any when it is not a producer" do
|
||||
api_post :create, { enterprise: new_enterprise_params }
|
||||
expect(response).to be_success
|
||||
expect(response.status).to eq 201
|
||||
|
||||
enterprise = Enterprise.last
|
||||
expect(enterprise.sells).to eq('any')
|
||||
@@ -44,7 +44,7 @@ describe Api::V0::EnterprisesController, type: :controller do
|
||||
enterprise: new_enterprise_params.
|
||||
merge({ user_ids: [enterprise_owner.id, manager1.id, manager2.id] })
|
||||
}
|
||||
expect(response).to be_success
|
||||
expect(response.status).to eq 201
|
||||
|
||||
enterprise = Enterprise.last
|
||||
expect(enterprise.user_ids).to match_array([enterprise_owner.id, manager1.id, manager2.id])
|
||||
@@ -83,7 +83,7 @@ describe Api::V0::EnterprisesController, type: :controller do
|
||||
|
||||
it "I can update enterprise image" do
|
||||
api_post :update_image, logo: 'a logo', id: enterprise.id
|
||||
expect(response).to be_success
|
||||
expect(response.status).to eq 200
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -30,7 +30,7 @@ module Api
|
||||
it "removes logo" do
|
||||
spree_delete :destroy, enterprise_id: enterprise
|
||||
|
||||
expect(response).to be_success
|
||||
expect(response.status).to eq 200
|
||||
expect(json_response["id"]).to eq enterprise.id
|
||||
enterprise.reload
|
||||
expect(enterprise.logo?).to be false
|
||||
@@ -53,7 +53,7 @@ module Api
|
||||
|
||||
it "allows removal of logo" do
|
||||
spree_delete :destroy, enterprise_id: enterprise
|
||||
expect(response).to be_success
|
||||
expect(response.status).to eq 200
|
||||
end
|
||||
end
|
||||
|
||||
@@ -62,7 +62,7 @@ module Api
|
||||
|
||||
it "allows removal of logo" do
|
||||
spree_delete :destroy, enterprise_id: enterprise
|
||||
expect(response).to be_success
|
||||
expect(response.status).to eq 200
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -164,6 +164,7 @@ describe Api::V0::ProductsController, type: :controller do
|
||||
|
||||
context 'as an enterprise user' do
|
||||
let(:current_api_user) { supplier_enterprise_user(supplier) }
|
||||
let!(:variant) { create(:variant, product_id: product.id) }
|
||||
|
||||
it 'responds with a successful response' do
|
||||
spree_post :clone, product_id: product.id, format: :json
|
||||
@@ -183,6 +184,27 @@ describe Api::V0::ProductsController, type: :controller do
|
||||
expect(response.status).to eq(201)
|
||||
expect(json_response['name']).to eq("COPY OF #{product_with_image.name}")
|
||||
end
|
||||
|
||||
# test cases related to bug #660: product duplication clones master variant
|
||||
|
||||
# stock info - clone is set to zero
|
||||
it '(does not) clone the stock info of the product' do
|
||||
spree_post :clone, product_id: product.id, format: :json
|
||||
expect(json_response['on_hand']).to eq(0)
|
||||
end
|
||||
|
||||
# variants: only the master variant of the product is cloned
|
||||
it '(does not) clone variants from a product with several variants' do
|
||||
spree_post :clone, product_id: product.id, format: :json
|
||||
expect(Spree::Product.second.variants.count).not_to eq Spree::Product.first.variants.count
|
||||
end
|
||||
|
||||
#price info: it does not consider price changes; it considers the price set upon product creation
|
||||
it '(does not) clone price which was updated' do
|
||||
product.update_attribute(:price, 2.22)
|
||||
spree_post :clone, product_id: product.id, format: :json
|
||||
expect(json_response['price']).not_to eq(2.22)
|
||||
end
|
||||
end
|
||||
|
||||
context 'as an administrator' do
|
||||
|
||||
@@ -30,7 +30,7 @@ module Api
|
||||
it "removes promo image" do
|
||||
spree_delete :destroy, enterprise_id: enterprise
|
||||
|
||||
expect(response).to be_success
|
||||
expect(response.status).to eq 200
|
||||
expect(json_response["id"]).to eq enterprise.id
|
||||
enterprise.reload
|
||||
expect(enterprise.promo_image?).to be false
|
||||
@@ -53,7 +53,7 @@ module Api
|
||||
|
||||
it "allows removal of promo image" do
|
||||
spree_delete :destroy, enterprise_id: enterprise
|
||||
expect(response).to be_success
|
||||
expect(response.status).to eq 200
|
||||
end
|
||||
end
|
||||
|
||||
@@ -62,7 +62,7 @@ module Api
|
||||
|
||||
it "allows removal of promo image" do
|
||||
spree_delete :destroy, enterprise_id: enterprise
|
||||
expect(response).to be_success
|
||||
expect(response.status).to eq 200
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -176,7 +176,88 @@ describe Api::V0::ShipmentsController, type: :controller do
|
||||
end
|
||||
end
|
||||
|
||||
context "can transition a shipment from ready to ship" do
|
||||
describe "#update" do
|
||||
let!(:distributor) { create(:distributor_enterprise) }
|
||||
let!(:shipping_method1) {
|
||||
create(:shipping_method_with, :flat_rate, distributors: [distributor], amount: 10)
|
||||
}
|
||||
let!(:shipping_method2) {
|
||||
create(:shipping_method_with, :flat_rate, distributors: [distributor], amount: 20)
|
||||
}
|
||||
let!(:order_cycle) { create(:order_cycle, distributors: [distributor]) }
|
||||
let!(:order) {
|
||||
create(:completed_order_with_totals, order_cycle: order_cycle, distributor: distributor)
|
||||
}
|
||||
let(:new_shipping_rate) {
|
||||
order.shipment.shipping_rates.select{ |sr| sr.shipping_method == shipping_method2 }.first
|
||||
}
|
||||
let(:params) {
|
||||
{
|
||||
id: order.shipment.number,
|
||||
order_id: order.number,
|
||||
shipment: {
|
||||
selected_shipping_rate_id: new_shipping_rate.id
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
before do
|
||||
order.shipments.first.shipping_methods = [shipping_method1, shipping_method2]
|
||||
order.select_shipping_method(shipping_method1.id)
|
||||
order.update_order!
|
||||
order.update_columns(
|
||||
payment_total: 60,
|
||||
payment_state: "paid"
|
||||
)
|
||||
end
|
||||
|
||||
context "when an order has multiple shipping methods available which could be chosen" do
|
||||
context "changing the selected shipping method" do
|
||||
it "updates the order's totals and states" do
|
||||
expect(order.shipment.shipping_method).to eq shipping_method1
|
||||
expect(order.shipment.cost).to eq 10
|
||||
expect(order.total).to eq 60 # item total is 50, shipping cost is 10
|
||||
expect(order.payment_state).to eq "paid" # order is fully paid for
|
||||
|
||||
api_put :update, params
|
||||
expect(response.status).to eq 200
|
||||
|
||||
order.reload
|
||||
|
||||
expect(order.shipment.shipping_method).to eq shipping_method2
|
||||
expect(order.shipment.cost).to eq 20
|
||||
expect(order.total).to eq 70 # item total is 50, shipping cost is 20
|
||||
expect(order.payment_state).to eq "balance_due" # total changed, payment is due
|
||||
end
|
||||
|
||||
context "using the 'unlock' parameter with closed adjustments" do
|
||||
before do
|
||||
order.shipment_adjustments.each(&:close)
|
||||
end
|
||||
|
||||
it "does not update closed adjustments without unlock option" do
|
||||
params[:shipment][:unlock] = "no"
|
||||
|
||||
expect {
|
||||
api_put :update, params
|
||||
expect(response.status).to eq 200
|
||||
}.to_not change { order.reload.shipment.fee_adjustment.amount }
|
||||
end
|
||||
|
||||
it "updates closed adjustments with unlock option selected" do
|
||||
params[:shipment][:unlock] = "yes"
|
||||
|
||||
expect {
|
||||
api_put :update, params
|
||||
expect(response.status).to eq 200
|
||||
}.to change { order.reload.shipment.fee_adjustment.amount }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "#ship" do
|
||||
before do
|
||||
allow_any_instance_of(Spree::Order).to receive_messages(paid?: true, complete?: true)
|
||||
# For the shipment notification email
|
||||
|
||||
@@ -10,21 +10,21 @@ module Api
|
||||
it "returns alive when up to date" do
|
||||
Spree::Config.last_job_queue_heartbeat_at = Time.now.in_time_zone
|
||||
get :job_queue
|
||||
expect(response).to be_success
|
||||
expect(response.status).to eq 200
|
||||
expect(response.body).to eq({ alive: true }.to_json)
|
||||
end
|
||||
|
||||
it "returns dead otherwise" do
|
||||
Spree::Config.last_job_queue_heartbeat_at = 10.minutes.ago
|
||||
get :job_queue
|
||||
expect(response).to be_success
|
||||
expect(response.status).to eq 200
|
||||
expect(response.body).to eq({ alive: false }.to_json)
|
||||
end
|
||||
|
||||
it "returns dead when no heartbeat recorded" do
|
||||
Spree::Config.last_job_queue_heartbeat_at = nil
|
||||
get :job_queue
|
||||
expect(response).to be_success
|
||||
expect(response.status).to eq 200
|
||||
expect(response.body).to eq({ alive: false }.to_json)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -26,7 +26,7 @@ module Api
|
||||
it "removes terms and conditions file" do
|
||||
spree_delete :destroy, enterprise_id: enterprise
|
||||
|
||||
expect(response).to be_success
|
||||
expect(response.status).to eq 200
|
||||
expect(json_response["id"]).to eq enterprise.id
|
||||
enterprise.reload
|
||||
expect(enterprise.terms_and_conditions?).to be false
|
||||
|
||||
@@ -118,7 +118,7 @@ describe CheckoutController, type: :controller do
|
||||
|
||||
it "does not redirect" do
|
||||
get :edit
|
||||
expect(response).to be_success
|
||||
expect(response.status).to eq 200
|
||||
end
|
||||
|
||||
it "returns a specific flash message when Spree::Core::GatewayError occurs" do
|
||||
@@ -291,7 +291,7 @@ describe CheckoutController, type: :controller do
|
||||
allow(controller).to receive(:current_order).and_return(order)
|
||||
end
|
||||
|
||||
it "returns errors and flash if order.update_attributes fails" do
|
||||
it "returns errors and flash if order.update fails" do
|
||||
spree_post :update, format: :json, order: {}
|
||||
expect(response.status).to eq(400)
|
||||
expect(response.body).to eq({ errors: assigns[:order].errors, flash: { error: order.errors.full_messages.to_sentence } }.to_json)
|
||||
|
||||
@@ -55,7 +55,7 @@ describe LineItemsController, type: :controller do
|
||||
|
||||
context "where the item's order is associated with the current user" do
|
||||
before do
|
||||
order.update_attributes!(user_id: user.id)
|
||||
order.update!(user_id: user.id)
|
||||
allow(controller).to receive_messages spree_current_user: item.order.user
|
||||
end
|
||||
|
||||
@@ -67,7 +67,7 @@ describe LineItemsController, type: :controller do
|
||||
end
|
||||
|
||||
context "with an order cycle and distributor" do
|
||||
before { order.update_attributes!(order_cycle_id: order_cycle.id, distributor_id: distributor.id) }
|
||||
before { order.update!(order_cycle_id: order_cycle.id, distributor_id: distributor.id) }
|
||||
|
||||
context "where changes are not allowed" do
|
||||
it "denies deletion" do
|
||||
@@ -77,7 +77,7 @@ describe LineItemsController, type: :controller do
|
||||
end
|
||||
|
||||
context "where changes are allowed" do
|
||||
before { distributor.update_attributes!(allow_order_changes: true) }
|
||||
before { distributor.update!(allow_order_changes: true) }
|
||||
|
||||
it "deletes the line item" do
|
||||
delete :destroy, params: params
|
||||
|
||||
@@ -36,7 +36,7 @@ describe ShopController, type: :controller do
|
||||
oc2 = create(:simple_order_cycle, distributors: [distributor])
|
||||
|
||||
spree_post :order_cycle, order_cycle_id: oc2.id
|
||||
expect(response).to be_success
|
||||
expect(response.status).to eq 200
|
||||
expect(controller.current_order_cycle).to eq(oc2)
|
||||
end
|
||||
|
||||
@@ -48,7 +48,7 @@ describe ShopController, type: :controller do
|
||||
oc2 = create(:simple_order_cycle, distributors: [distributor])
|
||||
|
||||
spree_post :order_cycle, order_cycle_id: oc2.id
|
||||
expect(response).to be_success
|
||||
expect(response.status).to eq 200
|
||||
expect(response.body).to have_content oc2.id
|
||||
end
|
||||
|
||||
@@ -68,7 +68,7 @@ describe ShopController, type: :controller do
|
||||
|
||||
it "returns the new order cycle details" do
|
||||
spree_post :order_cycle, order_cycle_id: oc2.id
|
||||
expect(response).to be_success
|
||||
expect(response.status).to eq 200
|
||||
expect(response.body).to have_content oc2.id
|
||||
end
|
||||
end
|
||||
|
||||
@@ -8,7 +8,7 @@ describe Spree::Admin::PaymentsController, type: :controller do
|
||||
|
||||
let!(:shop) { create(:enterprise) }
|
||||
let!(:user) { shop.owner }
|
||||
let!(:order) { create(:order, distributor: shop, state: 'complete') }
|
||||
let!(:order) { create(:completed_order_with_totals, distributor: shop) }
|
||||
let!(:line_item) { create(:line_item, order: order, price: 5.0) }
|
||||
|
||||
before do
|
||||
|
||||
@@ -309,5 +309,19 @@ describe Spree::Admin::PaymentsController, type: :controller do
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "the order contains an item that is out of stock" do
|
||||
let!(:order) { create(:order, distributor: shop, state: 'payment') }
|
||||
|
||||
before do
|
||||
order.line_items.first.variant.update_attribute(:on_hand, 0)
|
||||
end
|
||||
|
||||
it "redirects to the order details page" do
|
||||
spree_get :index, order_id: order.number
|
||||
expect(response.status).to eq 302
|
||||
expect(response.location).to eq spree.edit_admin_order_url(order)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -17,7 +17,7 @@ module Spree
|
||||
|
||||
# Pay the order
|
||||
order.payments.first.complete
|
||||
order.update!
|
||||
order.update_order!
|
||||
|
||||
# Ship the order
|
||||
order.shipment.ship!
|
||||
|
||||
@@ -24,7 +24,7 @@ describe Spree::OrdersController, type: :controller do
|
||||
|
||||
it "loads page" do
|
||||
get :show, params: { id: order.number, token: order.token }
|
||||
expect(response).to be_success
|
||||
expect(response.status).to eq 200
|
||||
end
|
||||
|
||||
it "stores order token in session as 'access_token'" do
|
||||
@@ -43,7 +43,7 @@ describe Spree::OrdersController, type: :controller do
|
||||
|
||||
it "loads page" do
|
||||
get :show, params: { id: order.number }
|
||||
expect(response).to be_success
|
||||
expect(response.status).to eq 200
|
||||
end
|
||||
end
|
||||
|
||||
@@ -52,7 +52,7 @@ describe Spree::OrdersController, type: :controller do
|
||||
|
||||
it "loads page" do
|
||||
get :show, params: { id: order.number }
|
||||
expect(response).to be_success
|
||||
expect(response.status).to eq 200
|
||||
end
|
||||
end
|
||||
|
||||
@@ -82,7 +82,10 @@ describe Spree::OrdersController, type: :controller do
|
||||
|
||||
describe "confirming a payment intent" do
|
||||
let(:customer) { create(:customer) }
|
||||
let(:order) { create(:order, customer: customer, distributor: customer.enterprise) }
|
||||
let(:order) {
|
||||
create(:order_with_totals, customer: customer, distributor: customer.enterprise,
|
||||
state: "payment")
|
||||
}
|
||||
let(:payment_method) { create(:stripe_sca_payment_method) }
|
||||
let!(:payment) { create(
|
||||
:payment,
|
||||
@@ -102,39 +105,66 @@ describe Spree::OrdersController, type: :controller do
|
||||
|
||||
context "with a valid payment intent" do
|
||||
let(:payment_intent) { "pi_123" }
|
||||
let(:payment_intent_response) { double(id: "pi_123", status: "requires_capture") }
|
||||
|
||||
before do
|
||||
allow_any_instance_of(Stripe::PaymentIntentValidator)
|
||||
.to receive(:call)
|
||||
.with(payment_intent, anything)
|
||||
.and_return(payment_intent)
|
||||
.with(payment_intent, kind_of(String))
|
||||
.and_return(payment_intent_response)
|
||||
|
||||
allow(Spree::Order).to receive(:find_by!) { order }
|
||||
end
|
||||
|
||||
it "completes the payment" do
|
||||
get :show, params: { id: order.number, payment_intent: payment_intent }
|
||||
context "when the order is in payment state" do
|
||||
it "completes the payment" do
|
||||
expect(order).to receive(:process_payments!) do
|
||||
payment.complete!
|
||||
end
|
||||
|
||||
expect(response).to be_success
|
||||
payment.reload
|
||||
expect(payment.cvv_response_message).to be nil
|
||||
expect(payment.state).to eq("completed")
|
||||
get :show, params: { id: order.number, payment_intent: payment_intent }
|
||||
|
||||
expect(response.status).to eq 200
|
||||
payment.reload
|
||||
expect(payment.state).to eq("completed")
|
||||
expect(payment.cvv_response_message).to be nil
|
||||
end
|
||||
end
|
||||
|
||||
context "when the order is already completed" do
|
||||
before do
|
||||
order.update_columns(state: "complete")
|
||||
end
|
||||
|
||||
it "should still process the payment" do
|
||||
expect(order).to receive(:process_payments!) do
|
||||
payment.complete!
|
||||
end
|
||||
|
||||
get :show, params: { id: order.number, payment_intent: payment_intent }
|
||||
expect(response.status).to eq 200
|
||||
payment.reload
|
||||
expect(payment.state).to eq("completed")
|
||||
expect(payment.cvv_response_message).to be nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "with an invalid payment intent" do
|
||||
let(:payment_intent) { "invalid" }
|
||||
let(:result) { instance_double(ProcessPaymentIntent::Result) }
|
||||
context "when the payment intent response has errors" do
|
||||
let(:payment_intent) { "pi_123" }
|
||||
|
||||
before do
|
||||
allow_any_instance_of(Stripe::PaymentIntentValidator)
|
||||
.to receive(:call)
|
||||
.with(payment_intent, anything)
|
||||
.and_return(result)
|
||||
.with(payment_intent, kind_of(String))
|
||||
.and_raise(Stripe::StripeError, "error message")
|
||||
end
|
||||
|
||||
it "does not complete the payment" do
|
||||
get :show, params: { id: order.number, payment_intent: payment_intent }
|
||||
|
||||
expect(response).to be_success
|
||||
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")
|
||||
expect(payment.state).to eq("pending")
|
||||
@@ -148,12 +178,18 @@ 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)
|
||||
end
|
||||
|
||||
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")}. ")
|
||||
payment.reload
|
||||
expect(payment.cvv_response_message).to eq("https://stripe.com/redirect")
|
||||
expect(payment.state).to eq("pending")
|
||||
@@ -219,10 +255,6 @@ describe Spree::OrdersController, type: :controller do
|
||||
describe "the page" do
|
||||
render_views
|
||||
|
||||
it "provides the right registration path" do
|
||||
expect(subject.registration_path).to eq registration_path
|
||||
end
|
||||
|
||||
it "shows the right registration link" do
|
||||
# We fixed our view by hardcoding the link.
|
||||
spree_registration_path = '/signup'
|
||||
@@ -497,7 +529,7 @@ describe Spree::OrdersController, type: :controller do
|
||||
end
|
||||
|
||||
before do
|
||||
order.update_attributes!(order_cycle_id: order_cycle.id, distributor_id: distributor.id)
|
||||
order.update!(order_cycle_id: order_cycle.id, distributor_id: distributor.id)
|
||||
end
|
||||
|
||||
it "returns the order" do
|
||||
|
||||
@@ -15,7 +15,7 @@ describe UserPasswordsController, type: :controller do
|
||||
describe "create" do
|
||||
it "returns errors" do
|
||||
spree_post :create, spree_user: {}
|
||||
expect(response).to be_success
|
||||
expect(response.status).to eq 200
|
||||
expect(response).to render_template "spree/user_passwords/new"
|
||||
end
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user