mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-01-16 19:16:49 +00:00
Compare commits
122 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d7cadde0a1 | ||
|
|
003b45d4b9 | ||
|
|
1eb5ee9266 | ||
|
|
a9c7f84bd3 | ||
|
|
4efcd8457c | ||
|
|
8261a33ae4 | ||
|
|
7312341fc4 | ||
|
|
f94fe452f0 | ||
|
|
2292deebe6 | ||
|
|
3f4b97d006 | ||
|
|
c40928d805 | ||
|
|
7b391adbac | ||
|
|
93efd3ab8f | ||
|
|
29d3c61b52 | ||
|
|
b6b07328ee | ||
|
|
35f6f8e73d | ||
|
|
bb0cf65ecc | ||
|
|
a02c505e62 | ||
|
|
77506caca1 | ||
|
|
ff82d37a40 | ||
|
|
958023d6da | ||
|
|
7857487bbb | ||
|
|
8a5762afba | ||
|
|
b2840aaebf | ||
|
|
e43f98405a | ||
|
|
756b3a6ee5 | ||
|
|
9c468f0557 | ||
|
|
f3347229fb | ||
|
|
7e255442a5 | ||
|
|
02009ed48b | ||
|
|
3f14694b2b | ||
|
|
d34dd30e51 | ||
|
|
0954a13f55 | ||
|
|
38cba66207 | ||
|
|
0d935725e2 | ||
|
|
b799a1777f | ||
|
|
3fb2e503f5 | ||
|
|
cd6ef9e274 | ||
|
|
ce83be4eac | ||
|
|
aac4a17c1f | ||
|
|
0eaa4aeb62 | ||
|
|
880075729d | ||
|
|
dee2004305 | ||
|
|
57035ae0cc | ||
|
|
b6b367c378 | ||
|
|
d447864b7e | ||
|
|
08491d9ad4 | ||
|
|
7882c427f7 | ||
|
|
dbe227bd41 | ||
|
|
e71f47a2e3 | ||
|
|
4b4f29641e | ||
|
|
fcb8145a6c | ||
|
|
c480d43bda | ||
|
|
4c5ecbc2d4 | ||
|
|
3c1883dac2 | ||
|
|
8db598bff7 | ||
|
|
a67038720c | ||
|
|
74ba6e35be | ||
|
|
42efb6f762 | ||
|
|
7d5726b6c7 | ||
|
|
741dee29c3 | ||
|
|
a41852ee7a | ||
|
|
877d76cf19 | ||
|
|
0980b81742 | ||
|
|
30df1cc55d | ||
|
|
c05a9cfb40 | ||
|
|
adff08038a | ||
|
|
e8bc1f5aca | ||
|
|
ab3b36ac0b | ||
|
|
1a25fb78df | ||
|
|
e7e337f0aa | ||
|
|
65f9454760 | ||
|
|
9094a133d6 | ||
|
|
9092b60229 | ||
|
|
4bddc59696 | ||
|
|
9c2010a43e | ||
|
|
558457993a | ||
|
|
2c1305b99e | ||
|
|
9f4b825d46 | ||
|
|
eccfcbc396 | ||
|
|
dcb5b36859 | ||
|
|
f004cc5b91 | ||
|
|
2be04cc25c | ||
|
|
e5b1af131f | ||
|
|
707876820a | ||
|
|
5fe8f89e32 | ||
|
|
42803e7a0f | ||
|
|
05d38efd8c | ||
|
|
e38336693a | ||
|
|
f70473677b | ||
|
|
25abf46599 | ||
|
|
f0365790d6 | ||
|
|
2e2e9918a9 | ||
|
|
fe3013b0b9 | ||
|
|
02703053bc | ||
|
|
a4f9706082 | ||
|
|
9f4d2b27bd | ||
|
|
e450fe95a1 | ||
|
|
d92510db56 | ||
|
|
025f1f2725 | ||
|
|
51d075166a | ||
|
|
0b9c62284a | ||
|
|
ef38abed28 | ||
|
|
5a19a14042 | ||
|
|
0ea085a275 | ||
|
|
2b93814fb1 | ||
|
|
2849f18313 | ||
|
|
6f340174d3 | ||
|
|
b27ecb3465 | ||
|
|
36ab3825e9 | ||
|
|
c7b85a3591 | ||
|
|
1a1552a6ed | ||
|
|
f494b720f8 | ||
|
|
9762275555 | ||
|
|
5082b6dc99 | ||
|
|
5815d1a4a4 | ||
|
|
50e0d78c0c | ||
|
|
0da90ab834 | ||
|
|
6c17680423 | ||
|
|
365dc2a49e | ||
|
|
a70b2a12d1 | ||
|
|
a82bae2a46 |
19
.github/workflows/build.yml
vendored
19
.github/workflows/build.yml
vendored
@@ -8,6 +8,7 @@ on:
|
||||
env:
|
||||
DISABLE_KNAPSACK: true
|
||||
TIMEZONE: UTC
|
||||
COVERAGE: true
|
||||
|
||||
jobs:
|
||||
test-controllers-and-serializers:
|
||||
@@ -51,6 +52,9 @@ jobs:
|
||||
- name: Run controller tests
|
||||
run: bundle exec rspec --profile -- spec/controllers spec/serializers
|
||||
|
||||
- name: Codecov
|
||||
uses: codecov/codecov-action@v1.3.1
|
||||
|
||||
test-models:
|
||||
runs-on: ubuntu-18.04
|
||||
services:
|
||||
@@ -92,6 +96,9 @@ jobs:
|
||||
- name: Run tests
|
||||
run: bundle exec rspec --profile -- spec/models
|
||||
|
||||
- name: Codecov
|
||||
uses: codecov/codecov-action@v1.3.1
|
||||
|
||||
test-admin-features-1:
|
||||
runs-on: ubuntu-18.04
|
||||
services:
|
||||
@@ -133,6 +140,9 @@ jobs:
|
||||
- name: Run admin feature tests
|
||||
run: bundle exec rspec --profile -- spec/features/admin/[a-o0-9]*_spec.rb
|
||||
|
||||
- name: Codecov
|
||||
uses: codecov/codecov-action@v1.3.1
|
||||
|
||||
test-admin-features-2:
|
||||
runs-on: ubuntu-18.04
|
||||
services:
|
||||
@@ -174,6 +184,9 @@ jobs:
|
||||
- name: Run admin feature tests
|
||||
run: bundle exec rspec --profile -- spec/features/admin/[p-z]*_spec.rb
|
||||
|
||||
- name: Codecov
|
||||
uses: codecov/codecov-action@v1.3.1
|
||||
|
||||
test-consumer-features:
|
||||
runs-on: ubuntu-18.04
|
||||
services:
|
||||
@@ -215,6 +228,9 @@ jobs:
|
||||
- name: Run consumer feature tests
|
||||
run: bundle exec rspec --profile -- spec/features/consumer
|
||||
|
||||
- name: Codecov
|
||||
uses: codecov/codecov-action@v1.3.1
|
||||
|
||||
test-engines-etc:
|
||||
runs-on: ubuntu-18.04
|
||||
services:
|
||||
@@ -299,3 +315,6 @@ jobs:
|
||||
|
||||
- name: Run admin feature folders, engines, lib
|
||||
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
|
||||
|
||||
@@ -1112,7 +1112,6 @@ Style/FrozenStringLiteralComment:
|
||||
- 'app/serializers/api/uncached_enterprise_serializer.rb'
|
||||
- 'app/serializers/api/user_serializer.rb'
|
||||
- 'app/serializers/api/variant_serializer.rb'
|
||||
- 'app/services/action_callbacks.rb'
|
||||
- 'app/services/bulk_invoice_service.rb'
|
||||
- 'app/services/cart_service.rb'
|
||||
- 'app/services/create_order_cycle.rb'
|
||||
@@ -1170,7 +1169,7 @@ Style/FrozenStringLiteralComment:
|
||||
- 'engines/order_management/app/services/reports/renderers/base.rb'
|
||||
- 'engines/order_management/app/services/reports/report_data/base.rb'
|
||||
- 'engines/web/app/controllers/web/angular_templates_controller.rb'
|
||||
- 'engines/web/app/controllers/web/api/cookies_consent_controller.rb'
|
||||
- 'engines/web/app/controllers/web/api/v0/cookies_consent_controller.rb'
|
||||
- 'engines/web/app/controllers/web/application_controller.rb'
|
||||
- 'engines/web/app/helpers/web/cookies_policy_helper.rb'
|
||||
- 'engines/web/lib/web/cookies_consent.rb'
|
||||
|
||||
@@ -1 +1 @@
|
||||
2.4.4
|
||||
2.5.8
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
#!/bin/env ruby
|
||||
|
||||
SimpleCov.start 'rails' do
|
||||
minimum_coverage 54
|
||||
|
||||
add_filter '/bin/'
|
||||
add_filter '/config/'
|
||||
add_filter '/jobs/application_job.rb'
|
||||
@@ -16,3 +14,6 @@ SimpleCov.start 'rails' do
|
||||
add_filter '/log'
|
||||
add_filter '/db'
|
||||
end
|
||||
|
||||
require 'codecov'
|
||||
SimpleCov.formatter = SimpleCov::Formatter::Codecov
|
||||
|
||||
7
Gemfile
7
Gemfile
@@ -1,7 +1,7 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
source 'https://rubygems.org'
|
||||
ruby "2.4.4"
|
||||
ruby "2.5.8"
|
||||
git_source(:github) { |repo_name| "https://github.com/#{repo_name}.git" }
|
||||
|
||||
gem 'rails', '~> 5.0.0'
|
||||
@@ -31,7 +31,7 @@ gem 'web', path: './engines/web'
|
||||
gem 'activerecord-postgresql-adapter'
|
||||
gem 'pg', '~> 0.21.0'
|
||||
|
||||
gem 'acts_as_list', '0.9.19'
|
||||
gem 'acts_as_list', '1.0.3'
|
||||
gem 'cancancan', '~> 1.15.0'
|
||||
gem 'ffaker'
|
||||
gem 'highline', '2.0.3' # Necessary for the install generator
|
||||
@@ -125,7 +125,7 @@ group :test, :development do
|
||||
gem 'bullet'
|
||||
gem 'capybara'
|
||||
gem 'database_cleaner', require: false
|
||||
gem "factory_bot_rails", '5.2.0', require: false
|
||||
gem "factory_bot_rails", '6.1.0', require: false
|
||||
gem 'fuubar', '~> 2.5.1'
|
||||
gem 'json_spec', '~> 1.1.4'
|
||||
gem 'knapsack'
|
||||
@@ -141,6 +141,7 @@ group :test, :development do
|
||||
end
|
||||
|
||||
group :test do
|
||||
gem 'codecov', require: false
|
||||
gem 'simplecov', require: false
|
||||
gem 'test-prof'
|
||||
gem 'webmock'
|
||||
|
||||
59
Gemfile.lock
59
Gemfile.lock
@@ -77,7 +77,7 @@ GEM
|
||||
activejob (5.0.7.2)
|
||||
activesupport (= 5.0.7.2)
|
||||
globalid (>= 0.3.6)
|
||||
activemerchant (1.107.4)
|
||||
activemerchant (1.119.0)
|
||||
activesupport (>= 4.2)
|
||||
builder (>= 2.1.2, < 4.0.0)
|
||||
i18n (>= 0.6.9)
|
||||
@@ -105,8 +105,8 @@ GEM
|
||||
tzinfo (~> 1.1)
|
||||
acts-as-taggable-on (7.0.0)
|
||||
activerecord (>= 5.0, < 6.2)
|
||||
acts_as_list (0.9.19)
|
||||
activerecord (>= 3.0)
|
||||
acts_as_list (1.0.3)
|
||||
activerecord (>= 4.2)
|
||||
addressable (2.7.0)
|
||||
public_suffix (>= 2.0.2, < 5.0)
|
||||
andand (1.3.3)
|
||||
@@ -114,7 +114,7 @@ GEM
|
||||
railties (>= 4.2, < 7)
|
||||
sprockets (>= 3.0, < 5)
|
||||
tilt
|
||||
angular_rails_csrf (4.2.0)
|
||||
angular_rails_csrf (4.5.0)
|
||||
railties (>= 3, < 7)
|
||||
angularjs-file-upload-rails (2.4.1)
|
||||
angularjs-rails (1.5.5)
|
||||
@@ -130,7 +130,7 @@ GEM
|
||||
json (~> 1.4)
|
||||
nokogiri (~> 1)
|
||||
bcrypt (3.1.16)
|
||||
bugsnag (6.19.0)
|
||||
bugsnag (6.20.0)
|
||||
concurrent-ruby (~> 1.0)
|
||||
builder (3.2.4)
|
||||
bullet (6.1.4)
|
||||
@@ -138,13 +138,13 @@ GEM
|
||||
uniform_notifier (~> 1.11)
|
||||
byebug (11.1.3)
|
||||
cancancan (1.15.0)
|
||||
capybara (3.32.2)
|
||||
capybara (3.35.3)
|
||||
addressable
|
||||
mini_mime (>= 0.1.3)
|
||||
nokogiri (~> 1.8)
|
||||
rack (>= 1.6.0)
|
||||
rack-test (>= 0.6.3)
|
||||
regexp_parser (~> 1.5)
|
||||
regexp_parser (>= 1.5, < 3.0)
|
||||
xpath (~> 3.2)
|
||||
childprocess (3.0.0)
|
||||
chronic (0.10.2)
|
||||
@@ -152,6 +152,8 @@ GEM
|
||||
climate_control (0.2.0)
|
||||
cocaine (0.5.8)
|
||||
climate_control (>= 0.0.3, < 1.0)
|
||||
codecov (0.5.1)
|
||||
simplecov (>= 0.15, < 0.22)
|
||||
coderay (1.1.3)
|
||||
coffee-rails (4.2.2)
|
||||
coffee-script (>= 2.2.0)
|
||||
@@ -187,7 +189,7 @@ GEM
|
||||
daemons (1.3.1)
|
||||
dalli (2.7.11)
|
||||
database_cleaner (1.99.0)
|
||||
ddtrace (0.46.0)
|
||||
ddtrace (0.47.0)
|
||||
msgpack
|
||||
debugger-linecache (1.2.0)
|
||||
delayed_job (4.1.9)
|
||||
@@ -211,22 +213,22 @@ GEM
|
||||
devise-token_authenticatable (1.1.0)
|
||||
devise (>= 4.0.0, < 5.0.0)
|
||||
diff-lcs (1.4.4)
|
||||
docile (1.3.4)
|
||||
docile (1.3.5)
|
||||
erubis (2.7.0)
|
||||
eventmachine (1.2.7)
|
||||
excon (0.79.0)
|
||||
execjs (2.7.0)
|
||||
factory_bot (5.2.0)
|
||||
activesupport (>= 4.2.0)
|
||||
factory_bot_rails (5.2.0)
|
||||
factory_bot (~> 5.2.0)
|
||||
railties (>= 4.2.0)
|
||||
factory_bot (6.1.0)
|
||||
activesupport (>= 5.0.0)
|
||||
factory_bot_rails (6.1.0)
|
||||
factory_bot (~> 6.1.0)
|
||||
railties (>= 5.0.0)
|
||||
faraday (1.3.0)
|
||||
faraday-net_http (~> 1.0)
|
||||
multipart-post (>= 1.2, < 3)
|
||||
ruby2_keywords
|
||||
faraday-net_http (1.0.1)
|
||||
ffaker (2.16.0)
|
||||
ffaker (2.18.0)
|
||||
ffi (1.15.0)
|
||||
figaro (1.2.0)
|
||||
thor (>= 0.14.0, < 2)
|
||||
@@ -269,7 +271,7 @@ GEM
|
||||
tilt
|
||||
hashdiff (1.0.1)
|
||||
highline (2.0.3)
|
||||
i18n (1.8.9)
|
||||
i18n (1.8.10)
|
||||
concurrent-ruby (~> 1.0)
|
||||
i18n-js (3.8.2)
|
||||
i18n (>= 0.6.6)
|
||||
@@ -319,8 +321,8 @@ GEM
|
||||
mime-types (3.3.1)
|
||||
mime-types-data (~> 3.2015)
|
||||
mime-types-data (3.2020.1104)
|
||||
mini_mime (1.0.2)
|
||||
mini_portile2 (2.4.0)
|
||||
mini_mime (1.0.3)
|
||||
mini_portile2 (2.5.0)
|
||||
mini_racer (0.3.1)
|
||||
libv8 (~> 8.4.255)
|
||||
minitest (5.14.4)
|
||||
@@ -335,8 +337,9 @@ GEM
|
||||
mustermann (1.1.1)
|
||||
ruby2_keywords (~> 0.0.1)
|
||||
nio4r (2.5.2)
|
||||
nokogiri (1.10.10)
|
||||
mini_portile2 (~> 2.4.0)
|
||||
nokogiri (1.11.2)
|
||||
mini_portile2 (~> 2.5.0)
|
||||
racc (~> 1.4)
|
||||
oauth2 (1.4.7)
|
||||
faraday (>= 0.8, < 2.0)
|
||||
jwt (>= 1.0, < 3.0)
|
||||
@@ -374,6 +377,7 @@ GEM
|
||||
byebug (~> 11.0)
|
||||
pry (~> 0.13.0)
|
||||
public_suffix (4.0.6)
|
||||
racc (1.5.2)
|
||||
rack (2.2.3)
|
||||
rack-mini-profiler (2.3.1)
|
||||
rack (>= 1.2.0)
|
||||
@@ -428,7 +432,7 @@ GEM
|
||||
rb-inotify (0.10.1)
|
||||
ffi (~> 1.0)
|
||||
redcarpet (3.5.1)
|
||||
regexp_parser (1.8.2)
|
||||
regexp_parser (2.1.1)
|
||||
request_store (1.5.0)
|
||||
rack (>= 1.4)
|
||||
responders (3.0.1)
|
||||
@@ -514,10 +518,12 @@ GEM
|
||||
rubyzip (>= 1.2.2)
|
||||
shoulda-matchers (4.5.1)
|
||||
activesupport (>= 4.2.0)
|
||||
simplecov (0.18.5)
|
||||
simplecov (0.21.2)
|
||||
docile (~> 1.1)
|
||||
simplecov-html (~> 0.11)
|
||||
simplecov_json_formatter (~> 0.1)
|
||||
simplecov-html (0.12.3)
|
||||
simplecov_json_formatter (0.1.2)
|
||||
sinatra (2.1.0)
|
||||
mustermann (~> 1.0)
|
||||
rack (~> 2.2)
|
||||
@@ -543,7 +549,7 @@ GEM
|
||||
stringex (2.8.5)
|
||||
stripe (5.30.0)
|
||||
temple (0.8.2)
|
||||
test-prof (0.11.3)
|
||||
test-prof (1.0.2)
|
||||
test-unit (3.4.0)
|
||||
power_assert
|
||||
thor (0.20.3)
|
||||
@@ -598,7 +604,7 @@ DEPENDENCIES
|
||||
activerecord-postgresql-adapter
|
||||
activerecord-session_store
|
||||
acts-as-taggable-on (~> 7.0)
|
||||
acts_as_list (= 0.9.19)
|
||||
acts_as_list (= 1.0.3)
|
||||
andand
|
||||
angular-rails-templates (>= 0.3.0)
|
||||
angular_rails_csrf
|
||||
@@ -614,6 +620,7 @@ DEPENDENCIES
|
||||
cancancan (~> 1.15.0)
|
||||
capybara
|
||||
catalog!
|
||||
codecov
|
||||
coffee-rails (~> 4.2.2)
|
||||
combine_pdf
|
||||
compass-rails
|
||||
@@ -631,7 +638,7 @@ DEPENDENCIES
|
||||
devise-token_authenticatable
|
||||
dfc_provider!
|
||||
eventmachine (>= 1.2.3)
|
||||
factory_bot_rails (= 5.2.0)
|
||||
factory_bot_rails (= 6.1.0)
|
||||
ffaker
|
||||
figaro
|
||||
fog-aws (>= 0.6.0)
|
||||
@@ -709,7 +716,7 @@ DEPENDENCIES
|
||||
wkhtmltopdf-binary (= 0.12.5)
|
||||
|
||||
RUBY VERSION
|
||||
ruby 2.4.4p296
|
||||
ruby 2.5.8p224
|
||||
|
||||
BUNDLED WITH
|
||||
1.17.3
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[](https://semaphoreci.com/openfoodfoundation/openfoodnetwork-2)
|
||||
[](https://codeclimate.com/github/openfoodfoundation/openfoodnetwork)
|
||||
[](https://github.com/openfoodfoundation/openfoodnetwork/actions/workflows/build.yml)
|
||||
[](https://codecov.io/gh/openfoodfoundation/openfoodnetwork)
|
||||
[](https://codeclimate.com/github/openfoodfoundation/openfoodnetwork)
|
||||
|
||||
# Open Food Network
|
||||
|
||||
|
||||
@@ -147,7 +147,7 @@ angular.module("ofn.admin").controller "AdminProductEditCtrl", ($scope, $timeout
|
||||
if confirm("Are you sure?")
|
||||
$http(
|
||||
method: "DELETE"
|
||||
url: "/api/products/" + product.id
|
||||
url: "/api/v0/products/" + product.id
|
||||
).success (data) ->
|
||||
$scope.products.splice $scope.products.indexOf(product), 1
|
||||
DirtyProducts.deleteProduct product.id
|
||||
@@ -162,7 +162,7 @@ angular.module("ofn.admin").controller "AdminProductEditCtrl", ($scope, $timeout
|
||||
if confirm(t("are_you_sure"))
|
||||
$http(
|
||||
method: "DELETE"
|
||||
url: "/api/products/" + product.permalink_live + "/variants/" + variant.id
|
||||
url: "/api/v0/products/" + product.permalink_live + "/variants/" + variant.id
|
||||
).success (data) ->
|
||||
$scope.removeVariant(product, variant)
|
||||
else
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
angular.module('admin.enterpriseFees').directive 'spreeDeleteResource', ->
|
||||
(scope, element, attrs) ->
|
||||
if scope.enterprise_fee.id
|
||||
url = '/api/enterprise_fees/' + scope.enterprise_fee.id
|
||||
url = '/api/v0/enterprise_fees/' + scope.enterprise_fee.id
|
||||
html = '<a href="' + url + '" class="delete-resource icon_link icon-trash no-text" data-action="remove" data-confirm="' + t('are_you_sure') + '" url="' + url + '"></a>'
|
||||
#var html = '<a href="'+url+'" class="delete-resource" data-confirm="Are you sure?"><img alt="Delete" src="/assets/admin/icons/delete.png" /> Delete</a>';
|
||||
element.append html
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
angular.module("admin.indexUtils").factory "resources", ($resource) ->
|
||||
LineItem = $resource '/api/orders/:order_number/line_items/:line_item_id.json',
|
||||
LineItem = $resource '/api/v0/orders/:order_number/line_items/:line_item_id.json',
|
||||
{ order_number: '@order_number', line_item_id: '@line_item_id'},
|
||||
'update': { method: 'PUT' }
|
||||
Customer = $resource '/admin/customers/:customer_id.json',
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
angular.module('admin.orderCycles').factory('ExchangeProduct', ($resource) ->
|
||||
ExchangeProductResource = $resource('/api/exchanges/:exchange_id/products.json', {}, {
|
||||
ExchangeProductResource = $resource('/api/v0/exchanges/:exchange_id/products.json', {}, {
|
||||
'index': { method: 'GET' }
|
||||
'variant_count': { method: 'GET', params: { action_name: "variant_count" }}
|
||||
})
|
||||
|
||||
@@ -8,7 +8,7 @@ angular.module("ofn.admin").factory "ProductImageService", (FileUploader, SpreeA
|
||||
autoUpload: true
|
||||
|
||||
configure: (product) =>
|
||||
@imageUploader.url = "/api/product_images/#{product.id}"
|
||||
@imageUploader.url = "/api/v0/product_images/#{product.id}"
|
||||
@imagePreview = product.image_url
|
||||
@imageUploader.onSuccessItem = (image, response) =>
|
||||
product.thumb_url = response.thumb_url
|
||||
|
||||
@@ -9,12 +9,12 @@ angular.module("admin.resources").factory 'EnterpriseResource', ($resource) ->
|
||||
'update':
|
||||
method: 'PUT'
|
||||
'removeLogo':
|
||||
url: '/api/enterprises/:id/logo.json'
|
||||
url: '/api/v0/enterprises/:id/logo.json'
|
||||
method: 'DELETE'
|
||||
'removePromoImage':
|
||||
url: '/api/enterprises/:id/promo_image.json'
|
||||
url: '/api/v0/enterprises/:id/promo_image.json'
|
||||
method: 'DELETE'
|
||||
'removeTermsAndConditions':
|
||||
url: '/api/enterprises/:id/terms_and_conditions.json'
|
||||
url: '/api/v0/enterprises/:id/terms_and_conditions.json'
|
||||
method: 'DELETE'
|
||||
})
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
angular.module("admin.resources").factory 'OrderResource', ($resource) ->
|
||||
$resource('/admin/orders/:id/:action.json', {}, {
|
||||
'index':
|
||||
url: '/api/orders.json'
|
||||
url: '/api/v0/orders.json'
|
||||
method: 'GET'
|
||||
'update':
|
||||
method: 'PUT'
|
||||
'capture':
|
||||
url: '/api/orders/:id/capture.json'
|
||||
url: '/api/v0/orders/:id/capture.json'
|
||||
method: 'PUT'
|
||||
params:
|
||||
id: '@id'
|
||||
'ship':
|
||||
url: '/api/orders/:id/ship.json'
|
||||
url: '/api/v0/orders/:id/ship.json'
|
||||
method: 'PUT'
|
||||
params:
|
||||
id: '@id'
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
angular.module("admin.resources").factory 'ProductResource', ($resource) ->
|
||||
$resource('/admin/product/:id/:action.json', {}, {
|
||||
'index':
|
||||
url: '/api/products/bulk_products.json'
|
||||
url: '/api/v0/products/bulk_products.json'
|
||||
method: 'GET'
|
||||
})
|
||||
|
||||
@@ -10,8 +10,8 @@ angular.module("ofn.admin").factory "BulkProducts", (ProductResource, dataFetche
|
||||
angular.extend(@pagination, data.pagination)
|
||||
|
||||
cloneProduct: (product) ->
|
||||
$http.post("/api/products/" + product.id + "/clone").success (data) =>
|
||||
dataFetcher("/api/products/" + data.id + "?template=bulk_show").then (newProduct) =>
|
||||
$http.post("/api/v0/products/" + product.id + "/clone").success (data) =>
|
||||
dataFetcher("/api/v0/products/" + data.id + "?template=bulk_show").then (newProduct) =>
|
||||
@unpackProduct newProduct
|
||||
@insertProductAfter(product, newProduct)
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
angular.module("admin.utils").factory "StatusMessage", ($timeout) ->
|
||||
angular.module("admin.utils").factory "StatusMessage", ->
|
||||
new class StatusMessage
|
||||
types:
|
||||
progress: {timeout: false, style: {color: '#ff9906'}}
|
||||
alert: {timeout: 5000, style: {color: 'grey'}}
|
||||
notice: {timeout: false, style: {color: 'grey'}}
|
||||
success: {timeout: 5000, style: {color: '#9fc820'}}
|
||||
failure: {timeout: false, style: {color: '#da5354'}}
|
||||
progress: {style: {color: '#ff9906'}}
|
||||
alert: {style: {color: 'grey'}}
|
||||
notice: {style: {color: 'grey'}}
|
||||
success: {style: {color: '#9fc820'}}
|
||||
failure: {style: {color: '#da5354'}}
|
||||
|
||||
statusMessage:
|
||||
text: ""
|
||||
@@ -25,13 +25,7 @@ angular.module("admin.utils").factory "StatusMessage", ($timeout) ->
|
||||
display: (type, text) ->
|
||||
@statusMessage.text = text
|
||||
@statusMessage.style = @types[type].style
|
||||
$timeout.cancel @statusMessage.timeout if @statusMessage.timeout
|
||||
timeout = @types[type].timeout
|
||||
if timeout
|
||||
@statusMessage.timeout = $timeout =>
|
||||
@clear()
|
||||
, timeout, true
|
||||
null # So we don't return weird timeouts
|
||||
null
|
||||
|
||||
clear: ->
|
||||
@statusMessage.text = ''
|
||||
|
||||
@@ -42,7 +42,7 @@ angular.module("admin.variantOverrides").controller "AdminVariantOverridesCtrl",
|
||||
$scope.fetchProducts()
|
||||
|
||||
$scope.fetchProducts = ->
|
||||
url = "/api/products/overridable?page=::page::;per_page=100"
|
||||
url = "/api/v0/products/overridable?page=::page::;per_page=100"
|
||||
PagedFetcher.fetch url, $scope.addProducts
|
||||
|
||||
$scope.addProducts = (data) ->
|
||||
|
||||
@@ -24,7 +24,7 @@ Darkswarm.controller "HubNodeCtrl", ($scope, HashNavigation, CurrentHub, $http,
|
||||
$scope.shopfront_loading = true
|
||||
$scope.toggle_tab(event)
|
||||
|
||||
$http.get("/api/shops/" + $scope.hub.id)
|
||||
$http.get("/api/v0/shops/" + $scope.hub.id)
|
||||
.success (data) ->
|
||||
$scope.shopfront_loading = false
|
||||
$scope.hub = data
|
||||
|
||||
@@ -24,7 +24,7 @@ Darkswarm.controller "ProducerNodeCtrl", ($scope, HashNavigation, $anchorScroll,
|
||||
$scope.shopfront_loading = true
|
||||
$scope.toggle_tab(event)
|
||||
|
||||
$http.get("/api/shops/" + $scope.producer.id)
|
||||
$http.get("/api/v0/shops/" + $scope.producer.id)
|
||||
.success (data) ->
|
||||
$scope.shopfront_loading = false
|
||||
$scope.producer = data
|
||||
|
||||
@@ -3,7 +3,15 @@ Darkswarm.directive "bodyScroll", ($rootScope, BodyScroll) ->
|
||||
scope: true
|
||||
link: (scope, elem, attrs) ->
|
||||
$rootScope.$on "toggleBodyScroll", ->
|
||||
if BodyScroll.disabled
|
||||
elem.addClass "disable-scroll"
|
||||
if BodyScroll.disabled && document.body.scrollHeight > document.body.clientHeight
|
||||
document.body.style.top = "-#{window.scrollY}px"
|
||||
document.body.style.position = 'fixed'
|
||||
document.body.style.overflowY = 'scroll'
|
||||
document.body.style.width = '100%'
|
||||
else
|
||||
elem.removeClass "disable-scroll"
|
||||
scrollY = parseInt(document.body.style.top) * -1
|
||||
document.body.style.position = ''
|
||||
document.body.style.top = ''
|
||||
document.body.style.overflowY = ''
|
||||
document.body.style.width = ''
|
||||
window.scrollTo(0, scrollY) if scrollY
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
angular.module("Darkswarm").factory 'Customer', ($resource, $injector, Messages) ->
|
||||
Customer = $resource('/api/customers/:id/:action.json', {}, {
|
||||
Customer = $resource('/api/v0/customers/:id/:action.json', {}, {
|
||||
'index':
|
||||
method: 'GET'
|
||||
isArray: true
|
||||
|
||||
@@ -8,5 +8,5 @@ Darkswarm.factory "EnterpriseImageService", (FileUploader, spreeApiKey) ->
|
||||
autoUpload: true
|
||||
|
||||
configure: (enterprise) =>
|
||||
@imageUploader.url = "/api/enterprises/#{enterprise.id}/update_image"
|
||||
@imageUploader.url = "/api/v0/enterprises/#{enterprise.id}/update_image"
|
||||
@imageUploader.onSuccessItem = (image, response) => @imageSrc = response
|
||||
|
||||
@@ -5,7 +5,7 @@ Darkswarm.factory "EnterpriseModal", ($modal, $rootScope, $http)->
|
||||
scope = $rootScope.$new(true) # Spawn an isolate to contain the enterprise
|
||||
scope.embedded_layout = window.location.search.indexOf("embedded_shopfront=true") != -1
|
||||
|
||||
$http.get("/api/shops/" + enterprise.id).success (data) ->
|
||||
$http.get("/api/v0/shops/" + enterprise.id).success (data) ->
|
||||
scope.enterprise = data
|
||||
$modal.open(templateUrl: "enterprise_modal.html", scope: scope)
|
||||
.error (data) ->
|
||||
|
||||
@@ -18,7 +18,7 @@ Darkswarm.factory "EnterpriseRegistrationService", ($http, RegistrationService,
|
||||
Loading.message = t('creating') + " " + @enterprise.name
|
||||
$http(
|
||||
method: "POST"
|
||||
url: "/api/enterprises"
|
||||
url: "/api/v0/enterprises"
|
||||
data:
|
||||
enterprise: @prepare()
|
||||
params:
|
||||
@@ -42,7 +42,7 @@ Darkswarm.factory "EnterpriseRegistrationService", ($http, RegistrationService,
|
||||
Loading.message = t('updating') + " " + @enterprise.name
|
||||
$http(
|
||||
method: "PUT"
|
||||
url: "/api/enterprises/#{@enterprise.id}"
|
||||
url: "/api/v0/enterprises/#{@enterprise.id}"
|
||||
data:
|
||||
enterprise: @prepare()
|
||||
params:
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
Darkswarm.factory 'OrderCycleResource', ($resource) ->
|
||||
$resource('/api/order_cycles/:id.json', {}, {
|
||||
$resource('/api/v0/order_cycles/:id.json', {}, {
|
||||
'products':
|
||||
method: 'GET'
|
||||
isArray: true
|
||||
url: '/api/order_cycles/:id/products.json'
|
||||
url: '/api/v0/order_cycles/:id/products.json'
|
||||
params:
|
||||
id: '@id'
|
||||
'taxons':
|
||||
method: 'GET'
|
||||
isArray: true
|
||||
url: '/api/order_cycles/:id/taxons.json'
|
||||
url: '/api/v0/order_cycles/:id/taxons.json'
|
||||
params:
|
||||
id: '@id'
|
||||
'properties':
|
||||
method: 'GET'
|
||||
isArray: true
|
||||
url: '/api/order_cycles/:id/properties.json'
|
||||
url: '/api/v0/order_cycles/:id/properties.json'
|
||||
params:
|
||||
id: '@id'
|
||||
})
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
Darkswarm.factory 'ShopsResource', ($resource) ->
|
||||
$resource('/api/shops/:id.json', {}, {
|
||||
$resource('/api/v0/shops/:id.json', {}, {
|
||||
'closed_shops':
|
||||
method: 'GET'
|
||||
isArray: true
|
||||
url: '/api/shops/closed_shops.json'
|
||||
url: '/api/v0/shops/closed_shops.json'
|
||||
})
|
||||
|
||||
@@ -4,7 +4,7 @@ OFNShared.directive "questionMarkWithTooltip", ($tooltip)->
|
||||
# Subsequently we patch the scope, template and restrictions
|
||||
tooltip = $tooltip 'questionMarkWithTooltip', 'questionMarkWithTooltip', 'click'
|
||||
tooltip.scope =
|
||||
variant: "="
|
||||
context: "="
|
||||
key: "="
|
||||
tooltip.templateUrl = "shared/question_mark_with_tooltip_icon.html"
|
||||
tooltip.replace = true
|
||||
|
||||
@@ -165,7 +165,3 @@ a.button.large {
|
||||
.flex {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.disable-scroll {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
@@ -36,6 +36,9 @@
|
||||
@include icon-font;
|
||||
content: "";
|
||||
color: $white;
|
||||
vertical-align: super;
|
||||
position: relative;
|
||||
top: 2px;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -45,6 +48,7 @@
|
||||
width: 15px;
|
||||
min-width: 15px;
|
||||
height: 15px;
|
||||
margin-left: 2px;
|
||||
}
|
||||
|
||||
.joyride-tip-guide.question-mark-tooltip {
|
||||
|
||||
@@ -53,15 +53,12 @@ module Admin
|
||||
|
||||
# copy of Admin::ResourceController without flash notice
|
||||
def destroy
|
||||
invoke_callbacks(:destroy, :before)
|
||||
if @object.destroy
|
||||
invoke_callbacks(:destroy, :after)
|
||||
respond_with(@object) do |format|
|
||||
format.html { redirect_to location_after_destroy }
|
||||
format.js { render partial: "spree/admin/shared/destroy" }
|
||||
end
|
||||
else
|
||||
invoke_callbacks(:destroy, :fails)
|
||||
respond_with(@object) do |format|
|
||||
format.html { redirect_to location_after_destroy }
|
||||
format.json { render json: { errors: @object.errors.full_messages }, status: :conflict }
|
||||
|
||||
@@ -43,12 +43,11 @@ module Admin
|
||||
end
|
||||
|
||||
def update
|
||||
invoke_callbacks(:update, :before)
|
||||
tag_rules_attributes = params[object_name].delete :tag_rules_attributes
|
||||
update_tag_rules(tag_rules_attributes) if tag_rules_attributes.present?
|
||||
update_enterprise_notifications
|
||||
|
||||
if @object.update(enterprise_params)
|
||||
invoke_callbacks(:update, :after)
|
||||
flash[:success] = flash_message_for(@object, :successfully_updated)
|
||||
respond_with(@object) do |format|
|
||||
format.html { redirect_to location_after_save }
|
||||
@@ -56,7 +55,6 @@ module Admin
|
||||
format.json { render_as_json @object, ams_prefix: 'index', spree_current_user: spree_current_user }
|
||||
end
|
||||
else
|
||||
invoke_callbacks(:update, :fails)
|
||||
respond_with(@object) do |format|
|
||||
format.json { render json: { errors: @object.errors.messages }, status: :unprocessable_entity }
|
||||
end
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
require 'action_callbacks'
|
||||
|
||||
module Admin
|
||||
class ResourceController < Spree::Admin::BaseController
|
||||
helper_method :new_object_url, :edit_object_url, :object_url, :collection_url
|
||||
@@ -11,7 +9,6 @@ module Admin
|
||||
respond_to :js, except: [:show, :index]
|
||||
|
||||
def new
|
||||
invoke_callbacks(:new_action, :before)
|
||||
respond_with(@object) do |format|
|
||||
format.html { render layout: !request.xhr? }
|
||||
format.js { render layout: false }
|
||||
@@ -26,32 +23,26 @@ module Admin
|
||||
end
|
||||
|
||||
def update
|
||||
invoke_callbacks(:update, :before)
|
||||
if @object.update(permitted_resource_params)
|
||||
invoke_callbacks(:update, :after)
|
||||
flash[:success] = flash_message_for(@object, :successfully_updated)
|
||||
respond_with(@object) do |format|
|
||||
format.html { redirect_to location_after_save }
|
||||
format.js { render layout: false }
|
||||
end
|
||||
else
|
||||
invoke_callbacks(:update, :fails)
|
||||
respond_with(@object)
|
||||
end
|
||||
end
|
||||
|
||||
def create
|
||||
invoke_callbacks(:create, :before)
|
||||
@object.attributes = permitted_resource_params
|
||||
if @object.save
|
||||
invoke_callbacks(:create, :after)
|
||||
flash[:success] = flash_message_for(@object, :successfully_created)
|
||||
respond_with(@object) do |format|
|
||||
format.html { redirect_to location_after_save }
|
||||
format.js { render layout: false }
|
||||
end
|
||||
else
|
||||
invoke_callbacks(:create, :fails)
|
||||
respond_with(@object)
|
||||
end
|
||||
end
|
||||
@@ -67,16 +58,13 @@ module Admin
|
||||
end
|
||||
|
||||
def destroy
|
||||
invoke_callbacks(:destroy, :before)
|
||||
if @object.destroy
|
||||
invoke_callbacks(:destroy, :after)
|
||||
flash[:success] = flash_message_for(@object, :successfully_removed)
|
||||
respond_with(@object) do |format|
|
||||
format.html { redirect_to collection_url }
|
||||
format.js { render partial: "spree/admin/shared/destroy" }
|
||||
end
|
||||
else
|
||||
invoke_callbacks(:destroy, :fails)
|
||||
respond_with(@object) do |format|
|
||||
format.html { redirect_to collection_url }
|
||||
end
|
||||
@@ -92,7 +80,6 @@ module Admin
|
||||
|
||||
class << self
|
||||
attr_accessor :parent_data
|
||||
attr_accessor :callbacks
|
||||
|
||||
def belongs_to(model_name, options = {})
|
||||
@parent_data ||= {}
|
||||
@@ -100,26 +87,6 @@ module Admin
|
||||
@parent_data[:model_class] = model_name.to_s.classify.constantize
|
||||
@parent_data[:find_by] = options[:find_by] || :id
|
||||
end
|
||||
|
||||
def new_action
|
||||
@callbacks ||= {}
|
||||
@callbacks[:new_action] ||= ActionCallbacks.new
|
||||
end
|
||||
|
||||
def create
|
||||
@callbacks ||= {}
|
||||
@callbacks[:create] ||= ActionCallbacks.new
|
||||
end
|
||||
|
||||
def update
|
||||
@callbacks ||= {}
|
||||
@callbacks[:update] ||= ActionCallbacks.new
|
||||
end
|
||||
|
||||
def destroy
|
||||
@callbacks ||= {}
|
||||
@callbacks[:destroy] ||= ActionCallbacks.new
|
||||
end
|
||||
end
|
||||
|
||||
def model_class
|
||||
@@ -212,17 +179,6 @@ module Admin
|
||||
collection_url
|
||||
end
|
||||
|
||||
def invoke_callbacks(action, callback_type)
|
||||
callbacks = self.class.callbacks || {}
|
||||
return if callbacks[action].nil?
|
||||
|
||||
case callback_type.to_sym
|
||||
when :before then callbacks[action].before_methods.each { |method| __send__ method }
|
||||
when :after then callbacks[action].after_methods.each { |method| __send__ method }
|
||||
when :fails then callbacks[action].fails_methods.each { |method| __send__ method }
|
||||
end
|
||||
end
|
||||
|
||||
# URL helpers
|
||||
def new_object_url(options = {})
|
||||
if parent_data.present?
|
||||
|
||||
@@ -9,7 +9,8 @@ module Admin
|
||||
before_action :editable_order_cycle_ids_for_create, only: [:create]
|
||||
before_action :editable_order_cycle_ids_for_update, only: [:update]
|
||||
before_action :check_dependent_subscriptions, only: [:destroy]
|
||||
update.after :sync_subscriptions_for_update
|
||||
|
||||
after_action :sync_subscriptions_for_update, only: :update
|
||||
|
||||
respond_to :json
|
||||
|
||||
@@ -120,7 +121,7 @@ module Admin
|
||||
end
|
||||
|
||||
def sync_subscriptions_for_update
|
||||
return unless params[:schedule][:order_cycle_ids]
|
||||
return unless params[:schedule][:order_cycle_ids] && @object.errors.blank?
|
||||
|
||||
sync_subscriptions
|
||||
end
|
||||
|
||||
@@ -1,103 +0,0 @@
|
||||
# Base controller for OFN's API
|
||||
require_dependency 'spree/api/controller_setup'
|
||||
require "spree/core/controller_helpers/ssl"
|
||||
|
||||
module Api
|
||||
class BaseController < ActionController::Metal
|
||||
include RawParams
|
||||
include ActionController::StrongParameters
|
||||
include ActionController::RespondWith
|
||||
include Spree::Api::ControllerSetup
|
||||
include Spree::Core::ControllerHelpers::SSL
|
||||
include ::ActionController::Head
|
||||
include ::ActionController::ConditionalGet
|
||||
include ActionView::Layouts
|
||||
|
||||
layout false
|
||||
|
||||
attr_accessor :current_api_user
|
||||
|
||||
before_action :set_content_type
|
||||
before_action :authenticate_user
|
||||
|
||||
rescue_from Exception, with: :error_during_processing
|
||||
rescue_from CanCan::AccessDenied, with: :unauthorized
|
||||
rescue_from ActiveRecord::RecordNotFound, with: :not_found
|
||||
|
||||
helper Spree::Api::ApiHelpers
|
||||
|
||||
ssl_allowed
|
||||
|
||||
# Include these because we inherit from ActionController::Metal
|
||||
# rather than ActionController::Base and these are required for AMS
|
||||
include ActionController::Serialization
|
||||
include ActionController::UrlFor
|
||||
include Rails.application.routes.url_helpers
|
||||
|
||||
use_renderers :json
|
||||
check_authorization
|
||||
|
||||
def respond_with_conflict(json_hash)
|
||||
render json: json_hash, status: :conflict
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Use logged in user (spree_current_user) for API authentication (current_api_user)
|
||||
def authenticate_user
|
||||
return if @current_api_user = spree_current_user
|
||||
|
||||
if api_key.blank?
|
||||
# An anonymous user
|
||||
@current_api_user = Spree.user_class.new
|
||||
return
|
||||
end
|
||||
|
||||
return if @current_api_user = Spree.user_class.find_by(spree_api_key: api_key.to_s)
|
||||
|
||||
invalid_api_key
|
||||
end
|
||||
|
||||
def set_content_type
|
||||
headers["Content-Type"] = "application/json"
|
||||
end
|
||||
|
||||
def error_during_processing(exception)
|
||||
Bugsnag.notify(exception)
|
||||
|
||||
render(json: { exception: exception.message },
|
||||
status: :unprocessable_entity) && return
|
||||
end
|
||||
|
||||
def current_ability
|
||||
Spree::Ability.new(current_api_user)
|
||||
end
|
||||
|
||||
def api_key
|
||||
request.headers["X-Spree-Token"] || params[:token]
|
||||
end
|
||||
helper_method :api_key
|
||||
|
||||
def invalid_resource!(resource)
|
||||
@resource = resource
|
||||
render(json: { error: I18n.t(:invalid_resource, scope: "spree.api"),
|
||||
errors: @resource.errors },
|
||||
status: :unprocessable_entity)
|
||||
end
|
||||
|
||||
def invalid_api_key
|
||||
render(json: { error: I18n.t(:invalid_api_key, key: api_key, scope: "spree.api") },
|
||||
status: :unauthorized) && return
|
||||
end
|
||||
|
||||
def unauthorized
|
||||
render(json: { error: I18n.t(:unauthorized, scope: "spree.api") },
|
||||
status: :unauthorized) && return
|
||||
end
|
||||
|
||||
def not_found
|
||||
render(json: { error: I18n.t(:resource_not_found, scope: "spree.api") },
|
||||
status: :not_found) && return
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,37 +0,0 @@
|
||||
module Api
|
||||
class CustomersController < Api::BaseController
|
||||
skip_authorization_check only: :index
|
||||
|
||||
def index
|
||||
@customers = current_api_user.customers
|
||||
render json: @customers, each_serializer: CustomerSerializer
|
||||
end
|
||||
|
||||
def update
|
||||
@customer = Customer.find(params[:id])
|
||||
authorize! :update, @customer
|
||||
|
||||
client_secret = RecurringPayments.setup_for(@customer) if params[:customer][:allow_charges]
|
||||
|
||||
if @customer.update(customer_params)
|
||||
add_recurring_payment_info(client_secret)
|
||||
render json: @customer, serializer: CustomerSerializer, status: :ok
|
||||
else
|
||||
invalid_resource!(@customer)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def add_recurring_payment_info(client_secret)
|
||||
return unless client_secret
|
||||
|
||||
@customer.gateway_recurring_payment_client_secret = client_secret
|
||||
@customer.gateway_shop_id = @customer.enterprise.stripe_account&.stripe_user_id
|
||||
end
|
||||
|
||||
def customer_params
|
||||
params.require(:customer).permit(:code, :email, :enterprise_id, :allow_charges)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,42 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'api/admin/enterprise_serializer'
|
||||
|
||||
module Api
|
||||
class EnterpriseAttachmentController < Api::BaseController
|
||||
class MissingImplementationError < StandardError; end
|
||||
class UnknownEnterpriseAuthorizationActionError < StandardError; end
|
||||
|
||||
before_action :load_enterprise
|
||||
|
||||
respond_to :json
|
||||
|
||||
def destroy
|
||||
return respond_with_conflict(error: destroy_attachment_does_not_exist_error_message) unless @enterprise.public_send("#{attachment_name}?")
|
||||
|
||||
@enterprise.update!(attachment_name => nil)
|
||||
render json: @enterprise, serializer: Admin::EnterpriseSerializer, spree_current_user: spree_current_user
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def attachment_name
|
||||
raise MissingImplementationError, "Method attachment_name should be defined"
|
||||
end
|
||||
|
||||
def enterprise_authorize_action
|
||||
raise MissingImplementationError, "Method enterprise_authorize_action should be defined"
|
||||
end
|
||||
|
||||
def load_enterprise
|
||||
@enterprise = Enterprise.find_by(permalink: params[:enterprise_id].to_s)
|
||||
raise UnknownEnterpriseAuthorizationActionError if enterprise_authorize_action.blank?
|
||||
|
||||
authorize!(enterprise_authorize_action, @enterprise)
|
||||
end
|
||||
|
||||
def destroy_attachment_does_not_exist_error_message
|
||||
I18n.t("api.enterprise_#{attachment_name}.destroy_attachment_does_not_exist")
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,21 +0,0 @@
|
||||
module Api
|
||||
class EnterpriseFeesController < Api::BaseController
|
||||
respond_to :json
|
||||
|
||||
def destroy
|
||||
authorize! :destroy, enterprise_fee
|
||||
|
||||
if enterprise_fee.destroy
|
||||
render plain: I18n.t(:successfully_removed), status: :no_content
|
||||
else
|
||||
render plain: enterprise_fee.errors.full_messages.first, status: :forbidden
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def enterprise_fee
|
||||
@enterprise_fee ||= EnterpriseFee.find_by id: params[:id]
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,78 +0,0 @@
|
||||
module Api
|
||||
class EnterprisesController < Api::BaseController
|
||||
before_action :override_owner, only: [:create, :update]
|
||||
before_action :check_type, only: :update
|
||||
before_action :override_sells, only: [:create, :update]
|
||||
before_action :override_visible, only: [:create, :update]
|
||||
respond_to :json
|
||||
|
||||
def create
|
||||
authorize! :create, Enterprise
|
||||
|
||||
# params[:user_ids] breaks the enterprise creation
|
||||
# We remove them from params and save them after creating the enterprise
|
||||
user_ids = enterprise_params.delete(:user_ids)
|
||||
@enterprise = Enterprise.new(enterprise_params)
|
||||
if @enterprise.save
|
||||
@enterprise.user_ids = user_ids
|
||||
render json: @enterprise.id, status: :created
|
||||
else
|
||||
invalid_resource!(@enterprise)
|
||||
end
|
||||
end
|
||||
|
||||
def update
|
||||
@enterprise = Enterprise.find_by(permalink: params[:id]) || Enterprise.find(params[:id])
|
||||
authorize! :update, @enterprise
|
||||
|
||||
if @enterprise.update(enterprise_params)
|
||||
render json: @enterprise.id, status: :ok
|
||||
else
|
||||
invalid_resource!(@enterprise)
|
||||
end
|
||||
end
|
||||
|
||||
def update_image
|
||||
@enterprise = Enterprise.find_by(permalink: params[:id]) || Enterprise.find(params[:id])
|
||||
authorize! :update, @enterprise
|
||||
|
||||
if params[:logo] && @enterprise.update( logo: params[:logo] )
|
||||
render plain: @enterprise.logo.url(:medium), status: :ok
|
||||
elsif params[:promo] && @enterprise.update( promo_image: params[:promo] )
|
||||
render plain: @enterprise.promo_image.url(:medium), status: :ok
|
||||
else
|
||||
invalid_resource!(@enterprise)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def override_owner
|
||||
enterprise_params[:owner_id] = current_api_user.id
|
||||
end
|
||||
|
||||
def check_type
|
||||
enterprise_params.delete :type unless current_api_user.admin?
|
||||
end
|
||||
|
||||
def override_sells
|
||||
has_hub = current_api_user.owned_enterprises.is_hub.any?
|
||||
new_enterprise_is_producer = !!enterprise_params[:is_primary_producer]
|
||||
|
||||
enterprise_params[:sells] = if has_hub && !new_enterprise_is_producer
|
||||
'any'
|
||||
else
|
||||
'unspecified'
|
||||
end
|
||||
end
|
||||
|
||||
def override_visible
|
||||
enterprise_params[:visible] = false
|
||||
end
|
||||
|
||||
def enterprise_params
|
||||
@enterprise_params ||= PermittedAttributes::Enterprise.new(params).call.
|
||||
to_h.with_indifferent_access
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,100 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
# This controller lists products that can be added to an exchange
|
||||
#
|
||||
# Pagination is optional and can be required by using param[:page]
|
||||
module Api
|
||||
class ExchangeProductsController < Api::BaseController
|
||||
include PaginationData
|
||||
DEFAULT_PER_PAGE = 100
|
||||
|
||||
skip_authorization_check only: [:index]
|
||||
|
||||
# If exchange_id is present in the URL:
|
||||
# Lists Products that can be added to that Exchange
|
||||
#
|
||||
# If exchange_id is not present in the URL:
|
||||
# Lists Products of the Enterprise given that can be added to the given Order Cycle
|
||||
# In this case parameters are: enterprise_id, order_cycle_id and incoming
|
||||
# (order_cycle_id is not necessary for incoming exchanges)
|
||||
def index
|
||||
if exchange_params[:exchange_id].present?
|
||||
load_data_from_exchange
|
||||
else
|
||||
load_data_from_other_params
|
||||
end
|
||||
|
||||
render_variant_count && return if params[:action_name] == "variant_count"
|
||||
|
||||
render_paginated_products paginated_products
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def render_variant_count
|
||||
render plain: {
|
||||
count: variants.count
|
||||
}.to_json
|
||||
end
|
||||
|
||||
def variants
|
||||
renderer.exchange_variants(@incoming, @enterprise)
|
||||
end
|
||||
|
||||
def products
|
||||
renderer.exchange_products(@incoming, @enterprise)
|
||||
end
|
||||
|
||||
def renderer
|
||||
@renderer ||= ExchangeProductsRenderer.
|
||||
new(@order_cycle, spree_current_user)
|
||||
end
|
||||
|
||||
def paginated_products
|
||||
return products unless pagination_required?
|
||||
|
||||
products.
|
||||
page(params[:page]).
|
||||
per(params[:per_page] || DEFAULT_PER_PAGE)
|
||||
end
|
||||
|
||||
def load_data_from_exchange
|
||||
exchange = Exchange.find_by(id: exchange_params[:exchange_id])
|
||||
|
||||
@order_cycle = exchange.order_cycle
|
||||
@incoming = exchange.incoming
|
||||
@enterprise = exchange.sender
|
||||
end
|
||||
|
||||
def load_data_from_other_params
|
||||
@enterprise = Enterprise.find_by(id: exchange_params[:enterprise_id])
|
||||
|
||||
# This will be a string (eg "true") when it arrives via params, but we want a boolean
|
||||
@incoming = ActiveModel::Type::Boolean.new.cast exchange_params[:incoming]
|
||||
|
||||
if exchange_params[:order_cycle_id]
|
||||
@order_cycle = OrderCycle.find_by(id: exchange_params[:order_cycle_id])
|
||||
elsif !@incoming
|
||||
raise "order_cycle_id is required to list products for new outgoing exchange"
|
||||
end
|
||||
end
|
||||
|
||||
def render_paginated_products(paginated_products)
|
||||
serialized_products = ActiveModel::ArraySerializer.new(
|
||||
paginated_products,
|
||||
each_serializer: Api::Admin::ForOrderCycle::SuppliedProductSerializer,
|
||||
order_cycle: @order_cycle
|
||||
)
|
||||
|
||||
render json: {
|
||||
products: serialized_products,
|
||||
pagination: pagination_data(paginated_products)
|
||||
}
|
||||
end
|
||||
|
||||
def exchange_params
|
||||
params.permit(:enterprise_id, :exchange_id, :order_cycle_id, :incoming).
|
||||
to_h.with_indifferent_access
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,16 +0,0 @@
|
||||
module Api
|
||||
class LogosController < Api::EnterpriseAttachmentController
|
||||
private
|
||||
|
||||
def attachment_name
|
||||
:logo
|
||||
end
|
||||
|
||||
def enterprise_authorize_action
|
||||
case action_name.to_sym
|
||||
when :destroy
|
||||
:remove_logo
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,101 +0,0 @@
|
||||
module Api
|
||||
class OrderCyclesController < Api::BaseController
|
||||
include EnterprisesHelper
|
||||
include ApiActionCaching
|
||||
|
||||
skip_authorization_check
|
||||
skip_before_action :authenticate_user, :ensure_api_key, only: [:taxons, :properties]
|
||||
|
||||
caches_action :taxons, :properties,
|
||||
expires_in: CacheService::FILTERS_EXPIRY,
|
||||
cache_path: proc { |controller| controller.request.url }
|
||||
|
||||
def products
|
||||
return render_no_products unless order_cycle.open?
|
||||
|
||||
products = ProductsRenderer.new(
|
||||
distributor,
|
||||
order_cycle,
|
||||
customer,
|
||||
search_params
|
||||
).products_json
|
||||
|
||||
render plain: products
|
||||
rescue ProductsRenderer::NoProducts
|
||||
render_no_products
|
||||
end
|
||||
|
||||
def taxons
|
||||
taxons = Spree::Taxon.
|
||||
joins(:products).
|
||||
where(spree_products: { id: distributed_products }).
|
||||
select('DISTINCT spree_taxons.*')
|
||||
|
||||
render plain: ActiveModel::ArraySerializer.new(
|
||||
taxons, each_serializer: Api::TaxonSerializer
|
||||
).to_json
|
||||
end
|
||||
|
||||
def properties
|
||||
render plain: ActiveModel::ArraySerializer.new(
|
||||
product_properties | producer_properties, each_serializer: Api::PropertySerializer
|
||||
).to_json
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def render_no_products
|
||||
render status: :not_found, json: {}
|
||||
end
|
||||
|
||||
def product_properties
|
||||
Spree::Property.
|
||||
joins(:products).
|
||||
where(spree_products: { id: distributed_products }).
|
||||
select('DISTINCT spree_properties.*')
|
||||
end
|
||||
|
||||
def producer_properties
|
||||
producers = Enterprise.
|
||||
joins(:supplied_products).
|
||||
where(spree_products: { id: distributed_products })
|
||||
|
||||
Spree::Property.
|
||||
joins(:producer_properties).
|
||||
where(producer_properties: { producer_id: producers }).
|
||||
select('DISTINCT spree_properties.*')
|
||||
end
|
||||
|
||||
def search_params
|
||||
permitted_search_params = params.slice :q, :page, :per_page
|
||||
|
||||
if permitted_search_params.key? :q
|
||||
permitted_search_params[:q].slice!(*permitted_ransack_params)
|
||||
end
|
||||
|
||||
permitted_search_params
|
||||
end
|
||||
|
||||
def permitted_ransack_params
|
||||
[:name_or_meta_keywords_or_variants_display_as_or_variants_display_name_or_supplier_name_cont,
|
||||
:properties_id_or_supplier_properties_id_in_any,
|
||||
:primary_taxon_id_in_any]
|
||||
end
|
||||
|
||||
def distributor
|
||||
@distributor ||= Enterprise.find_by(id: params[:distributor])
|
||||
end
|
||||
|
||||
def order_cycle
|
||||
@order_cycle ||= OrderCycle.find_by(id: params[:id])
|
||||
end
|
||||
|
||||
def customer
|
||||
@current_api_user.andand.customer_of(distributor) || nil
|
||||
end
|
||||
|
||||
def distributed_products
|
||||
OrderCycleDistributedProducts.new(distributor, order_cycle, customer).products_relation
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,67 +0,0 @@
|
||||
module Api
|
||||
class OrdersController < Api::BaseController
|
||||
include PaginationData
|
||||
|
||||
def show
|
||||
authorize! :read, order
|
||||
render json: order, serializer: Api::OrderDetailedSerializer, current_order: order
|
||||
end
|
||||
|
||||
def index
|
||||
authorize! :admin, Spree::Order
|
||||
|
||||
orders = SearchOrders.new(params, current_api_user).orders
|
||||
|
||||
render json: {
|
||||
orders: serialized_orders(orders),
|
||||
pagination: pagination_data(orders)
|
||||
}
|
||||
end
|
||||
|
||||
def ship
|
||||
authorize! :admin, order
|
||||
|
||||
if order.ship
|
||||
render json: order.reload, serializer: Api::Admin::OrderSerializer, status: :ok
|
||||
else
|
||||
render json: { error: I18n.t('api.orders.failed_to_update') }, status: :unprocessable_entity
|
||||
end
|
||||
end
|
||||
|
||||
def capture
|
||||
authorize! :admin, order
|
||||
|
||||
pending_payment = order.pending_payments.first
|
||||
|
||||
return payment_capture_failed unless order.payment_required? && pending_payment
|
||||
|
||||
if pending_payment.capture!
|
||||
render json: order.reload, serializer: Api::Admin::OrderSerializer, status: :ok
|
||||
else
|
||||
payment_capture_failed
|
||||
end
|
||||
rescue Spree::Core::GatewayError => e
|
||||
error_during_processing(e)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def payment_capture_failed
|
||||
render json: { error: I18n.t(:payment_processing_failed) }, status: :unprocessable_entity
|
||||
end
|
||||
|
||||
def serialized_orders(orders)
|
||||
ActiveModel::ArraySerializer.new(
|
||||
orders,
|
||||
each_serializer: Api::Admin::OrderSerializer
|
||||
)
|
||||
end
|
||||
|
||||
def order
|
||||
@order ||= Spree::Order.
|
||||
where(number: params[:id]).
|
||||
includes(line_items: { variant: [:product, :stock_items, :default_price] }).
|
||||
first!
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,19 +0,0 @@
|
||||
module Api
|
||||
class ProductImagesController < Api::BaseController
|
||||
respond_to :json
|
||||
|
||||
def update_product_image
|
||||
@product = Spree::Product.find(params[:product_id])
|
||||
authorize! :update, @product
|
||||
|
||||
if @product.images.first.nil?
|
||||
@image = Spree::Image.create(attachment: params[:file], viewable_id: @product.master.id, viewable_type: 'Spree::Variant')
|
||||
render json: @image, serializer: ImageSerializer, status: :created
|
||||
else
|
||||
@image = @product.images.first
|
||||
@image.update(attachment: params[:file])
|
||||
render json: @image, serializer: ImageSerializer, status: :ok
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,159 +0,0 @@
|
||||
require 'open_food_network/permissions'
|
||||
require 'spree/core/product_duplicator'
|
||||
|
||||
module Api
|
||||
class ProductsController < Api::BaseController
|
||||
include PaginationData
|
||||
respond_to :json
|
||||
DEFAULT_PER_PAGE = 15
|
||||
|
||||
before_action :set_default_available_on, only: :create
|
||||
|
||||
skip_authorization_check only: [:show, :bulk_products, :overridable]
|
||||
|
||||
def show
|
||||
@product = find_product(params[:id])
|
||||
render json: @product, serializer: Api::Admin::ProductSerializer
|
||||
end
|
||||
|
||||
def create
|
||||
authorize! :create, Spree::Product
|
||||
@product = Spree::Product.new(product_params)
|
||||
|
||||
begin
|
||||
if @product.save
|
||||
render json: @product, serializer: Api::Admin::ProductSerializer, status: :created
|
||||
else
|
||||
invalid_resource!(@product)
|
||||
end
|
||||
rescue ActiveRecord::RecordNotUnique
|
||||
@product.permalink = nil
|
||||
retry
|
||||
end
|
||||
end
|
||||
|
||||
def update
|
||||
authorize! :update, Spree::Product
|
||||
@product = find_product(params[:id])
|
||||
if @product.update(product_params)
|
||||
render json: @product, serializer: Api::Admin::ProductSerializer, status: :ok
|
||||
else
|
||||
invalid_resource!(@product)
|
||||
end
|
||||
end
|
||||
|
||||
def destroy
|
||||
authorize! :delete, Spree::Product
|
||||
@product = find_product(params[:id])
|
||||
authorize! :delete, @product
|
||||
@product.destroy
|
||||
render json: @product, serializer: Api::Admin::ProductSerializer, status: :no_content
|
||||
end
|
||||
|
||||
def bulk_products
|
||||
product_query = OpenFoodNetwork::Permissions.
|
||||
new(current_api_user).
|
||||
editable_products.
|
||||
merge(product_scope)
|
||||
|
||||
if params[:import_date].present?
|
||||
product_query = product_query.
|
||||
imported_on(params[:import_date]).
|
||||
group_by_products_id
|
||||
end
|
||||
|
||||
@products = product_query.
|
||||
ransack(query_params_with_defaults).
|
||||
result.
|
||||
page(params[:page] || 1).
|
||||
per(params[:per_page] || DEFAULT_PER_PAGE)
|
||||
|
||||
render_paged_products @products
|
||||
end
|
||||
|
||||
def overridable
|
||||
producer_ids = OpenFoodNetwork::Permissions.new(current_api_user).
|
||||
variant_override_producers.by_name.select('enterprises.id')
|
||||
|
||||
@products = paged_products_for_producers producer_ids
|
||||
|
||||
render_paged_products @products, ::Api::Admin::ProductSimpleSerializer
|
||||
end
|
||||
|
||||
# POST /api/products/:product_id/clone
|
||||
#
|
||||
def clone
|
||||
authorize! :create, Spree::Product
|
||||
original_product = find_product(params[:product_id])
|
||||
authorize! :update, original_product
|
||||
|
||||
@product = original_product.duplicate
|
||||
|
||||
render json: @product, serializer: Api::Admin::ProductSerializer, status: :created
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def find_product(id)
|
||||
product_scope.find_by!(permalink: id.to_s)
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
product_scope.find(id)
|
||||
end
|
||||
|
||||
def product_scope
|
||||
if current_api_user.has_spree_role?("admin") || current_api_user.enterprises.present?
|
||||
scope = Spree::Product
|
||||
if params[:show_deleted]
|
||||
scope = scope.with_deleted
|
||||
end
|
||||
else
|
||||
scope = Spree::Product.active
|
||||
end
|
||||
|
||||
scope.includes(product_query_includes)
|
||||
end
|
||||
|
||||
def product_query_includes
|
||||
[
|
||||
master: [:images],
|
||||
variants: [:default_price, :stock_locations, :stock_items, :variant_overrides,
|
||||
{ option_values: :option_type }]
|
||||
]
|
||||
end
|
||||
|
||||
def paged_products_for_producers(producer_ids)
|
||||
Spree::Product.where(nil).
|
||||
merge(product_scope).
|
||||
includes(variants: [:product, :default_price, :stock_items]).
|
||||
where(supplier_id: producer_ids).
|
||||
by_producer.by_name.
|
||||
ransack(params[:q]).result.
|
||||
page(params[:page]).per(params[:per_page])
|
||||
end
|
||||
|
||||
def render_paged_products(products, product_serializer = ::Api::Admin::ProductSerializer)
|
||||
serialized_products = ActiveModel::ArraySerializer.new(
|
||||
products,
|
||||
each_serializer: product_serializer
|
||||
)
|
||||
|
||||
render json: {
|
||||
products: serialized_products,
|
||||
pagination: pagination_data(products)
|
||||
}
|
||||
end
|
||||
|
||||
def query_params_with_defaults
|
||||
(params[:q] || {}).reverse_merge(s: 'created_at desc')
|
||||
end
|
||||
|
||||
def product_params
|
||||
@product_params ||=
|
||||
params.permit(product: PermittedAttributes::Product.attributes)[:product].to_h
|
||||
end
|
||||
|
||||
def set_default_available_on
|
||||
product_params[:available_on] ||= Time.zone.now
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,16 +0,0 @@
|
||||
module Api
|
||||
class PromoImagesController < Api::EnterpriseAttachmentController
|
||||
private
|
||||
|
||||
def attachment_name
|
||||
:promo_image
|
||||
end
|
||||
|
||||
def enterprise_authorize_action
|
||||
case action_name.to_sym
|
||||
when :destroy
|
||||
:remove_promo_image
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,112 +0,0 @@
|
||||
require 'open_food_network/scope_variant_to_hub'
|
||||
|
||||
module Api
|
||||
class ShipmentsController < Api::BaseController
|
||||
respond_to :json
|
||||
|
||||
before_action :find_order
|
||||
before_action :find_and_update_shipment, only: [:ship, :ready, :add, :remove]
|
||||
|
||||
def create
|
||||
variant = scoped_variant(params[:variant_id])
|
||||
quantity = params[:quantity].to_i
|
||||
@shipment = get_or_create_shipment(params[:stock_location_id])
|
||||
|
||||
@order.contents.add(variant, quantity, nil, @shipment)
|
||||
|
||||
@shipment.refresh_rates
|
||||
@shipment.save!
|
||||
|
||||
render json: @shipment.reload, serializer: Api::ShipmentSerializer, status: :ok
|
||||
end
|
||||
|
||||
def update
|
||||
authorize! :read, Spree::Shipment
|
||||
@shipment = @order.shipments.find_by!(number: params[:id])
|
||||
params[:shipment] ||= []
|
||||
unlock = params[:shipment].delete(:unlock)
|
||||
|
||||
if unlock == 'yes'
|
||||
@shipment.fee_adjustment.open
|
||||
end
|
||||
|
||||
@shipment.update(shipment_params[:shipment])
|
||||
|
||||
if unlock == 'yes'
|
||||
@shipment.fee_adjustment.close
|
||||
end
|
||||
|
||||
render json: @shipment.reload, serializer: Api::ShipmentSerializer, status: :ok
|
||||
end
|
||||
|
||||
def ready
|
||||
authorize! :read, Spree::Shipment
|
||||
unless @shipment.ready?
|
||||
if @shipment.can_ready?
|
||||
@shipment.ready!
|
||||
else
|
||||
render(json: { error: I18n.t(:cannot_ready, scope: "spree.api.shipment") },
|
||||
status: :unprocessable_entity) && return
|
||||
end
|
||||
end
|
||||
render json: @shipment, serializer: Api::ShipmentSerializer, status: :ok
|
||||
end
|
||||
|
||||
def ship
|
||||
authorize! :read, Spree::Shipment
|
||||
unless @shipment.shipped?
|
||||
@shipment.ship!
|
||||
end
|
||||
render json: @shipment, serializer: Api::ShipmentSerializer, status: :ok
|
||||
end
|
||||
|
||||
def add
|
||||
variant = scoped_variant(params[:variant_id])
|
||||
quantity = params[:quantity].to_i
|
||||
|
||||
@order.contents.add(variant, quantity, nil, @shipment)
|
||||
|
||||
render json: @shipment, serializer: Api::ShipmentSerializer, status: :ok
|
||||
end
|
||||
|
||||
def remove
|
||||
variant = scoped_variant(params[:variant_id])
|
||||
quantity = params[:quantity].to_i
|
||||
|
||||
@order.contents.remove(variant, quantity, @shipment)
|
||||
@shipment.reload if @shipment.persisted?
|
||||
|
||||
render json: @shipment, serializer: Api::ShipmentSerializer, status: :ok
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def find_order
|
||||
@order = Spree::Order.find_by!(number: params[:order_id])
|
||||
authorize! :read, @order
|
||||
end
|
||||
|
||||
def find_and_update_shipment
|
||||
@shipment = @order.shipments.find_by!(number: params[:id])
|
||||
@shipment.update(shipment_params[:shipment]) if shipment_params[:shipment].present?
|
||||
@shipment.reload
|
||||
end
|
||||
|
||||
def scoped_variant(variant_id)
|
||||
variant = Spree::Variant.find(variant_id)
|
||||
OpenFoodNetwork::ScopeVariantToHub.new(@order.distributor).scope(variant)
|
||||
variant
|
||||
end
|
||||
|
||||
def get_or_create_shipment(stock_location_id)
|
||||
@order.shipment || @order.shipments.create(stock_location_id: stock_location_id)
|
||||
end
|
||||
|
||||
def shipment_params
|
||||
params.permit(
|
||||
[:id, :order_id, :variant_id, :quantity,
|
||||
{ shipment: [:tracking, :selected_shipping_rate_id] }]
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,27 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Api
|
||||
class ShopsController < BaseController
|
||||
respond_to :json
|
||||
skip_authorization_check only: [:show, :closed_shops]
|
||||
|
||||
def show
|
||||
enterprise = Enterprise.find_by(id: params[:id])
|
||||
|
||||
render plain: Api::EnterpriseShopfrontSerializer.new(enterprise).to_json, status: :ok
|
||||
end
|
||||
|
||||
def closed_shops
|
||||
@active_distributor_ids = []
|
||||
@earliest_closing_times = []
|
||||
|
||||
serialized_closed_shops = ActiveModel::ArraySerializer.new(
|
||||
ShopsListService.new.closed_shops,
|
||||
each_serializer: Api::EnterpriseSerializer,
|
||||
data: OpenFoodNetwork::EnterpriseInjectionData.new
|
||||
)
|
||||
|
||||
render json: serialized_closed_shops
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,44 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Api
|
||||
class StatesController < Api::BaseController
|
||||
respond_to :json
|
||||
|
||||
skip_authorization_check
|
||||
|
||||
def index
|
||||
render json: states, each_serializer: Api::StateSerializer, status: :ok
|
||||
end
|
||||
|
||||
def show
|
||||
@state = scope.find(params[:id])
|
||||
render json: @state, serializer: Api::StateSerializer, status: :ok
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def scope
|
||||
if params[:country_id]
|
||||
@country = Spree::Country.find(params[:country_id])
|
||||
@country.states
|
||||
else
|
||||
Spree::State.all
|
||||
end
|
||||
end
|
||||
|
||||
def states
|
||||
states = scope.ransack(params[:q]).result.
|
||||
includes(:country).order('name ASC')
|
||||
|
||||
if pagination?
|
||||
states = states.page(params[:page]).per(params[:per_page])
|
||||
end
|
||||
|
||||
states
|
||||
end
|
||||
|
||||
def pagination?
|
||||
params[:page] || params[:per_page]
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,16 +0,0 @@
|
||||
module Api
|
||||
class StatusesController < ::BaseController
|
||||
respond_to :json
|
||||
|
||||
def job_queue
|
||||
render json: { alive: job_queue_alive? }
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def job_queue_alive?
|
||||
Spree::Config.last_job_queue_heartbeat_at.present? &&
|
||||
Time.parse(Spree::Config.last_job_queue_heartbeat_at).in_time_zone > 6.minutes.ago
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,12 +0,0 @@
|
||||
module Api
|
||||
class TaxonomiesController < Api::BaseController
|
||||
respond_to :json
|
||||
|
||||
skip_authorization_check only: :jstree
|
||||
|
||||
def jstree
|
||||
@taxonomy = Spree::Taxonomy.find(params[:id])
|
||||
render json: @taxonomy.root, serializer: Api::TaxonJstreeSerializer
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,76 +0,0 @@
|
||||
module Api
|
||||
class TaxonsController < Api::BaseController
|
||||
respond_to :json
|
||||
|
||||
skip_authorization_check only: [:index, :show, :jstree]
|
||||
|
||||
def index
|
||||
@taxons = if taxonomy
|
||||
taxonomy.root.children
|
||||
elsif params[:ids]
|
||||
Spree::Taxon.where(id: raw_params[:ids].split(","))
|
||||
else
|
||||
Spree::Taxon.ransack(raw_params[:q]).result
|
||||
end
|
||||
render json: @taxons, each_serializer: Api::TaxonSerializer
|
||||
end
|
||||
|
||||
def jstree
|
||||
@taxon = taxon
|
||||
render json: @taxon.children, each_serializer: Api::TaxonJstreeSerializer
|
||||
end
|
||||
|
||||
def create
|
||||
authorize! :create, Spree::Taxon
|
||||
@taxon = Spree::Taxon.new(taxon_params)
|
||||
@taxon.taxonomy_id = params[:taxonomy_id]
|
||||
taxonomy = Spree::Taxonomy.find_by(id: params[:taxonomy_id])
|
||||
|
||||
if taxonomy.nil?
|
||||
@taxon.errors[:taxonomy_id] = I18n.t(:invalid_taxonomy_id, scope: 'spree.api')
|
||||
invalid_resource!(@taxon) && return
|
||||
end
|
||||
|
||||
@taxon.parent_id = taxonomy.root.id unless params.dig(:taxon, :parent_id)
|
||||
|
||||
if @taxon.save
|
||||
render json: @taxon, serializer: Api::TaxonSerializer, status: :created
|
||||
else
|
||||
invalid_resource!(@taxon)
|
||||
end
|
||||
end
|
||||
|
||||
def update
|
||||
authorize! :update, Spree::Taxon
|
||||
if taxon.update(taxon_params)
|
||||
render json: taxon, serializer: Api::TaxonSerializer, status: :ok
|
||||
else
|
||||
invalid_resource!(taxon)
|
||||
end
|
||||
end
|
||||
|
||||
def destroy
|
||||
authorize! :delete, Spree::Taxon
|
||||
taxon.destroy
|
||||
render json: taxon, serializer: Api::TaxonSerializer, status: :no_content
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def taxonomy
|
||||
return if params[:taxonomy_id].blank?
|
||||
|
||||
@taxonomy ||= Spree::Taxonomy.find(params[:taxonomy_id])
|
||||
end
|
||||
|
||||
def taxon
|
||||
@taxon ||= taxonomy.taxons.find(params[:id])
|
||||
end
|
||||
|
||||
def taxon_params
|
||||
return if params[:taxon].blank?
|
||||
|
||||
params.require(:taxon).permit([:name, :parent_id])
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,18 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Api
|
||||
class TermsAndConditionsController < Api::EnterpriseAttachmentController
|
||||
private
|
||||
|
||||
def attachment_name
|
||||
:terms_and_conditions
|
||||
end
|
||||
|
||||
def enterprise_authorize_action
|
||||
case action_name.to_sym
|
||||
when :destroy
|
||||
:remove_terms_and_conditions
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
107
app/controllers/api/v0/base_controller.rb
Normal file
107
app/controllers/api/v0/base_controller.rb
Normal file
@@ -0,0 +1,107 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
# Base controller for OFN's API
|
||||
require_dependency 'spree/api/controller_setup'
|
||||
require "spree/core/controller_helpers/ssl"
|
||||
|
||||
module Api
|
||||
module V0
|
||||
class BaseController < ActionController::Metal
|
||||
include RawParams
|
||||
include ActionController::StrongParameters
|
||||
include ActionController::RespondWith
|
||||
include Spree::Api::ControllerSetup
|
||||
include Spree::Core::ControllerHelpers::SSL
|
||||
include ::ActionController::Head
|
||||
include ::ActionController::ConditionalGet
|
||||
include ActionView::Layouts
|
||||
|
||||
layout false
|
||||
|
||||
attr_accessor :current_api_user
|
||||
|
||||
before_action :set_content_type
|
||||
before_action :authenticate_user
|
||||
|
||||
rescue_from Exception, with: :error_during_processing
|
||||
rescue_from CanCan::AccessDenied, with: :unauthorized
|
||||
rescue_from ActiveRecord::RecordNotFound, with: :not_found
|
||||
|
||||
helper Spree::Api::ApiHelpers
|
||||
|
||||
ssl_allowed
|
||||
|
||||
# Include these because we inherit from ActionController::Metal
|
||||
# rather than ActionController::Base and these are required for AMS
|
||||
include ActionController::Serialization
|
||||
include ActionController::UrlFor
|
||||
include Rails.application.routes.url_helpers
|
||||
|
||||
use_renderers :json
|
||||
check_authorization
|
||||
|
||||
def respond_with_conflict(json_hash)
|
||||
render json: json_hash, status: :conflict
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Use logged in user (spree_current_user) for API authentication (current_api_user)
|
||||
def authenticate_user
|
||||
return if @current_api_user = spree_current_user
|
||||
|
||||
if api_key.blank?
|
||||
# An anonymous user
|
||||
@current_api_user = Spree.user_class.new
|
||||
return
|
||||
end
|
||||
|
||||
return if @current_api_user = Spree.user_class.find_by(spree_api_key: api_key.to_s)
|
||||
|
||||
invalid_api_key
|
||||
end
|
||||
|
||||
def set_content_type
|
||||
headers["Content-Type"] = "application/json"
|
||||
end
|
||||
|
||||
def error_during_processing(exception)
|
||||
Bugsnag.notify(exception)
|
||||
|
||||
render(json: { exception: exception.message },
|
||||
status: :unprocessable_entity) && return
|
||||
end
|
||||
|
||||
def current_ability
|
||||
Spree::Ability.new(current_api_user)
|
||||
end
|
||||
|
||||
def api_key
|
||||
request.headers["X-Spree-Token"] || params[:token]
|
||||
end
|
||||
helper_method :api_key
|
||||
|
||||
def invalid_resource!(resource)
|
||||
@resource = resource
|
||||
render(json: { error: I18n.t(:invalid_resource, scope: "spree.api"),
|
||||
errors: @resource.errors },
|
||||
status: :unprocessable_entity)
|
||||
end
|
||||
|
||||
def invalid_api_key
|
||||
render(json: { error: I18n.t(:invalid_api_key, key: api_key, scope: "spree.api") },
|
||||
status: :unauthorized) && return
|
||||
end
|
||||
|
||||
def unauthorized
|
||||
render(json: { error: I18n.t(:unauthorized, scope: "spree.api") },
|
||||
status: :unauthorized) && return
|
||||
end
|
||||
|
||||
def not_found
|
||||
render(json: { error: I18n.t(:resource_not_found, scope: "spree.api") },
|
||||
status: :not_found) && return
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
41
app/controllers/api/v0/customers_controller.rb
Normal file
41
app/controllers/api/v0/customers_controller.rb
Normal file
@@ -0,0 +1,41 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Api
|
||||
module V0
|
||||
class CustomersController < Api::V0::BaseController
|
||||
skip_authorization_check only: :index
|
||||
|
||||
def index
|
||||
@customers = current_api_user.customers
|
||||
render json: @customers, each_serializer: CustomerSerializer
|
||||
end
|
||||
|
||||
def update
|
||||
@customer = Customer.find(params[:id])
|
||||
authorize! :update, @customer
|
||||
|
||||
client_secret = RecurringPayments.setup_for(@customer) if params[:customer][:allow_charges]
|
||||
|
||||
if @customer.update(customer_params)
|
||||
add_recurring_payment_info(client_secret)
|
||||
render json: @customer, serializer: CustomerSerializer, status: :ok
|
||||
else
|
||||
invalid_resource!(@customer)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def add_recurring_payment_info(client_secret)
|
||||
return unless client_secret
|
||||
|
||||
@customer.gateway_recurring_payment_client_secret = client_secret
|
||||
@customer.gateway_shop_id = @customer.enterprise.stripe_account&.stripe_user_id
|
||||
end
|
||||
|
||||
def customer_params
|
||||
params.require(:customer).permit(:code, :email, :enterprise_id, :allow_charges)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
49
app/controllers/api/v0/enterprise_attachment_controller.rb
Normal file
49
app/controllers/api/v0/enterprise_attachment_controller.rb
Normal file
@@ -0,0 +1,49 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'api/admin/enterprise_serializer'
|
||||
|
||||
module Api
|
||||
module V0
|
||||
class EnterpriseAttachmentController < Api::V0::BaseController
|
||||
class MissingImplementationError < StandardError; end
|
||||
|
||||
class UnknownEnterpriseAuthorizationActionError < StandardError; end
|
||||
|
||||
before_action :load_enterprise
|
||||
|
||||
respond_to :json
|
||||
|
||||
def destroy
|
||||
unless @enterprise.public_send("#{attachment_name}?")
|
||||
return respond_with_conflict(error: destroy_attachment_does_not_exist_error_message)
|
||||
end
|
||||
|
||||
@enterprise.update!(attachment_name => nil)
|
||||
render json: @enterprise,
|
||||
serializer: Admin::EnterpriseSerializer,
|
||||
spree_current_user: spree_current_user
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def attachment_name
|
||||
raise MissingImplementationError, "Method attachment_name should be defined"
|
||||
end
|
||||
|
||||
def enterprise_authorize_action
|
||||
raise MissingImplementationError, "Method enterprise_authorize_action should be defined"
|
||||
end
|
||||
|
||||
def load_enterprise
|
||||
@enterprise = Enterprise.find_by(permalink: params[:enterprise_id].to_s)
|
||||
raise UnknownEnterpriseAuthorizationActionError if enterprise_authorize_action.blank?
|
||||
|
||||
authorize!(enterprise_authorize_action, @enterprise)
|
||||
end
|
||||
|
||||
def destroy_attachment_does_not_exist_error_message
|
||||
I18n.t("api.enterprise_#{attachment_name}.destroy_attachment_does_not_exist")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
25
app/controllers/api/v0/enterprise_fees_controller.rb
Normal file
25
app/controllers/api/v0/enterprise_fees_controller.rb
Normal file
@@ -0,0 +1,25 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Api
|
||||
module V0
|
||||
class EnterpriseFeesController < Api::V0::BaseController
|
||||
respond_to :json
|
||||
|
||||
def destroy
|
||||
authorize! :destroy, enterprise_fee
|
||||
|
||||
if enterprise_fee.destroy
|
||||
render plain: I18n.t(:successfully_removed), status: :no_content
|
||||
else
|
||||
render plain: enterprise_fee.errors.full_messages.first, status: :forbidden
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def enterprise_fee
|
||||
@enterprise_fee ||= EnterpriseFee.find_by id: params[:id]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
82
app/controllers/api/v0/enterprises_controller.rb
Normal file
82
app/controllers/api/v0/enterprises_controller.rb
Normal file
@@ -0,0 +1,82 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Api
|
||||
module V0
|
||||
class EnterprisesController < Api::V0::BaseController
|
||||
before_action :override_owner, only: [:create, :update]
|
||||
before_action :check_type, only: :update
|
||||
before_action :override_sells, only: [:create, :update]
|
||||
before_action :override_visible, only: [:create, :update]
|
||||
respond_to :json
|
||||
|
||||
def create
|
||||
authorize! :create, Enterprise
|
||||
|
||||
# params[:user_ids] breaks the enterprise creation
|
||||
# We remove them from params and save them after creating the enterprise
|
||||
user_ids = enterprise_params.delete(:user_ids)
|
||||
@enterprise = Enterprise.new(enterprise_params)
|
||||
if @enterprise.save
|
||||
@enterprise.user_ids = user_ids
|
||||
render json: @enterprise.id, status: :created
|
||||
else
|
||||
invalid_resource!(@enterprise)
|
||||
end
|
||||
end
|
||||
|
||||
def update
|
||||
@enterprise = Enterprise.find_by(permalink: params[:id]) || Enterprise.find(params[:id])
|
||||
authorize! :update, @enterprise
|
||||
|
||||
if @enterprise.update(enterprise_params)
|
||||
render json: @enterprise.id, status: :ok
|
||||
else
|
||||
invalid_resource!(@enterprise)
|
||||
end
|
||||
end
|
||||
|
||||
def update_image
|
||||
@enterprise = Enterprise.find_by(permalink: params[:id]) || Enterprise.find(params[:id])
|
||||
authorize! :update, @enterprise
|
||||
|
||||
if params[:logo] && @enterprise.update( logo: params[:logo] )
|
||||
render plain: @enterprise.logo.url(:medium), status: :ok
|
||||
elsif params[:promo] && @enterprise.update( promo_image: params[:promo] )
|
||||
render plain: @enterprise.promo_image.url(:medium), status: :ok
|
||||
else
|
||||
invalid_resource!(@enterprise)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def override_owner
|
||||
enterprise_params[:owner_id] = current_api_user.id
|
||||
end
|
||||
|
||||
def check_type
|
||||
enterprise_params.delete :type unless current_api_user.admin?
|
||||
end
|
||||
|
||||
def override_sells
|
||||
has_hub = current_api_user.owned_enterprises.is_hub.any?
|
||||
new_enterprise_is_producer = !!enterprise_params[:is_primary_producer]
|
||||
|
||||
enterprise_params[:sells] = if has_hub && !new_enterprise_is_producer
|
||||
'any'
|
||||
else
|
||||
'unspecified'
|
||||
end
|
||||
end
|
||||
|
||||
def override_visible
|
||||
enterprise_params[:visible] = false
|
||||
end
|
||||
|
||||
def enterprise_params
|
||||
@enterprise_params ||= PermittedAttributes::Enterprise.new(params).call.
|
||||
to_h.with_indifferent_access
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
102
app/controllers/api/v0/exchange_products_controller.rb
Normal file
102
app/controllers/api/v0/exchange_products_controller.rb
Normal file
@@ -0,0 +1,102 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
# This controller lists products that can be added to an exchange
|
||||
#
|
||||
# Pagination is optional and can be required by using param[:page]
|
||||
module Api
|
||||
module V0
|
||||
class ExchangeProductsController < Api::V0::BaseController
|
||||
include PaginationData
|
||||
DEFAULT_PER_PAGE = 100
|
||||
|
||||
skip_authorization_check only: [:index]
|
||||
|
||||
# If exchange_id is present in the URL:
|
||||
# Lists Products that can be added to that Exchange
|
||||
#
|
||||
# If exchange_id is not present in the URL:
|
||||
# Lists Products of the Enterprise given that can be added to the given Order Cycle
|
||||
# In this case parameters are: enterprise_id, order_cycle_id and incoming
|
||||
# (order_cycle_id is not necessary for incoming exchanges)
|
||||
def index
|
||||
if exchange_params[:exchange_id].present?
|
||||
load_data_from_exchange
|
||||
else
|
||||
load_data_from_other_params
|
||||
end
|
||||
|
||||
render_variant_count && return if params[:action_name] == "variant_count"
|
||||
|
||||
render_paginated_products paginated_products
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def render_variant_count
|
||||
render plain: {
|
||||
count: variants.count
|
||||
}.to_json
|
||||
end
|
||||
|
||||
def variants
|
||||
renderer.exchange_variants(@incoming, @enterprise)
|
||||
end
|
||||
|
||||
def products
|
||||
renderer.exchange_products(@incoming, @enterprise)
|
||||
end
|
||||
|
||||
def renderer
|
||||
@renderer ||= ExchangeProductsRenderer.
|
||||
new(@order_cycle, spree_current_user)
|
||||
end
|
||||
|
||||
def paginated_products
|
||||
return products unless pagination_required?
|
||||
|
||||
products.
|
||||
page(params[:page]).
|
||||
per(params[:per_page] || DEFAULT_PER_PAGE)
|
||||
end
|
||||
|
||||
def load_data_from_exchange
|
||||
exchange = Exchange.find_by(id: exchange_params[:exchange_id])
|
||||
|
||||
@order_cycle = exchange.order_cycle
|
||||
@incoming = exchange.incoming
|
||||
@enterprise = exchange.sender
|
||||
end
|
||||
|
||||
def load_data_from_other_params
|
||||
@enterprise = Enterprise.find_by(id: exchange_params[:enterprise_id])
|
||||
|
||||
# This will be a string (eg "true") when it arrives via params, but we want a boolean
|
||||
@incoming = ActiveModel::Type::Boolean.new.cast exchange_params[:incoming]
|
||||
|
||||
if exchange_params[:order_cycle_id]
|
||||
@order_cycle = OrderCycle.find_by(id: exchange_params[:order_cycle_id])
|
||||
elsif !@incoming
|
||||
raise "order_cycle_id is required to list products for new outgoing exchange"
|
||||
end
|
||||
end
|
||||
|
||||
def render_paginated_products(paginated_products)
|
||||
serialized_products = ActiveModel::ArraySerializer.new(
|
||||
paginated_products,
|
||||
each_serializer: Api::Admin::ForOrderCycle::SuppliedProductSerializer,
|
||||
order_cycle: @order_cycle
|
||||
)
|
||||
|
||||
render json: {
|
||||
products: serialized_products,
|
||||
pagination: pagination_data(paginated_products)
|
||||
}
|
||||
end
|
||||
|
||||
def exchange_params
|
||||
params.permit(:enterprise_id, :exchange_id, :order_cycle_id, :incoming).
|
||||
to_h.with_indifferent_access
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
20
app/controllers/api/v0/logos_controller.rb
Normal file
20
app/controllers/api/v0/logos_controller.rb
Normal file
@@ -0,0 +1,20 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Api
|
||||
module V0
|
||||
class LogosController < Api::V0::EnterpriseAttachmentController
|
||||
private
|
||||
|
||||
def attachment_name
|
||||
:logo
|
||||
end
|
||||
|
||||
def enterprise_authorize_action
|
||||
case action_name.to_sym
|
||||
when :destroy
|
||||
:remove_logo
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
105
app/controllers/api/v0/order_cycles_controller.rb
Normal file
105
app/controllers/api/v0/order_cycles_controller.rb
Normal file
@@ -0,0 +1,105 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Api
|
||||
module V0
|
||||
class OrderCyclesController < Api::V0::BaseController
|
||||
include EnterprisesHelper
|
||||
include ApiActionCaching
|
||||
|
||||
skip_authorization_check
|
||||
skip_before_action :authenticate_user, :ensure_api_key, only: [:taxons, :properties]
|
||||
|
||||
caches_action :taxons, :properties,
|
||||
expires_in: CacheService::FILTERS_EXPIRY,
|
||||
cache_path: proc { |controller| controller.request.url }
|
||||
|
||||
def products
|
||||
return render_no_products unless order_cycle.open?
|
||||
|
||||
products = ProductsRenderer.new(
|
||||
distributor,
|
||||
order_cycle,
|
||||
customer,
|
||||
search_params
|
||||
).products_json
|
||||
|
||||
render plain: products
|
||||
rescue ProductsRenderer::NoProducts
|
||||
render_no_products
|
||||
end
|
||||
|
||||
def taxons
|
||||
taxons = Spree::Taxon.
|
||||
joins(:products).
|
||||
where(spree_products: { id: distributed_products }).
|
||||
select('DISTINCT spree_taxons.*')
|
||||
|
||||
render plain: ActiveModel::ArraySerializer.new(
|
||||
taxons, each_serializer: Api::TaxonSerializer
|
||||
).to_json
|
||||
end
|
||||
|
||||
def properties
|
||||
render plain: ActiveModel::ArraySerializer.new(
|
||||
product_properties | producer_properties, each_serializer: Api::PropertySerializer
|
||||
).to_json
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def render_no_products
|
||||
render status: :not_found, json: {}
|
||||
end
|
||||
|
||||
def product_properties
|
||||
Spree::Property.
|
||||
joins(:products).
|
||||
where(spree_products: { id: distributed_products }).
|
||||
select('DISTINCT spree_properties.*')
|
||||
end
|
||||
|
||||
def producer_properties
|
||||
producers = Enterprise.
|
||||
joins(:supplied_products).
|
||||
where(spree_products: { id: distributed_products })
|
||||
|
||||
Spree::Property.
|
||||
joins(:producer_properties).
|
||||
where(producer_properties: { producer_id: producers }).
|
||||
select('DISTINCT spree_properties.*')
|
||||
end
|
||||
|
||||
def search_params
|
||||
permitted_search_params = params.slice :q, :page, :per_page
|
||||
|
||||
if permitted_search_params.key? :q
|
||||
permitted_search_params[:q].slice!(*permitted_ransack_params)
|
||||
end
|
||||
|
||||
permitted_search_params
|
||||
end
|
||||
|
||||
def permitted_ransack_params
|
||||
[:name_or_meta_keywords_or_variants_display_as_or_variants_display_name_or_supplier_name_cont,
|
||||
:properties_id_or_supplier_properties_id_in_any,
|
||||
:primary_taxon_id_in_any]
|
||||
end
|
||||
|
||||
def distributor
|
||||
@distributor ||= Enterprise.find_by(id: params[:distributor])
|
||||
end
|
||||
|
||||
def order_cycle
|
||||
@order_cycle ||= OrderCycle.find_by(id: params[:id])
|
||||
end
|
||||
|
||||
def customer
|
||||
@current_api_user.andand.customer_of(distributor) || nil
|
||||
end
|
||||
|
||||
def distributed_products
|
||||
OrderCycleDistributedProducts.new(distributor, order_cycle, customer).products_relation
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
72
app/controllers/api/v0/orders_controller.rb
Normal file
72
app/controllers/api/v0/orders_controller.rb
Normal file
@@ -0,0 +1,72 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Api
|
||||
module V0
|
||||
class OrdersController < Api::V0::BaseController
|
||||
include PaginationData
|
||||
|
||||
def show
|
||||
authorize! :read, order
|
||||
render json: order, serializer: Api::OrderDetailedSerializer, current_order: order
|
||||
end
|
||||
|
||||
def index
|
||||
authorize! :admin, Spree::Order
|
||||
|
||||
orders = SearchOrders.new(params, current_api_user).orders
|
||||
|
||||
render json: {
|
||||
orders: serialized_orders(orders),
|
||||
pagination: pagination_data(orders)
|
||||
}
|
||||
end
|
||||
|
||||
def ship
|
||||
authorize! :admin, order
|
||||
|
||||
if order.ship
|
||||
render json: order.reload, serializer: Api::Admin::OrderSerializer, status: :ok
|
||||
else
|
||||
render json: { error: I18n.t('api.orders.failed_to_update') },
|
||||
status: :unprocessable_entity
|
||||
end
|
||||
end
|
||||
|
||||
def capture
|
||||
authorize! :admin, order
|
||||
|
||||
pending_payment = order.pending_payments.first
|
||||
|
||||
return payment_capture_failed unless order.payment_required? && pending_payment
|
||||
|
||||
if pending_payment.capture!
|
||||
render json: order.reload, serializer: Api::Admin::OrderSerializer, status: :ok
|
||||
else
|
||||
payment_capture_failed
|
||||
end
|
||||
rescue Spree::Core::GatewayError => e
|
||||
error_during_processing(e)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def payment_capture_failed
|
||||
render json: { error: I18n.t(:payment_processing_failed) }, status: :unprocessable_entity
|
||||
end
|
||||
|
||||
def serialized_orders(orders)
|
||||
ActiveModel::ArraySerializer.new(
|
||||
orders,
|
||||
each_serializer: Api::Admin::OrderSerializer
|
||||
)
|
||||
end
|
||||
|
||||
def order
|
||||
@order ||= Spree::Order.
|
||||
where(number: params[:id]).
|
||||
includes(line_items: { variant: [:product, :stock_items, :default_price] }).
|
||||
first!
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
27
app/controllers/api/v0/product_images_controller.rb
Normal file
27
app/controllers/api/v0/product_images_controller.rb
Normal file
@@ -0,0 +1,27 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Api
|
||||
module V0
|
||||
class ProductImagesController < Api::V0::BaseController
|
||||
respond_to :json
|
||||
|
||||
def update_product_image
|
||||
@product = Spree::Product.find(params[:product_id])
|
||||
authorize! :update, @product
|
||||
|
||||
if @product.images.first.nil?
|
||||
@image = Spree::Image.create(
|
||||
attachment: params[:file],
|
||||
viewable_id: @product.master.id,
|
||||
viewable_type: 'Spree::Variant'
|
||||
)
|
||||
render json: @image, serializer: ImageSerializer, status: :created
|
||||
else
|
||||
@image = @product.images.first
|
||||
@image.update(attachment: params[:file])
|
||||
render json: @image, serializer: ImageSerializer, status: :ok
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
163
app/controllers/api/v0/products_controller.rb
Normal file
163
app/controllers/api/v0/products_controller.rb
Normal file
@@ -0,0 +1,163 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'open_food_network/permissions'
|
||||
require 'spree/core/product_duplicator'
|
||||
|
||||
module Api
|
||||
module V0
|
||||
class ProductsController < Api::V0::BaseController
|
||||
include PaginationData
|
||||
respond_to :json
|
||||
DEFAULT_PER_PAGE = 15
|
||||
|
||||
before_action :set_default_available_on, only: :create
|
||||
|
||||
skip_authorization_check only: [:show, :bulk_products, :overridable]
|
||||
|
||||
def show
|
||||
@product = find_product(params[:id])
|
||||
render json: @product, serializer: Api::Admin::ProductSerializer
|
||||
end
|
||||
|
||||
def create
|
||||
authorize! :create, Spree::Product
|
||||
@product = Spree::Product.new(product_params)
|
||||
|
||||
begin
|
||||
if @product.save
|
||||
render json: @product, serializer: Api::Admin::ProductSerializer, status: :created
|
||||
else
|
||||
invalid_resource!(@product)
|
||||
end
|
||||
rescue ActiveRecord::RecordNotUnique
|
||||
@product.permalink = nil
|
||||
retry
|
||||
end
|
||||
end
|
||||
|
||||
def update
|
||||
authorize! :update, Spree::Product
|
||||
@product = find_product(params[:id])
|
||||
if @product.update(product_params)
|
||||
render json: @product, serializer: Api::Admin::ProductSerializer, status: :ok
|
||||
else
|
||||
invalid_resource!(@product)
|
||||
end
|
||||
end
|
||||
|
||||
def destroy
|
||||
authorize! :delete, Spree::Product
|
||||
@product = find_product(params[:id])
|
||||
authorize! :delete, @product
|
||||
@product.destroy
|
||||
render json: @product, serializer: Api::Admin::ProductSerializer, status: :no_content
|
||||
end
|
||||
|
||||
def bulk_products
|
||||
product_query = OpenFoodNetwork::Permissions.
|
||||
new(current_api_user).
|
||||
editable_products.
|
||||
merge(product_scope)
|
||||
|
||||
if params[:import_date].present?
|
||||
product_query = product_query.
|
||||
imported_on(params[:import_date]).
|
||||
group_by_products_id
|
||||
end
|
||||
|
||||
@products = product_query.
|
||||
ransack(query_params_with_defaults).
|
||||
result.
|
||||
page(params[:page] || 1).
|
||||
per(params[:per_page] || DEFAULT_PER_PAGE)
|
||||
|
||||
render_paged_products @products
|
||||
end
|
||||
|
||||
def overridable
|
||||
producer_ids = OpenFoodNetwork::Permissions.new(current_api_user).
|
||||
variant_override_producers.by_name.select('enterprises.id')
|
||||
|
||||
@products = paged_products_for_producers producer_ids
|
||||
|
||||
render_paged_products @products, ::Api::Admin::ProductSimpleSerializer
|
||||
end
|
||||
|
||||
# POST /api/products/:product_id/clone
|
||||
#
|
||||
def clone
|
||||
authorize! :create, Spree::Product
|
||||
original_product = find_product(params[:product_id])
|
||||
authorize! :update, original_product
|
||||
|
||||
@product = original_product.duplicate
|
||||
|
||||
render json: @product, serializer: Api::Admin::ProductSerializer, status: :created
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def find_product(id)
|
||||
product_scope.find_by!(permalink: id.to_s)
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
product_scope.find(id)
|
||||
end
|
||||
|
||||
def product_scope
|
||||
if current_api_user.has_spree_role?("admin") || current_api_user.enterprises.present?
|
||||
scope = Spree::Product
|
||||
if params[:show_deleted]
|
||||
scope = scope.with_deleted
|
||||
end
|
||||
else
|
||||
scope = Spree::Product.active
|
||||
end
|
||||
|
||||
scope.includes(product_query_includes)
|
||||
end
|
||||
|
||||
def product_query_includes
|
||||
[
|
||||
master: [:images],
|
||||
variants: [:default_price, :stock_locations, :stock_items, :variant_overrides,
|
||||
{ option_values: :option_type }]
|
||||
]
|
||||
end
|
||||
|
||||
def paged_products_for_producers(producer_ids)
|
||||
Spree::Product.where(nil).
|
||||
merge(product_scope).
|
||||
includes(variants: [:product, :default_price, :stock_items]).
|
||||
where(supplier_id: producer_ids).
|
||||
by_producer.by_name.
|
||||
ransack(params[:q]).result.
|
||||
page(params[:page]).per(params[:per_page])
|
||||
end
|
||||
|
||||
def render_paged_products(products, product_serializer = ::Api::Admin::ProductSerializer)
|
||||
serialized_products = ActiveModel::ArraySerializer.new(
|
||||
products,
|
||||
each_serializer: product_serializer
|
||||
)
|
||||
|
||||
render json: {
|
||||
products: serialized_products,
|
||||
pagination: pagination_data(products)
|
||||
}
|
||||
end
|
||||
|
||||
def query_params_with_defaults
|
||||
(params[:q] || {}).reverse_merge(s: 'created_at desc')
|
||||
end
|
||||
|
||||
def product_params
|
||||
@product_params ||=
|
||||
params.permit(product: PermittedAttributes::Product.attributes)[:product].to_h
|
||||
end
|
||||
|
||||
def set_default_available_on
|
||||
product_params[:available_on] ||= Time.zone.now
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
20
app/controllers/api/v0/promo_images_controller.rb
Normal file
20
app/controllers/api/v0/promo_images_controller.rb
Normal file
@@ -0,0 +1,20 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Api
|
||||
module V0
|
||||
class PromoImagesController < Api::V0::EnterpriseAttachmentController
|
||||
private
|
||||
|
||||
def attachment_name
|
||||
:promo_image
|
||||
end
|
||||
|
||||
def enterprise_authorize_action
|
||||
case action_name.to_sym
|
||||
when :destroy
|
||||
:remove_promo_image
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
116
app/controllers/api/v0/shipments_controller.rb
Normal file
116
app/controllers/api/v0/shipments_controller.rb
Normal file
@@ -0,0 +1,116 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'open_food_network/scope_variant_to_hub'
|
||||
|
||||
module Api
|
||||
module V0
|
||||
class ShipmentsController < Api::V0::BaseController
|
||||
respond_to :json
|
||||
|
||||
before_action :find_order
|
||||
before_action :find_and_update_shipment, only: [:ship, :ready, :add, :remove]
|
||||
|
||||
def create
|
||||
variant = scoped_variant(params[:variant_id])
|
||||
quantity = params[:quantity].to_i
|
||||
@shipment = get_or_create_shipment(params[:stock_location_id])
|
||||
|
||||
@order.contents.add(variant, quantity, nil, @shipment)
|
||||
|
||||
@shipment.refresh_rates
|
||||
@shipment.save!
|
||||
|
||||
render json: @shipment.reload, serializer: Api::ShipmentSerializer, status: :ok
|
||||
end
|
||||
|
||||
def update
|
||||
authorize! :read, Spree::Shipment
|
||||
@shipment = @order.shipments.find_by!(number: params[:id])
|
||||
params[:shipment] ||= []
|
||||
unlock = params[:shipment].delete(:unlock)
|
||||
|
||||
if unlock == 'yes'
|
||||
@shipment.fee_adjustment.open
|
||||
end
|
||||
|
||||
@shipment.update(shipment_params[:shipment])
|
||||
|
||||
if unlock == 'yes'
|
||||
@shipment.fee_adjustment.close
|
||||
end
|
||||
|
||||
render json: @shipment.reload, serializer: Api::ShipmentSerializer, status: :ok
|
||||
end
|
||||
|
||||
def ready
|
||||
authorize! :read, Spree::Shipment
|
||||
unless @shipment.ready?
|
||||
if @shipment.can_ready?
|
||||
@shipment.ready!
|
||||
else
|
||||
render(json: { error: I18n.t(:cannot_ready, scope: "spree.api.shipment") },
|
||||
status: :unprocessable_entity) && return
|
||||
end
|
||||
end
|
||||
render json: @shipment, serializer: Api::ShipmentSerializer, status: :ok
|
||||
end
|
||||
|
||||
def ship
|
||||
authorize! :read, Spree::Shipment
|
||||
unless @shipment.shipped?
|
||||
@shipment.ship!
|
||||
end
|
||||
render json: @shipment, serializer: Api::ShipmentSerializer, status: :ok
|
||||
end
|
||||
|
||||
def add
|
||||
variant = scoped_variant(params[:variant_id])
|
||||
quantity = params[:quantity].to_i
|
||||
|
||||
@order.contents.add(variant, quantity, nil, @shipment)
|
||||
|
||||
render json: @shipment, serializer: Api::ShipmentSerializer, status: :ok
|
||||
end
|
||||
|
||||
def remove
|
||||
variant = scoped_variant(params[:variant_id])
|
||||
quantity = params[:quantity].to_i
|
||||
|
||||
@order.contents.remove(variant, quantity, @shipment)
|
||||
@shipment.reload if @shipment.persisted?
|
||||
|
||||
render json: @shipment, serializer: Api::ShipmentSerializer, status: :ok
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def find_order
|
||||
@order = Spree::Order.find_by!(number: params[:order_id])
|
||||
authorize! :read, @order
|
||||
end
|
||||
|
||||
def find_and_update_shipment
|
||||
@shipment = @order.shipments.find_by!(number: params[:id])
|
||||
@shipment.update(shipment_params[:shipment]) if shipment_params[:shipment].present?
|
||||
@shipment.reload
|
||||
end
|
||||
|
||||
def scoped_variant(variant_id)
|
||||
variant = Spree::Variant.find(variant_id)
|
||||
OpenFoodNetwork::ScopeVariantToHub.new(@order.distributor).scope(variant)
|
||||
variant
|
||||
end
|
||||
|
||||
def get_or_create_shipment(stock_location_id)
|
||||
@order.shipment || @order.shipments.create(stock_location_id: stock_location_id)
|
||||
end
|
||||
|
||||
def shipment_params
|
||||
params.permit(
|
||||
[:id, :order_id, :variant_id, :quantity,
|
||||
{ shipment: [:tracking, :selected_shipping_rate_id] }]
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
29
app/controllers/api/v0/shops_controller.rb
Normal file
29
app/controllers/api/v0/shops_controller.rb
Normal file
@@ -0,0 +1,29 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Api
|
||||
module V0
|
||||
class ShopsController < BaseController
|
||||
respond_to :json
|
||||
skip_authorization_check only: [:show, :closed_shops]
|
||||
|
||||
def show
|
||||
enterprise = Enterprise.find_by(id: params[:id])
|
||||
|
||||
render plain: Api::EnterpriseShopfrontSerializer.new(enterprise).to_json, status: :ok
|
||||
end
|
||||
|
||||
def closed_shops
|
||||
@active_distributor_ids = []
|
||||
@earliest_closing_times = []
|
||||
|
||||
serialized_closed_shops = ActiveModel::ArraySerializer.new(
|
||||
ShopsListService.new.closed_shops,
|
||||
each_serializer: Api::EnterpriseSerializer,
|
||||
data: OpenFoodNetwork::EnterpriseInjectionData.new
|
||||
)
|
||||
|
||||
render json: serialized_closed_shops
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
46
app/controllers/api/v0/states_controller.rb
Normal file
46
app/controllers/api/v0/states_controller.rb
Normal file
@@ -0,0 +1,46 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Api
|
||||
module V0
|
||||
class StatesController < Api::V0::BaseController
|
||||
respond_to :json
|
||||
|
||||
skip_authorization_check
|
||||
|
||||
def index
|
||||
render json: states, each_serializer: Api::StateSerializer, status: :ok
|
||||
end
|
||||
|
||||
def show
|
||||
@state = scope.find(params[:id])
|
||||
render json: @state, serializer: Api::StateSerializer, status: :ok
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def scope
|
||||
if params[:country_id]
|
||||
@country = Spree::Country.find(params[:country_id])
|
||||
@country.states
|
||||
else
|
||||
Spree::State.all
|
||||
end
|
||||
end
|
||||
|
||||
def states
|
||||
states = scope.ransack(params[:q]).result.
|
||||
includes(:country).order('name ASC')
|
||||
|
||||
if pagination?
|
||||
states = states.page(params[:page]).per(params[:per_page])
|
||||
end
|
||||
|
||||
states
|
||||
end
|
||||
|
||||
def pagination?
|
||||
params[:page] || params[:per_page]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
20
app/controllers/api/v0/statuses_controller.rb
Normal file
20
app/controllers/api/v0/statuses_controller.rb
Normal file
@@ -0,0 +1,20 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Api
|
||||
module V0
|
||||
class StatusesController < ::BaseController
|
||||
respond_to :json
|
||||
|
||||
def job_queue
|
||||
render json: { alive: job_queue_alive? }
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def job_queue_alive?
|
||||
Spree::Config.last_job_queue_heartbeat_at.present? &&
|
||||
Time.parse(Spree::Config.last_job_queue_heartbeat_at).in_time_zone > 6.minutes.ago
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
16
app/controllers/api/v0/taxonomies_controller.rb
Normal file
16
app/controllers/api/v0/taxonomies_controller.rb
Normal file
@@ -0,0 +1,16 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Api
|
||||
module V0
|
||||
class TaxonomiesController < Api::V0::BaseController
|
||||
respond_to :json
|
||||
|
||||
skip_authorization_check only: :jstree
|
||||
|
||||
def jstree
|
||||
@taxonomy = Spree::Taxonomy.find(params[:id])
|
||||
render json: @taxonomy.root, serializer: Api::TaxonJstreeSerializer
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
78
app/controllers/api/v0/taxons_controller.rb
Normal file
78
app/controllers/api/v0/taxons_controller.rb
Normal file
@@ -0,0 +1,78 @@
|
||||
module Api
|
||||
module V0
|
||||
class TaxonsController < Api::V0::BaseController
|
||||
respond_to :json
|
||||
|
||||
skip_authorization_check only: [:index, :show, :jstree]
|
||||
|
||||
def index
|
||||
@taxons = if taxonomy
|
||||
taxonomy.root.children
|
||||
elsif params[:ids]
|
||||
Spree::Taxon.where(id: raw_params[:ids].split(","))
|
||||
else
|
||||
Spree::Taxon.ransack(raw_params[:q]).result
|
||||
end
|
||||
render json: @taxons, each_serializer: Api::TaxonSerializer
|
||||
end
|
||||
|
||||
def jstree
|
||||
@taxon = taxon
|
||||
render json: @taxon.children, each_serializer: Api::TaxonJstreeSerializer
|
||||
end
|
||||
|
||||
def create
|
||||
authorize! :create, Spree::Taxon
|
||||
@taxon = Spree::Taxon.new(taxon_params)
|
||||
@taxon.taxonomy_id = params[:taxonomy_id]
|
||||
taxonomy = Spree::Taxonomy.find_by(id: params[:taxonomy_id])
|
||||
|
||||
if taxonomy.nil?
|
||||
@taxon.errors[:taxonomy_id] = I18n.t(:invalid_taxonomy_id, scope: 'spree.api')
|
||||
invalid_resource!(@taxon) && return
|
||||
end
|
||||
|
||||
@taxon.parent_id = taxonomy.root.id unless params.dig(:taxon, :parent_id)
|
||||
|
||||
if @taxon.save
|
||||
render json: @taxon, serializer: Api::TaxonSerializer, status: :created
|
||||
else
|
||||
invalid_resource!(@taxon)
|
||||
end
|
||||
end
|
||||
|
||||
def update
|
||||
authorize! :update, Spree::Taxon
|
||||
if taxon.update(taxon_params)
|
||||
render json: taxon, serializer: Api::TaxonSerializer, status: :ok
|
||||
else
|
||||
invalid_resource!(taxon)
|
||||
end
|
||||
end
|
||||
|
||||
def destroy
|
||||
authorize! :delete, Spree::Taxon
|
||||
taxon.destroy
|
||||
render json: taxon, serializer: Api::TaxonSerializer, status: :no_content
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def taxonomy
|
||||
return if params[:taxonomy_id].blank?
|
||||
|
||||
@taxonomy ||= Spree::Taxonomy.find(params[:taxonomy_id])
|
||||
end
|
||||
|
||||
def taxon
|
||||
@taxon ||= taxonomy.taxons.find(params[:id])
|
||||
end
|
||||
|
||||
def taxon_params
|
||||
return if params[:taxon].blank?
|
||||
|
||||
params.require(:taxon).permit([:name, :parent_id])
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
20
app/controllers/api/v0/terms_and_conditions_controller.rb
Normal file
20
app/controllers/api/v0/terms_and_conditions_controller.rb
Normal file
@@ -0,0 +1,20 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Api
|
||||
module V0
|
||||
class TermsAndConditionsController < Api::V0::EnterpriseAttachmentController
|
||||
private
|
||||
|
||||
def attachment_name
|
||||
:terms_and_conditions
|
||||
end
|
||||
|
||||
def enterprise_authorize_action
|
||||
case action_name.to_sym
|
||||
when :destroy
|
||||
:remove_terms_and_conditions
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
81
app/controllers/api/v0/variants_controller.rb
Normal file
81
app/controllers/api/v0/variants_controller.rb
Normal file
@@ -0,0 +1,81 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Api
|
||||
module V0
|
||||
class VariantsController < Api::V0::BaseController
|
||||
respond_to :json
|
||||
|
||||
skip_authorization_check only: [:index, :show]
|
||||
before_action :product
|
||||
|
||||
def index
|
||||
@variants = scope.includes(option_values: :option_type).ransack(params[:q]).result
|
||||
render json: @variants, each_serializer: Api::VariantSerializer
|
||||
end
|
||||
|
||||
def show
|
||||
@variant = scope.includes(option_values: :option_type).find(params[:id])
|
||||
render json: @variant, serializer: Api::VariantSerializer
|
||||
end
|
||||
|
||||
def create
|
||||
authorize! :create, Spree::Variant
|
||||
@variant = scope.new(variant_params)
|
||||
if @variant.save
|
||||
render json: @variant, serializer: Api::VariantSerializer, status: :created
|
||||
else
|
||||
invalid_resource!(@variant)
|
||||
end
|
||||
end
|
||||
|
||||
def update
|
||||
authorize! :update, Spree::Variant
|
||||
@variant = scope.find(params[:id])
|
||||
if @variant.update(variant_params)
|
||||
render json: @variant, serializer: Api::VariantSerializer, status: :ok
|
||||
else
|
||||
invalid_resource!(@product)
|
||||
end
|
||||
end
|
||||
|
||||
def destroy
|
||||
authorize! :delete, Spree::Variant
|
||||
@variant = scope.find(params[:id])
|
||||
authorize! :delete, @variant
|
||||
|
||||
VariantDeleter.new.delete(@variant)
|
||||
render json: @variant, serializer: Api::VariantSerializer, status: :no_content
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def product
|
||||
@product ||= Spree::Product.find_by(permalink: params[:product_id]) if params[:product_id]
|
||||
end
|
||||
|
||||
def scope
|
||||
if @product
|
||||
variants = if current_api_user.has_spree_role?("admin") || params[:show_deleted]
|
||||
@product.variants_including_master.with_deleted
|
||||
else
|
||||
@product.variants_including_master
|
||||
end
|
||||
else
|
||||
variants = Spree::Variant.where(nil)
|
||||
if current_api_user.has_spree_role?("admin")
|
||||
unless params[:show_deleted]
|
||||
variants = Spree::Variant.active
|
||||
end
|
||||
else
|
||||
variants = variants.active
|
||||
end
|
||||
end
|
||||
variants
|
||||
end
|
||||
|
||||
def variant_params
|
||||
params.require(:variant).permit(PermittedAttributes::Variant.attributes)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,77 +0,0 @@
|
||||
module Api
|
||||
class VariantsController < Api::BaseController
|
||||
respond_to :json
|
||||
|
||||
skip_authorization_check only: [:index, :show]
|
||||
before_action :product
|
||||
|
||||
def index
|
||||
@variants = scope.includes(option_values: :option_type).ransack(params[:q]).result
|
||||
render json: @variants, each_serializer: Api::VariantSerializer
|
||||
end
|
||||
|
||||
def show
|
||||
@variant = scope.includes(option_values: :option_type).find(params[:id])
|
||||
render json: @variant, serializer: Api::VariantSerializer
|
||||
end
|
||||
|
||||
def create
|
||||
authorize! :create, Spree::Variant
|
||||
@variant = scope.new(variant_params)
|
||||
if @variant.save
|
||||
render json: @variant, serializer: Api::VariantSerializer, status: :created
|
||||
else
|
||||
invalid_resource!(@variant)
|
||||
end
|
||||
end
|
||||
|
||||
def update
|
||||
authorize! :update, Spree::Variant
|
||||
@variant = scope.find(params[:id])
|
||||
if @variant.update(variant_params)
|
||||
render json: @variant, serializer: Api::VariantSerializer, status: :ok
|
||||
else
|
||||
invalid_resource!(@product)
|
||||
end
|
||||
end
|
||||
|
||||
def destroy
|
||||
authorize! :delete, Spree::Variant
|
||||
@variant = scope.find(params[:id])
|
||||
authorize! :delete, @variant
|
||||
|
||||
VariantDeleter.new.delete(@variant)
|
||||
render json: @variant, serializer: Api::VariantSerializer, status: :no_content
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def product
|
||||
@product ||= Spree::Product.find_by(permalink: params[:product_id]) if params[:product_id]
|
||||
end
|
||||
|
||||
def scope
|
||||
if @product
|
||||
variants = if current_api_user.has_spree_role?("admin") || params[:show_deleted]
|
||||
@product.variants_including_master.with_deleted
|
||||
else
|
||||
@product.variants_including_master
|
||||
end
|
||||
else
|
||||
variants = Spree::Variant.where(nil)
|
||||
if current_api_user.has_spree_role?("admin")
|
||||
unless params[:show_deleted]
|
||||
variants = Spree::Variant.active
|
||||
end
|
||||
else
|
||||
variants = variants.active
|
||||
end
|
||||
end
|
||||
variants
|
||||
end
|
||||
|
||||
def variant_params
|
||||
params.require(:variant).permit(PermittedAttributes::Variant.attributes)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -5,7 +5,6 @@ module Spree
|
||||
before_action :load_data
|
||||
before_action :validate_payment_method_provider, only: [:create]
|
||||
before_action :load_hubs, only: [:new, :edit, :update]
|
||||
create.before :load_hubs
|
||||
|
||||
respond_to :html
|
||||
|
||||
@@ -15,14 +14,12 @@ module Spree
|
||||
@payment_method = payment_method_class.constantize.new(base_params)
|
||||
@object = @payment_method
|
||||
|
||||
invoke_callbacks(:create, :before)
|
||||
load_hubs
|
||||
|
||||
if @payment_method.save
|
||||
invoke_callbacks(:create, :after)
|
||||
flash[:success] = Spree.t(:successfully_created, resource: Spree.t(:payment_method))
|
||||
redirect_to spree.edit_admin_payment_method_path(@payment_method)
|
||||
else
|
||||
invoke_callbacks(:create, :fails)
|
||||
respond_with(@payment_method)
|
||||
end
|
||||
end
|
||||
@@ -31,8 +28,6 @@ module Spree
|
||||
restrict_stripe_account_change
|
||||
force_environment
|
||||
|
||||
invoke_callbacks(:update, :before)
|
||||
|
||||
if @payment_method.type.to_s != payment_method_class
|
||||
@payment_method.update_columns(
|
||||
type: payment_method_class,
|
||||
@@ -42,11 +37,9 @@ module Spree
|
||||
end
|
||||
|
||||
if @payment_method.update(update_params)
|
||||
invoke_callbacks(:update, :after)
|
||||
flash[:success] = Spree.t(:successfully_updated, resource: Spree.t(:payment_method))
|
||||
redirect_to spree.edit_admin_payment_method_path(@payment_method)
|
||||
else
|
||||
invoke_callbacks(:update, :fails)
|
||||
respond_with(@payment_method)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -38,7 +38,6 @@ module Spree
|
||||
end
|
||||
end
|
||||
rescue Paperclip::Errors::NotIdentifiedByImageMagickError
|
||||
invoke_callbacks(:create, :fails)
|
||||
@object.errors.add(:base, t('spree.admin.products.image_upload_error'))
|
||||
respond_with(@object)
|
||||
end
|
||||
@@ -80,7 +79,7 @@ module Spree
|
||||
product_set.collection.each { |p| authorize! :update, p }
|
||||
|
||||
if product_set.save
|
||||
redirect_to main_app.bulk_products_api_products_path(bulk_index_query)
|
||||
redirect_to main_app.bulk_products_api_v0_products_path(bulk_index_query)
|
||||
elsif product_set.errors.present?
|
||||
render json: { errors: product_set.errors }, status: :bad_request
|
||||
else
|
||||
|
||||
@@ -3,8 +3,7 @@ module Spree
|
||||
class ReturnAuthorizationsController < ::Admin::ResourceController
|
||||
belongs_to 'spree/order', find_by: :number
|
||||
|
||||
update.after :associate_inventory_units
|
||||
create.after :associate_inventory_units
|
||||
after_action :associate_inventory_units, only: [:create, :update]
|
||||
|
||||
def fire
|
||||
@return_authorization.public_send("#{params[:e]}!")
|
||||
|
||||
@@ -102,7 +102,6 @@ module Spree
|
||||
|
||||
# handling raise from Admin::ResourceController#destroy
|
||||
def user_destroy_with_orders_error
|
||||
invoke_callbacks(:destroy, :fails)
|
||||
render status: :forbidden, text: Spree.t(:error_user_destroy_with_orders)
|
||||
end
|
||||
|
||||
|
||||
@@ -4,9 +4,9 @@ module Spree
|
||||
module Admin
|
||||
class VariantsController < ::Admin::ResourceController
|
||||
helper 'spree/products'
|
||||
|
||||
belongs_to 'spree/product', find_by: :permalink
|
||||
new_action.before :new_before
|
||||
|
||||
before_action :assign_default_attributes, only: :new
|
||||
|
||||
def index
|
||||
@url_filters = ::ProductFilters.new.extract(request.query_parameters)
|
||||
@@ -84,7 +84,7 @@ module Spree
|
||||
@object.save
|
||||
end
|
||||
|
||||
def new_before
|
||||
def assign_default_attributes
|
||||
@object.attributes = @object.product.master.
|
||||
attributes.except('id', 'created_at', 'deleted_at', 'sku', 'is_master')
|
||||
# Shallow Clone of the default price to populate the price field.
|
||||
|
||||
@@ -6,6 +6,6 @@ module OrderHelper
|
||||
end
|
||||
|
||||
def outstanding_balance_label(order)
|
||||
order.outstanding_balance.negative? ? t(:credit_owed) : t(:balance_due)
|
||||
order.outstanding_balance.label
|
||||
end
|
||||
end
|
||||
|
||||
@@ -29,9 +29,9 @@ module ShopHelper
|
||||
{ name: 'home', title: t(:shopping_tabs_home), show: show_home_tab? },
|
||||
{ name: 'shop', title: t(:shopping_tabs_shop), show: !require_customer? },
|
||||
{ name: 'about', title: t(:shopping_tabs_about), show: true },
|
||||
{ name: 'producers', title: t(:label_producers), show: true },
|
||||
{ name: 'producers', title: t(:shopping_tabs_producers), show: true },
|
||||
{ name: 'contact', title: t(:shopping_tabs_contact), show: true },
|
||||
{ name: 'groups', title: t(:label_groups), show: current_distributor.groups.any? },
|
||||
{ name: 'groups', title: t(:shopping_tabs_groups), show: current_distributor.groups.any? },
|
||||
].select{ |tab| tab[:show] }
|
||||
end
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@ class ProducerMailer < Spree::BaseMailer
|
||||
includes(:option_values, variant: [:product, { option_values: :option_type }]).
|
||||
from_order_cycle(order_cycle).
|
||||
sorted_by_name_and_unit_value.
|
||||
merge(Spree::Product.in_supplier(producer)).
|
||||
merge(Spree::Product.with_deleted.in_supplier(producer)).
|
||||
merge(Spree::Order.by_state('complete'))
|
||||
end
|
||||
|
||||
|
||||
@@ -7,13 +7,28 @@ require 'active_support/concern'
|
||||
module Balance
|
||||
FINALIZED_NON_SUCCESSFUL_STATES = %w(canceled returned).freeze
|
||||
|
||||
# Branches by the OrderBalance abstraction
|
||||
def outstanding_balance
|
||||
OrderBalance.new(self)
|
||||
end
|
||||
|
||||
# This method is the one we're gradually replacing with `#new_outstanding_balance`. Having them
|
||||
# separate enables us to choose which implementation we want depending on the context using
|
||||
# a feature toggle. This avoids inconsistent behavior during that incremental refactoring.
|
||||
#
|
||||
# It is meant to be removed as soon as we get product approval that the new implementation has
|
||||
# been working correctly in production.
|
||||
def old_outstanding_balance
|
||||
total - payment_total
|
||||
end
|
||||
|
||||
# Returns the order balance by considering the total as money owed to the order distributor aka.
|
||||
# the shop, and as a positive balance of said enterprise. If the customer pays it all, they
|
||||
# the shop, and as a positive balance of said enterprise. If the customer pays it all, the
|
||||
# distributor and customer are even.
|
||||
#
|
||||
# Note however, this is meant to be used only in the context of a single order object. When
|
||||
# working with a collection of orders, such an index controller action, please consider using
|
||||
# `app/queries/oustanding_balance.rb` instead so we avoid potential N+1s.
|
||||
# `app/queries/outstanding_balance.rb` instead so we avoid potential N+1s.
|
||||
def new_outstanding_balance
|
||||
if state.in?(FINALIZED_NON_SUCCESSFUL_STATES)
|
||||
-payment_total
|
||||
@@ -22,22 +37,11 @@ module Balance
|
||||
end
|
||||
end
|
||||
|
||||
# This method is the one we're gradually replacing with `#new_outstanding_balance`. Having them
|
||||
# separate enables us to choose which implementation we want depending on the context using
|
||||
# a feature toggle. This avoids incosistent behavior across the app during that incremental
|
||||
# refactoring.
|
||||
#
|
||||
# It is meant to be removed as soon as we get product approval that the new implementation has
|
||||
# been working correctly in production.
|
||||
def outstanding_balance
|
||||
total - payment_total
|
||||
end
|
||||
|
||||
def outstanding_balance?
|
||||
!outstanding_balance.zero?
|
||||
end
|
||||
|
||||
def display_outstanding_balance
|
||||
Spree::Money.new(outstanding_balance, currency: currency)
|
||||
outstanding_balance.display_amount
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,27 +1,31 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class OrderBalance
|
||||
delegate :zero?, :abs, :to_s, :to_f, :to_d, :<, :>, to: :amount
|
||||
|
||||
def initialize(order)
|
||||
@order = order
|
||||
end
|
||||
|
||||
def label
|
||||
to_f.negative? ? I18n.t(:credit_owed) : I18n.t(:balance_due)
|
||||
amount.negative? ? I18n.t(:credit_owed) : I18n.t(:balance_due)
|
||||
end
|
||||
|
||||
def display_amount
|
||||
Spree::Money.new(amount, currency: order.currency)
|
||||
end
|
||||
|
||||
def amount
|
||||
Spree::Money.new(to_f, currency: order.currency)
|
||||
end
|
||||
|
||||
def to_f
|
||||
if customer_balance_enabled?
|
||||
order.new_outstanding_balance
|
||||
else
|
||||
order.outstanding_balance
|
||||
order.old_outstanding_balance
|
||||
end
|
||||
end
|
||||
|
||||
delegate :zero?, to: :to_f
|
||||
def +(other)
|
||||
amount + other.to_f
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
|
||||
@@ -66,7 +66,7 @@ module Spree
|
||||
scope :optional, -> { where(mandatory: false) }
|
||||
scope :charge, -> { where('amount >= 0') }
|
||||
scope :credit, -> { where('amount < 0') }
|
||||
scope :return_authorization, -> { where(source_type: "Spree::ReturnAuthorization") }
|
||||
scope :return_authorization, -> { where(originator_type: "Spree::ReturnAuthorization") }
|
||||
scope :inclusive, -> { where(included: true) }
|
||||
scope :additional, -> { where(included: false) }
|
||||
|
||||
@@ -100,12 +100,14 @@ module Spree
|
||||
# adjustment calculations would not performed on proper values
|
||||
def update!(calculable = nil, force: false)
|
||||
return if immutable? && !force
|
||||
return if originator.blank?
|
||||
|
||||
# Fix for Spree issue #3381
|
||||
# If we attempt to call 'source' before the reload, then source is currently
|
||||
# the order object. After calling a reload, the source is the Shipment.
|
||||
reload
|
||||
originator.update_adjustment(self, calculable || source) if originator.present?
|
||||
amount = originator.compute_amount(calculable || adjustable)
|
||||
|
||||
update_columns(
|
||||
amount: amount,
|
||||
updated_at: Time.zone.now,
|
||||
)
|
||||
end
|
||||
|
||||
def currency
|
||||
|
||||
@@ -28,7 +28,7 @@ module Spree
|
||||
gateway_options = options
|
||||
gateway_options.delete :login if gateway_options.key?(:login) && gateway_options[:login].nil?
|
||||
if gateway_options[:server]
|
||||
ActiveMerchant::Billing::Base.gateway_mode = gateway_options[:server].to_sym
|
||||
ActiveMerchant::Billing::Base.mode = gateway_options[:server].to_sym
|
||||
end
|
||||
@provider ||= provider_class.new(gateway_options)
|
||||
end
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
module Spree
|
||||
class InventoryUnit < ActiveRecord::Base
|
||||
belongs_to :variant, class_name: "Spree::Variant"
|
||||
belongs_to :variant, -> { with_deleted }, class_name: "Spree::Variant"
|
||||
belongs_to :order, class_name: "Spree::Order"
|
||||
belongs_to :shipment, class_name: "Spree::Shipment"
|
||||
belongs_to :return_authorization, class_name: "Spree::ReturnAuthorization",
|
||||
@@ -59,11 +59,6 @@ module Spree
|
||||
variant_id: variant_id)
|
||||
end
|
||||
|
||||
# Remove variant default_scope `deleted_at: nil`
|
||||
def variant
|
||||
Spree::Variant.unscoped { super }
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def allow_ship?
|
||||
|
||||
@@ -4,7 +4,7 @@ module Spree
|
||||
class Price < ActiveRecord::Base
|
||||
acts_as_paranoid without_default_scope: true
|
||||
|
||||
belongs_to :variant, class_name: 'Spree::Variant'
|
||||
belongs_to :variant, -> { with_deleted }, class_name: 'Spree::Variant'
|
||||
|
||||
validate :check_price
|
||||
validates :amount, numericality: { greater_than_or_equal_to: 0 }, allow_nil: true
|
||||
@@ -26,11 +26,6 @@ module Spree
|
||||
self[:amount] = parse_price(price)
|
||||
end
|
||||
|
||||
# Allow prices to access associated soft-deleted variants.
|
||||
def variant
|
||||
Spree::Variant.unscoped { super }
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def check_price
|
||||
|
||||
@@ -64,6 +64,11 @@ module Spree
|
||||
order.shipped_shipments.collect{ |s| s.inventory_units.to_a }.flatten
|
||||
end
|
||||
|
||||
# Used when Adjustment#update! wants to update the related adjustment
|
||||
def compute_amount(*_args)
|
||||
-amount.abs
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def must_have_shipped_units
|
||||
@@ -89,10 +94,13 @@ module Spree
|
||||
Spree::StockMovement.create!(stock_item_id: iu.find_stock_item.id, quantity: 1)
|
||||
end
|
||||
|
||||
credit = Adjustment.new(amount: amount.abs * -1, label: Spree.t(:rma_credit))
|
||||
credit.source = self
|
||||
credit.adjustable = order
|
||||
credit.save
|
||||
Adjustment.create(
|
||||
amount: -amount.abs,
|
||||
label: I18n.t('spree.rma_credit'),
|
||||
order: order,
|
||||
adjustable: order,
|
||||
originator: self
|
||||
)
|
||||
|
||||
order.return if inventory_units.all?(&:returned?)
|
||||
order.update!
|
||||
|
||||
@@ -5,7 +5,7 @@ module Spree
|
||||
acts_as_paranoid
|
||||
|
||||
belongs_to :stock_location, class_name: 'Spree::StockLocation', inverse_of: :stock_items
|
||||
belongs_to :variant, class_name: 'Spree::Variant'
|
||||
belongs_to :variant, -> { with_deleted }, class_name: 'Spree::Variant'
|
||||
has_many :stock_movements
|
||||
|
||||
validates :stock_location, :variant, presence: true
|
||||
@@ -37,10 +37,6 @@ module Spree
|
||||
in_stock? || backorderable?
|
||||
end
|
||||
|
||||
def variant
|
||||
Spree::Variant.unscoped { super }
|
||||
end
|
||||
|
||||
def count_on_hand=(value)
|
||||
self[:count_on_hand] = value
|
||||
end
|
||||
|
||||
@@ -34,7 +34,7 @@ module Spree
|
||||
accepts_nested_attributes_for :images
|
||||
|
||||
has_one :default_price,
|
||||
-> { where currency: Spree::Config[:currency] },
|
||||
-> { with_deleted.where(currency: Spree::Config[:currency]) },
|
||||
class_name: 'Spree::Price',
|
||||
dependent: :destroy
|
||||
has_many :prices,
|
||||
@@ -152,11 +152,6 @@ module Spree
|
||||
select("spree_variants.id"))
|
||||
end
|
||||
|
||||
# Allow variant to access associated soft-deleted prices.
|
||||
def default_price
|
||||
Spree::Price.unscoped { super }
|
||||
end
|
||||
|
||||
def price_with_fees(distributor, order_cycle)
|
||||
price + fees_for(distributor, order_cycle)
|
||||
end
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
class SubscriptionLineItem < ActiveRecord::Base
|
||||
belongs_to :subscription, inverse_of: :subscription_line_items
|
||||
belongs_to :variant, class_name: 'Spree::Variant'
|
||||
belongs_to :variant, -> { with_deleted }, class_name: 'Spree::Variant'
|
||||
|
||||
validates :subscription, presence: true
|
||||
validates :variant, presence: true
|
||||
@@ -12,11 +12,6 @@ class SubscriptionLineItem < ActiveRecord::Base
|
||||
(price_estimate || 0) * (quantity || 0)
|
||||
end
|
||||
|
||||
# Ensure SubscriptionLineItem always has access to soft-deleted Variant attribute
|
||||
def variant
|
||||
Spree::Variant.unscoped { super }
|
||||
end
|
||||
|
||||
# Used to calculators to estimate fees
|
||||
alias_method :amount, :total_estimate
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ module Api
|
||||
if OpenFoodNetwork::FeatureToggle.enabled?(:customer_balance, object.user)
|
||||
-object.balance_value
|
||||
else
|
||||
object.outstanding_balance
|
||||
object.old_outstanding_balance
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ class Api::VariantSerializer < ActiveModel::Serializer
|
||||
end
|
||||
|
||||
def unit_price_price
|
||||
price_with_fees / unit_price.denominator
|
||||
price_with_fees / (unit_price.denominator || 1)
|
||||
end
|
||||
|
||||
def unit_price_unit
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
class ActionCallbacks
|
||||
attr_reader :before_methods
|
||||
attr_reader :after_methods
|
||||
attr_reader :fails_methods
|
||||
|
||||
def initialize
|
||||
@before_methods = []
|
||||
@after_methods = []
|
||||
@fails_methods = []
|
||||
end
|
||||
|
||||
def before(method)
|
||||
@before_methods << method
|
||||
end
|
||||
|
||||
def after(method)
|
||||
@after_methods << method
|
||||
end
|
||||
|
||||
def fails(method)
|
||||
@fails_methods << method
|
||||
end
|
||||
end
|
||||
@@ -8,7 +8,7 @@
|
||||
%tr
|
||||
%th.producer=t('admin.producer')
|
||||
%th.product=t('admin.product')
|
||||
%th.variant=t('(admin.variant')
|
||||
%th.variant=t('admin.variant')
|
||||
%th.add=t('admin.variant_overrides.index.add')
|
||||
%tbody{ ng: { repeat: 'product in filteredProducts | limitTo:productLimit' } }
|
||||
%tr{ id: "v_{{variant.id}}", ng: { repeat: 'variant in product.variants | inventoryVariants:hub_id:views' } }
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
.field
|
||||
= label_tag nil, t(:shipping_method)
|
||||
= select_tag("shipping_method_id",
|
||||
options_for_select(Spree::ShippingMethod.managed_by(spree_current_user).collect {|s| [t("spree.shipping_method.#{s.name}"), s.id]}),
|
||||
options_for_select(Spree::ShippingMethod.managed_by(spree_current_user).collect {|s| [t("spree.shipping_method_names.#{s.name}"), s.id]}),
|
||||
{include_blank: true, class: 'select2', 'ng-model' => 'shipping_method_id'})
|
||||
.field-block.alpha.eight.columns
|
||||
= label_tag nil, t(:distributors)
|
||||
|
||||
@@ -55,13 +55,13 @@
|
||||
- if feature? :unit_price, spree_current_user
|
||||
.four.columns{ ng: { app: 'ofn.admin'}}
|
||||
= f.field_container :unit_price do
|
||||
= f.label :unit_price, t(".unit_price")
|
||||
%question-mark-with-tooltip{"question-mark-with-tooltip" => "_",
|
||||
%div{style: "display: flex"}
|
||||
= f.label :unit_price, t(".unit_price")
|
||||
%question-mark-with-tooltip{"question-mark-with-tooltip" => "_",
|
||||
"question-mark-with-tooltip-append-to-body" => "true",
|
||||
"question-mark-with-tooltip-placement" => "top",
|
||||
"question-mark-with-tooltip-animation" => true,
|
||||
key: "'js.admin.unit_price_tooltip'"}
|
||||
%br/
|
||||
= f.text_field :price, {"class" => 'fullwidth', "disabled" => true, "ng-model" => "unit_price"}
|
||||
%div{style: "color: black"}
|
||||
= t(".unit_price_legend")
|
||||
|
||||
@@ -7,8 +7,8 @@
|
||||
}
|
||||
Spree.routes = <%== {
|
||||
:variants_search => spree.admin_search_variants_path(:format => 'json'),
|
||||
:taxons_search => main_app.api_taxons_path(:format => 'json'),
|
||||
:orders_api => main_app.api_orders_path,
|
||||
:states_search => main_app.api_states_path(:format => 'json')
|
||||
:taxons_search => main_app.api_v0_taxons_path(:format => 'json'),
|
||||
:orders_api => main_app.api_v0_orders_path,
|
||||
:states_search => main_app.api_v0_states_path(:format => 'json')
|
||||
}.to_json %>;
|
||||
</script>
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
= label_tag nil, t("spree.tree")
|
||||
%br/
|
||||
:javascript
|
||||
Spree.routes.taxonomy_taxons_path = "#{main_app.api_taxonomy_taxons_path(@taxonomy)}";
|
||||
Spree.routes.taxonomy_taxons_path = "#{main_app.api_v0_taxonomy_taxons_path(@taxonomy)}";
|
||||
Spree.routes.admin_taxonomy_taxons_path = "#{spree.admin_taxonomy_taxons_path(@taxonomy)}";
|
||||
#taxonomy_tree.tree
|
||||
#progress{style: "display:none;"}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user