spree_api 2.2.1 → 2.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +7 -2
- data/app/controllers/spree/api/addresses_controller.rb +1 -1
- data/app/controllers/spree/api/base_controller.rb +5 -1
- data/app/controllers/spree/api/checkouts_controller.rb +4 -0
- data/app/controllers/spree/api/line_items_controller.rb +1 -1
- data/app/controllers/spree/api/orders_controller.rb +7 -1
- data/app/controllers/spree/api/payments_controller.rb +1 -1
- data/app/controllers/spree/api/return_authorizations_controller.rb +1 -1
- data/app/controllers/spree/api/shipments_controller.rb +22 -6
- data/app/helpers/spree/api/api_helpers.rb +3 -3
- data/app/views/spree/api/orders/order.v1.rabl +1 -0
- data/config/routes.rb +43 -29
- data/lib/spree/api/engine.rb +5 -2
- data/spec/controllers/spree/api/checkouts_controller_spec.rb +2 -1
- data/spec/controllers/spree/api/orders_controller_spec.rb +15 -0
- data/spec/controllers/spree/api/products_controller_spec.rb +12 -1
- data/spec/controllers/spree/api/shipments_controller_spec.rb +17 -6
- data/spec/controllers/spree/api/states_controller_spec.rb +6 -0
- data/spec/requests/rabl_cache_spec.rb +5 -2
- metadata +5 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 898408b377a8e9d880bf8eb6ba24b5e732df26fc
|
4
|
+
data.tar.gz: 24fbb8abc05caf4c6a2f7a07c309690d44d0e3a2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 348fa6f5b63439eeaacda5659931402eefe300c0eac4d9922d0b2800ada8baf81a40c6015c757cb331c47c8aaac8b2c5d84ffba38a0a26aee87ccb8e5a4444e6
|
7
|
+
data.tar.gz: cdaf932f2f3a76ab20e43d6b99bd49a9c2d41b58b525a72732187c7250296aa5f9835b78f1a49f665d33a903d4aa4f7d1ac4b8462dcceff39de2c4e243dd7895
|
data/CHANGELOG.md
CHANGED
@@ -145,8 +145,12 @@ module Spree
|
|
145
145
|
scope
|
146
146
|
end
|
147
147
|
|
148
|
+
def order_id
|
149
|
+
params[:order_id] || params[:checkout_id] || params[:order_number]
|
150
|
+
end
|
151
|
+
|
148
152
|
def authorize_for_order
|
149
|
-
@order = Spree::Order.find_by(number:
|
153
|
+
@order = Spree::Order.find_by(number: order_id)
|
150
154
|
authorize! :read, @order, order_token
|
151
155
|
end
|
152
156
|
end
|
@@ -28,6 +28,7 @@ module Spree
|
|
28
28
|
|
29
29
|
def empty
|
30
30
|
find_order
|
31
|
+
authorize! :update, @order, order_token
|
31
32
|
@order.empty!
|
32
33
|
@order.update!
|
33
34
|
render text: nil, status: 200
|
@@ -41,6 +42,7 @@ module Spree
|
|
41
42
|
|
42
43
|
def show
|
43
44
|
find_order
|
45
|
+
authorize! :show, @order, order_token
|
44
46
|
method = "before_#{@order.state}"
|
45
47
|
send(method) if respond_to?(method, true)
|
46
48
|
respond_with(@order)
|
@@ -48,6 +50,7 @@ module Spree
|
|
48
50
|
|
49
51
|
def update
|
50
52
|
find_order(true)
|
53
|
+
authorize! :update, @order, order_token
|
51
54
|
# Parsing line items through as an update_attributes call in the API will result in
|
52
55
|
# many line items for the same variant_id being created. We must be smarter about this,
|
53
56
|
# hence the use of the update_line_items method, defined within order_decorator.rb.
|
@@ -74,6 +77,7 @@ module Spree
|
|
74
77
|
|
75
78
|
def apply_coupon_code
|
76
79
|
find_order
|
80
|
+
authorize! :update, @order, order_token
|
77
81
|
@order.coupon_code = params[:coupon_code]
|
78
82
|
@handler = PromotionHandler::Coupon.new(@order).apply
|
79
83
|
status = @handler.successful? ? 200 : 422
|
@@ -138,13 +142,15 @@ module Spree
|
|
138
142
|
|
139
143
|
def find_order(lock = false)
|
140
144
|
@order = Spree::Order.lock(lock).find_by!(number: params[:id])
|
141
|
-
authorize! :update, @order, order_token
|
142
145
|
end
|
143
146
|
|
144
147
|
def before_delivery
|
145
148
|
@order.create_proposed_shipments
|
146
149
|
end
|
147
150
|
|
151
|
+
def order_id
|
152
|
+
super || params[:id]
|
153
|
+
end
|
148
154
|
end
|
149
155
|
end
|
150
156
|
end
|
@@ -6,6 +6,11 @@ module Spree
|
|
6
6
|
before_filter :find_and_update_shipment, only: [:ship, :ready, :add, :remove]
|
7
7
|
|
8
8
|
def create
|
9
|
+
# TODO Can remove conditional here once deprecated #find_order is removed.
|
10
|
+
unless @order.present?
|
11
|
+
@order = Spree::Order.find_by!(number: params[:shipment][:order_id])
|
12
|
+
authorize! :read, @order
|
13
|
+
end
|
9
14
|
authorize! :create, Shipment
|
10
15
|
variant = Spree::Variant.find(params[:variant_id])
|
11
16
|
quantity = params[:quantity].to_i
|
@@ -19,7 +24,11 @@ module Spree
|
|
19
24
|
end
|
20
25
|
|
21
26
|
def update
|
22
|
-
|
27
|
+
if @order.present?
|
28
|
+
@shipment = @order.shipments.accessible_by(current_ability, :update).find_by!(number: params[:id])
|
29
|
+
else
|
30
|
+
@shipment = Spree::Shipment.accessible_by(current_ability, :update).readonly(false).find_by!(number: params[:id])
|
31
|
+
end
|
23
32
|
|
24
33
|
unlock = params[:shipment].delete(:unlock)
|
25
34
|
|
@@ -59,7 +68,7 @@ module Spree
|
|
59
68
|
variant = Spree::Variant.find(params[:variant_id])
|
60
69
|
quantity = params[:quantity].to_i
|
61
70
|
|
62
|
-
@order.contents.add(variant, quantity, nil, @shipment)
|
71
|
+
@shipment.order.contents.add(variant, quantity, nil, @shipment)
|
63
72
|
|
64
73
|
respond_with(@shipment, default_template: :show)
|
65
74
|
end
|
@@ -68,7 +77,7 @@ module Spree
|
|
68
77
|
variant = Spree::Variant.find(params[:variant_id])
|
69
78
|
quantity = params[:quantity].to_i
|
70
79
|
|
71
|
-
@order.contents.remove(variant, quantity, @shipment)
|
80
|
+
@shipment.order.contents.remove(variant, quantity, @shipment)
|
72
81
|
@shipment.reload if @shipment.persisted?
|
73
82
|
respond_with(@shipment, default_template: :show)
|
74
83
|
end
|
@@ -76,12 +85,19 @@ module Spree
|
|
76
85
|
private
|
77
86
|
|
78
87
|
def find_order
|
79
|
-
|
80
|
-
|
88
|
+
if params[:order_id].present?
|
89
|
+
ActiveSupport::Deprecation.warn "Spree::Api::ShipmentsController#find_order is deprecated and will be removed from Spree 2.3.x, access shipments directly without being nested to orders route instead.", caller
|
90
|
+
@order = Spree::Order.find_by!(number: params[:order_id])
|
91
|
+
authorize! :read, @order
|
92
|
+
end
|
81
93
|
end
|
82
94
|
|
83
95
|
def find_and_update_shipment
|
84
|
-
|
96
|
+
if @order.present?
|
97
|
+
@shipment = @order.shipments.accessible_by(current_ability, :update).find_by!(number: params[:id])
|
98
|
+
else
|
99
|
+
@shipment = Spree::Shipment.accessible_by(current_ability, :update).readonly(false).find_by!(number: params[:id])
|
100
|
+
end
|
85
101
|
@shipment.update_attributes(shipment_params)
|
86
102
|
@shipment.reload
|
87
103
|
end
|
@@ -48,7 +48,7 @@ module Spree
|
|
48
48
|
@@product_attributes = [
|
49
49
|
:id, :name, :description, :price, :display_price, :available_on,
|
50
50
|
:slug, :meta_description, :meta_keywords, :shipping_category_id,
|
51
|
-
:taxon_ids
|
51
|
+
:taxon_ids, :total_on_hand
|
52
52
|
]
|
53
53
|
|
54
54
|
@@product_property_attributes = [
|
@@ -112,7 +112,7 @@ module Spree
|
|
112
112
|
@@address_attributes = [
|
113
113
|
:id, :firstname, :lastname, :full_name, :address1, :address2, :city,
|
114
114
|
:zipcode, :phone, :company, :alternative_phone, :country_id, :state_id,
|
115
|
-
:state_name
|
115
|
+
:state_name, :state_text
|
116
116
|
]
|
117
117
|
|
118
118
|
@@country_attributes = [:id, :iso_name, :iso, :iso3, :name, :numcode]
|
@@ -126,7 +126,7 @@ module Spree
|
|
126
126
|
]
|
127
127
|
|
128
128
|
@@creditcard_attributes = [
|
129
|
-
:id, :month, :year, :cc_type, :last_digits, :
|
129
|
+
:id, :month, :year, :cc_type, :last_digits, :name,
|
130
130
|
:gateway_customer_profile_id, :gateway_payment_profile_id
|
131
131
|
]
|
132
132
|
|
@@ -4,5 +4,6 @@ node(:display_item_total) { |o| o.display_item_total.to_s }
|
|
4
4
|
node(:total_quantity) { |o| o.line_items.sum(:quantity) }
|
5
5
|
node(:display_total) { |o| o.display_total.to_s }
|
6
6
|
node(:display_ship_total) { |o| o.display_ship_total }
|
7
|
+
node(:display_tax_total) { |o| o.display_tax_total }
|
7
8
|
node(:token) { |o| o.token }
|
8
9
|
node(:checkout_steps) { |o| o.checkout_steps }
|
data/config/routes.rb
CHANGED
@@ -15,33 +15,7 @@ Spree::Core::Engine.add_routes do
|
|
15
15
|
resources :product_properties
|
16
16
|
end
|
17
17
|
|
18
|
-
|
19
|
-
member do
|
20
|
-
put :next
|
21
|
-
put :advance
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
resources :variants, :only => [:index, :show] do
|
26
|
-
resources :images
|
27
|
-
end
|
28
|
-
|
29
|
-
resources :option_types do
|
30
|
-
resources :option_values
|
31
|
-
end
|
32
|
-
|
33
|
-
get '/orders/mine', :to => 'orders#mine', :as => 'my_orders'
|
34
|
-
|
35
|
-
resources :orders do
|
36
|
-
resources :addresses, :only => [:show, :update]
|
37
|
-
|
38
|
-
resources :return_authorizations do
|
39
|
-
member do
|
40
|
-
put :add
|
41
|
-
put :cancel
|
42
|
-
put :receive
|
43
|
-
end
|
44
|
-
end
|
18
|
+
order_routes = lambda {
|
45
19
|
member do
|
46
20
|
put :cancel
|
47
21
|
put :empty
|
@@ -58,7 +32,7 @@ Spree::Core::Engine.add_routes do
|
|
58
32
|
put :credit
|
59
33
|
end
|
60
34
|
end
|
61
|
-
|
35
|
+
# TODO Remove after shipment api is no longer handled through order nesting.
|
62
36
|
resources :shipments, :only => [:create, :update] do
|
63
37
|
member do
|
64
38
|
put :ready
|
@@ -67,10 +41,50 @@ Spree::Core::Engine.add_routes do
|
|
67
41
|
put :remove
|
68
42
|
end
|
69
43
|
end
|
44
|
+
|
45
|
+
resources :addresses, :only => [:show, :update]
|
46
|
+
|
47
|
+
resources :return_authorizations do
|
48
|
+
member do
|
49
|
+
put :add
|
50
|
+
put :cancel
|
51
|
+
put :receive
|
52
|
+
end
|
53
|
+
end
|
54
|
+
}
|
55
|
+
|
56
|
+
resources :checkouts do
|
57
|
+
member do
|
58
|
+
put :next
|
59
|
+
put :advance
|
60
|
+
end
|
61
|
+
order_routes.call
|
70
62
|
end
|
71
63
|
|
64
|
+
resources :variants, :only => [:index, :show] do
|
65
|
+
resources :images
|
66
|
+
end
|
67
|
+
|
68
|
+
resources :option_types do
|
69
|
+
resources :option_values
|
70
|
+
end
|
71
|
+
|
72
|
+
get '/orders/mine', :to => 'orders#mine', :as => 'my_orders'
|
73
|
+
|
74
|
+
resources :orders, &order_routes
|
75
|
+
|
72
76
|
resources :zones
|
73
|
-
resources :countries, :only => [:index, :show]
|
77
|
+
resources :countries, :only => [:index, :show] do
|
78
|
+
resources :states, :only => [:index, :show]
|
79
|
+
end
|
80
|
+
resources :shipments, :only => [:create, :update] do
|
81
|
+
member do
|
82
|
+
put :ready
|
83
|
+
put :ship
|
84
|
+
put :add
|
85
|
+
put :remove
|
86
|
+
end
|
87
|
+
end
|
74
88
|
resources :states, :only => [:index, :show]
|
75
89
|
|
76
90
|
resources :taxonomies do
|
data/lib/spree/api/engine.rb
CHANGED
@@ -9,6 +9,11 @@ module Spree
|
|
9
9
|
Rabl.configure do |config|
|
10
10
|
config.include_json_root = false
|
11
11
|
config.include_child_root = false
|
12
|
+
|
13
|
+
# Motivation here it make it call as_json when rendering. Otherwise it
|
14
|
+
# would fall to JSON and get errors like the one described here https://github.com/spree/spree/issues/4589
|
15
|
+
# where Float::INFINITY would resolve to Infinite (invalid json) istead of null
|
16
|
+
config.json_engine = ActiveSupport::JSON
|
12
17
|
end
|
13
18
|
|
14
19
|
config.view_versions = [1]
|
@@ -31,5 +36,3 @@ module Spree
|
|
31
36
|
end
|
32
37
|
end
|
33
38
|
end
|
34
|
-
|
35
|
-
|
@@ -173,7 +173,8 @@ module Spree
|
|
173
173
|
order.update_column(:state, "payment")
|
174
174
|
api_put :update, :id => order.to_param, :order_token => order.token,
|
175
175
|
:order => { :payments_attributes => [{ :payment_method_id => @payment_method.id.to_s }],
|
176
|
-
:payment_source => { @payment_method.id.to_s => { } } }
|
176
|
+
:payment_source => { @payment_method.id.to_s => { name: "Spree" } } }
|
177
|
+
|
177
178
|
response.status.should == 422
|
178
179
|
cc_errors = json_response['errors']['payments.Credit Card']
|
179
180
|
cc_errors.should include("Number can't be blank")
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'spec_helper'
|
2
|
+
require 'spree/testing_support/bar_ability'
|
2
3
|
|
3
4
|
module Spree
|
4
5
|
describe Api::OrdersController do
|
@@ -116,6 +117,20 @@ module Spree
|
|
116
117
|
response.status.should == 200
|
117
118
|
end
|
118
119
|
|
120
|
+
context "with BarAbility registered" do
|
121
|
+
before { Spree::Ability.register_ability(::BarAbility) }
|
122
|
+
after { Spree::Ability.remove_ability(::BarAbility) }
|
123
|
+
|
124
|
+
it "can view an order" do
|
125
|
+
user = mock_model(Spree::LegacyUser)
|
126
|
+
user.stub(:has_spree_role?).with('bar').and_return(true)
|
127
|
+
user.stub(:has_spree_role?).with('admin').and_return(false)
|
128
|
+
controller.stub try_spree_current_user: user
|
129
|
+
api_get :show, :id => order.to_param
|
130
|
+
response.status.should == 200
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
119
134
|
it "cannot cancel an order that doesn't belong to them" do
|
120
135
|
order.update_attribute(:completed_at, Time.now)
|
121
136
|
order.update_attribute(:shipment_state, "ready")
|
@@ -7,7 +7,7 @@ module Spree
|
|
7
7
|
|
8
8
|
let!(:product) { create(:product) }
|
9
9
|
let!(:inactive_product) { create(:product, :available_on => Time.now.tomorrow, :name => "inactive") }
|
10
|
-
let(:base_attributes) {
|
10
|
+
let(:base_attributes) { Api::ApiHelpers.product_attributes }
|
11
11
|
let(:show_attributes) { base_attributes.dup.push(:has_variants) }
|
12
12
|
let(:new_attributes) { base_attributes }
|
13
13
|
|
@@ -166,6 +166,17 @@ module Spree
|
|
166
166
|
:property_name])
|
167
167
|
end
|
168
168
|
|
169
|
+
context "tracking is disabled" do
|
170
|
+
before { Config.track_inventory_levels = false }
|
171
|
+
|
172
|
+
it "still displays valid json with total on hand" do
|
173
|
+
api_get :show, :id => product.to_param
|
174
|
+
expect(response).to be_ok
|
175
|
+
expect(json_response[:total_on_hand]).to eq nil
|
176
|
+
end
|
177
|
+
|
178
|
+
after { Config.track_inventory_levels = true }
|
179
|
+
end
|
169
180
|
|
170
181
|
context "finds a product by slug first then by id" do
|
171
182
|
let!(:other_product) { create(:product, :slug => "these-are-not-the-droids-you-are-looking-for") }
|
@@ -9,17 +9,17 @@ describe Spree::Api::ShipmentsController do
|
|
9
9
|
stub_authentication!
|
10
10
|
end
|
11
11
|
|
12
|
-
let!(:resource_scoping) { { :
|
12
|
+
let!(:resource_scoping) { { id: shipment.to_param, shipment: { order_id: shipment.order.to_param } } }
|
13
13
|
|
14
14
|
context "as a non-admin" do
|
15
15
|
it "cannot make a shipment ready" do
|
16
16
|
api_put :ready
|
17
|
-
|
17
|
+
assert_not_found!
|
18
18
|
end
|
19
19
|
|
20
20
|
it "cannot make a shipment shipped" do
|
21
21
|
api_put :ship
|
22
|
-
|
22
|
+
assert_not_found!
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|
@@ -32,7 +32,7 @@ describe Spree::Api::ShipmentsController do
|
|
32
32
|
it 'can create a new shipment' do
|
33
33
|
params = {
|
34
34
|
variant_id: stock_location.stock_items.first.variant.to_param,
|
35
|
-
order_id: order.number,
|
35
|
+
shipment: { order_id: order.number },
|
36
36
|
stock_location_id: stock_location.to_param,
|
37
37
|
}
|
38
38
|
|
@@ -70,7 +70,7 @@ describe Spree::Api::ShipmentsController do
|
|
70
70
|
|
71
71
|
context 'for completed shipments' do
|
72
72
|
let(:order) { create :completed_order_with_totals }
|
73
|
-
let!(:resource_scoping) { { :
|
73
|
+
let!(:resource_scoping) { { id: order.shipments.first.to_param, shipment: { order_id: order.to_param } } }
|
74
74
|
|
75
75
|
it 'adds a variant to a shipment' do
|
76
76
|
api_put :add, { variant_id: variant.to_param, quantity: 2 }
|
@@ -100,10 +100,21 @@ describe Spree::Api::ShipmentsController do
|
|
100
100
|
|
101
101
|
it "can transition a shipment from ready to ship" do
|
102
102
|
shipment.reload
|
103
|
-
api_put :ship, :
|
103
|
+
api_put :ship, id: shipment.to_param, shipment: { tracking: "123123", order_id: shipment.order.to_param }
|
104
104
|
json_response.should have_attributes(attributes)
|
105
105
|
json_response["state"].should == "shipped"
|
106
106
|
end
|
107
|
+
|
108
|
+
context 'DEPRECATED:' do
|
109
|
+
it "can transition a shipment from ready to ship" do
|
110
|
+
ActiveSupport::Deprecation.should_receive(:warn).once
|
111
|
+
shipment.reload
|
112
|
+
api_put :ship, order_id: shipment.order.to_param, id: shipment.to_param, shipment: { tracking: "123123" }
|
113
|
+
json_response.should have_attributes(attributes)
|
114
|
+
json_response["state"].should == "shipped"
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
107
118
|
end
|
108
119
|
end
|
109
120
|
end
|
@@ -17,6 +17,12 @@ module Spree
|
|
17
17
|
json_response['states'].first['name'].should eq(state.name)
|
18
18
|
end
|
19
19
|
|
20
|
+
it "gets all the states for a particular country" do
|
21
|
+
api_get :index, :country_id => state.country.id
|
22
|
+
json_response["states"].first.should have_attributes(attributes)
|
23
|
+
json_response['states'].first['name'].should eq(state.name)
|
24
|
+
end
|
25
|
+
|
20
26
|
context "pagination" do
|
21
27
|
before do
|
22
28
|
State.should_receive(:accessible_by).and_return(@scope = double)
|
@@ -14,7 +14,10 @@ describe "Rabl Cache", :caching => true do
|
|
14
14
|
response.status.should == 200
|
15
15
|
|
16
16
|
# Make sure we get a non master variant
|
17
|
-
variant_a = JSON.parse(response.body)['variants'].
|
17
|
+
variant_a = JSON.parse(response.body)['variants'].select do |v|
|
18
|
+
!v['is_master']
|
19
|
+
end.first
|
20
|
+
|
18
21
|
variant_a['is_master'].should be_false
|
19
22
|
variant_a['stock_items'].should_not be_nil
|
20
23
|
|
@@ -26,4 +29,4 @@ describe "Rabl Cache", :caching => true do
|
|
26
29
|
variant_a['id'].should == variant_b['id']
|
27
30
|
variant_b['stock_items'].should be_nil
|
28
31
|
end
|
29
|
-
end
|
32
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: spree_api
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.2.
|
4
|
+
version: 2.2.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ryan Bigg
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-05-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: spree_core
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - '='
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 2.2.
|
19
|
+
version: 2.2.2
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - '='
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 2.2.
|
26
|
+
version: 2.2.2
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rabl
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -254,7 +254,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
254
254
|
version: '0'
|
255
255
|
requirements: []
|
256
256
|
rubyforge_project:
|
257
|
-
rubygems_version: 2.2.
|
257
|
+
rubygems_version: 2.2.0
|
258
258
|
signing_key:
|
259
259
|
specification_version: 4
|
260
260
|
summary: Spree's API
|