spree_api 2.1.12 → 2.2.0
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 +51 -1
- data/app/controllers/spree/api/addresses_controller.rb +25 -10
- data/app/controllers/spree/api/base_controller.rb +18 -29
- data/app/controllers/spree/api/checkouts_controller.rb +23 -29
- data/app/controllers/spree/api/classifications_controller.rb +18 -0
- data/app/controllers/spree/api/line_items_controller.rb +13 -1
- data/app/controllers/spree/api/option_types_controller.rb +2 -2
- data/app/controllers/spree/api/option_values_controller.rb +1 -1
- data/app/controllers/spree/api/orders_controller.rb +12 -34
- data/app/controllers/spree/api/products_controller.rb +22 -23
- data/app/controllers/spree/api/taxons_controller.rb +9 -0
- data/app/controllers/spree/api/variants_controller.rb +1 -1
- data/app/helpers/spree/api/api_helpers.rb +5 -3
- data/app/models/spree/order_decorator.rb +2 -11
- data/app/views/spree/api/line_items/show.v1.rabl +4 -0
- data/app/views/spree/api/orders/order.v1.rabl +0 -1
- data/app/views/spree/api/products/show.v1.rabl +7 -10
- data/app/views/spree/api/promotions/handler.v1.rabl +4 -0
- data/app/views/spree/api/variants/index.v1.rabl +1 -1
- data/app/views/spree/api/variants/show.v1.rabl +2 -3
- data/app/views/spree/api/variants/variant.v1.rabl +2 -0
- data/app/views/spree/api/variants/{big_variant.v1.rabl → variant_full.v1.rabl} +0 -0
- data/config/routes.rb +6 -4
- data/lib/spree/api/controller_setup.rb +0 -1
- data/lib/spree/api/testing_support/helpers.rb +1 -0
- data/spec/controllers/spree/api/addresses_controller_spec.rb +57 -31
- data/spec/controllers/spree/api/base_controller_spec.rb +0 -36
- data/spec/controllers/spree/api/checkouts_controller_spec.rb +8 -41
- data/spec/controllers/spree/api/classifications_controller_spec.rb +38 -0
- data/spec/controllers/spree/api/line_items_controller_spec.rb +10 -21
- data/spec/controllers/spree/api/option_values_controller_spec.rb +0 -7
- data/spec/controllers/spree/api/orders_controller_spec.rb +24 -121
- data/spec/controllers/spree/api/products_controller_spec.rb +26 -48
- data/spec/controllers/spree/api/promotion_application_spec.rb +48 -0
- data/spec/controllers/spree/api/shipments_controller_spec.rb +1 -22
- data/spec/controllers/spree/api/unauthenticated_products_controller_spec.rb +1 -1
- data/spec/controllers/spree/api/users_controller_spec.rb +3 -2
- data/spec/controllers/spree/api/variants_controller_spec.rb +13 -7
- data/spec/models/spree/order_spec.rb +3 -28
- metadata +12 -7
- data/app/views/spree/api/orders/apply_coupon_code.v1.rabl +0 -7
@@ -10,12 +10,15 @@ module Spree
|
|
10
10
|
end
|
11
11
|
|
12
12
|
@products = @products.distinct.page(params[:page]).per(params[:per_page])
|
13
|
+
expires_in 15.minutes, :public => true
|
14
|
+
headers['Surrogate-Control'] = "max-age=#{15.minutes}"
|
13
15
|
end
|
14
16
|
|
15
17
|
def show
|
16
18
|
@product = find_product(params[:id])
|
17
|
-
expires_in
|
18
|
-
|
19
|
+
expires_in 15.minutes, :public => true
|
20
|
+
headers['Surrogate-Control'] = "max-age=#{15.minutes}"
|
21
|
+
headers['Surrogate-Key'] = "product_id=1"
|
19
22
|
end
|
20
23
|
|
21
24
|
# Takes besides the products attributes either an array of variants or
|
@@ -56,30 +59,25 @@ module Spree
|
|
56
59
|
params[:product][:available_on] ||= Time.now
|
57
60
|
set_up_shipping_category
|
58
61
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
end
|
66
|
-
|
67
|
-
option_types_params.each do |name|
|
68
|
-
option_type = OptionType.where(name: name).first_or_initialize do |option_type|
|
69
|
-
option_type.presentation = name
|
70
|
-
option_type.save!
|
71
|
-
end
|
62
|
+
@product = Product.new(product_params)
|
63
|
+
if @product.save
|
64
|
+
variants_params.each do |variant_attribute|
|
65
|
+
# make sure the product is assigned before the options=
|
66
|
+
@product.variants.create({ product: @product }.merge(variant_attribute))
|
67
|
+
end
|
72
68
|
|
73
|
-
|
69
|
+
option_types_params.each do |name|
|
70
|
+
option_type = OptionType.where(name: name).first_or_initialize do |option_type|
|
71
|
+
option_type.presentation = name
|
72
|
+
option_type.save!
|
74
73
|
end
|
75
74
|
|
76
|
-
|
77
|
-
else
|
78
|
-
invalid_resource!(@product)
|
75
|
+
@product.option_types << option_type unless @product.option_types.include?(option_type)
|
79
76
|
end
|
80
|
-
|
81
|
-
@product
|
82
|
-
|
77
|
+
|
78
|
+
respond_with(@product, :status => 201, :default_template => :show)
|
79
|
+
else
|
80
|
+
invalid_resource!(@product)
|
83
81
|
end
|
84
82
|
end
|
85
83
|
|
@@ -116,7 +114,8 @@ module Spree
|
|
116
114
|
def destroy
|
117
115
|
@product = find_product(params[:id])
|
118
116
|
authorize! :destroy, @product
|
119
|
-
@product.
|
117
|
+
@product.update_attribute(:deleted_at, Time.now)
|
118
|
+
@product.variants_including_master.update_all(:deleted_at => Time.now)
|
120
119
|
respond_with(@product, :status => 204)
|
121
120
|
end
|
122
121
|
|
@@ -60,6 +60,15 @@ module Spree
|
|
60
60
|
respond_with(taxon, status: 204)
|
61
61
|
end
|
62
62
|
|
63
|
+
def products
|
64
|
+
# Returns the products sorted by their position with the classification
|
65
|
+
# Products#index does not do the sorting.
|
66
|
+
taxon = Spree::Taxon.find(params[:id])
|
67
|
+
@products = taxon.products.ransack(params[:q]).result
|
68
|
+
@products = @products.page(params[:page]).per(500 || params[:per_page])
|
69
|
+
render "spree/api/products/index"
|
70
|
+
end
|
71
|
+
|
63
72
|
private
|
64
73
|
|
65
74
|
def taxonomy
|
@@ -46,7 +46,7 @@ module Spree
|
|
46
46
|
private
|
47
47
|
|
48
48
|
def product
|
49
|
-
@product ||= Spree::Product.accessible_by(current_ability, :read).
|
49
|
+
@product ||= Spree::Product.accessible_by(current_ability, :read).friendly.find(params[:product_id]) if params[:product_id]
|
50
50
|
end
|
51
51
|
|
52
52
|
def scope
|
@@ -40,12 +40,14 @@ module Spree
|
|
40
40
|
# Permalinks presence is validated, but are really automatically generated
|
41
41
|
# Therefore we shouldn't tell API clients that they MUST send one through
|
42
42
|
required_fields.map!(&:to_s).delete("permalink")
|
43
|
+
# Do not require slugs, either
|
44
|
+
required_fields.delete("slug")
|
43
45
|
required_fields
|
44
46
|
end
|
45
47
|
|
46
48
|
@@product_attributes = [
|
47
49
|
:id, :name, :description, :price, :display_price, :available_on,
|
48
|
-
:
|
50
|
+
:slug, :meta_description, :meta_keywords, :shipping_category_id,
|
49
51
|
:taxon_ids
|
50
52
|
]
|
51
53
|
|
@@ -55,7 +57,7 @@ module Spree
|
|
55
57
|
|
56
58
|
@@variant_attributes = [
|
57
59
|
:id, :name, :sku, :price, :weight, :height, :width, :depth, :is_master,
|
58
|
-
:cost_price, :
|
60
|
+
:cost_price, :slug, :description, :track_inventory
|
59
61
|
]
|
60
62
|
|
61
63
|
@@image_attributes = [
|
@@ -73,7 +75,7 @@ module Spree
|
|
73
75
|
:user_id, :created_at, :updated_at, :completed_at, :payment_total,
|
74
76
|
:shipment_state, :payment_state, :email, :special_instructions, :channel,
|
75
77
|
:included_tax_total, :additional_tax_total, :display_included_tax_total,
|
76
|
-
:display_additional_tax_total
|
78
|
+
:display_additional_tax_total
|
77
79
|
]
|
78
80
|
|
79
81
|
@@line_item_attributes = [:id, :quantity, :price, :variant_id]
|
@@ -15,9 +15,7 @@ Spree::Order.class_eval do
|
|
15
15
|
order.create_payments_from_api params.delete(:payments_attributes) || []
|
16
16
|
order.complete_from_api params.delete(:completed_at)
|
17
17
|
|
18
|
-
destroy_automatic_taxes_on_import(order, params)
|
19
18
|
order.update_attributes!(params)
|
20
|
-
|
21
19
|
order.reload
|
22
20
|
rescue Exception => e
|
23
21
|
order.destroy if order && order.persisted?
|
@@ -25,12 +23,6 @@ Spree::Order.class_eval do
|
|
25
23
|
end
|
26
24
|
end
|
27
25
|
|
28
|
-
def self.destroy_automatic_taxes_on_import(order, params)
|
29
|
-
if params.delete :import
|
30
|
-
order.adjustments.tax.destroy_all
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
26
|
def complete_from_api(completed_at)
|
35
27
|
if completed_at
|
36
28
|
self.completed_at = completed_at
|
@@ -85,7 +77,7 @@ Spree::Order.class_eval do
|
|
85
77
|
line_item = line_items_hash[k]
|
86
78
|
self.class.ensure_variant_id_from_api(line_item)
|
87
79
|
|
88
|
-
extra_params = line_item.except(:variant_id, :quantity
|
80
|
+
extra_params = line_item.except(:variant_id, :quantity)
|
89
81
|
line_item = self.contents.add(Spree::Variant.find(line_item[:variant_id]), line_item[:quantity])
|
90
82
|
line_item.update_attributes(extra_params) unless extra_params.empty?
|
91
83
|
rescue Exception => e
|
@@ -97,11 +89,10 @@ Spree::Order.class_eval do
|
|
97
89
|
def create_adjustments_from_api(adjustments)
|
98
90
|
adjustments.each do |a|
|
99
91
|
begin
|
100
|
-
a.symbolize_keys! # For backwards compatibility sake (before it acccessed string keys)
|
101
92
|
adjustment = self.adjustments.build(:amount => a[:amount].to_f,
|
102
93
|
:label => a[:label])
|
103
94
|
adjustment.save!
|
104
|
-
adjustment.
|
95
|
+
adjustment.close!
|
105
96
|
rescue Exception => e
|
106
97
|
raise "Order import adjustments: #{e.message} #{a}"
|
107
98
|
end
|
@@ -2,7 +2,6 @@ cache @order
|
|
2
2
|
attributes *order_attributes
|
3
3
|
node(:display_item_total) { |o| o.display_item_total.to_s }
|
4
4
|
node(:total_quantity) { |o| o.line_items.sum(:quantity) }
|
5
|
-
node(:display_tax_total) { |o| o.display_tax_total }
|
6
5
|
node(:display_total) { |o| o.display_total.to_s }
|
7
6
|
node(:display_ship_total) { |o| o.display_ship_total }
|
8
7
|
node(:token) { |o| o.token }
|
@@ -1,17 +1,14 @@
|
|
1
1
|
object @product
|
2
|
-
cache [current_currency,
|
2
|
+
cache [current_currency, @product]
|
3
3
|
attributes *product_attributes
|
4
4
|
node(:display_price) { |p| p.display_price.to_s }
|
5
|
-
|
6
|
-
|
5
|
+
node(:has_variants) { |p| p.has_variants? }
|
6
|
+
child :master => :master do
|
7
|
+
extends "spree/api/variants/show"
|
8
|
+
end
|
7
9
|
|
8
|
-
|
9
|
-
|
10
|
-
end
|
11
|
-
|
12
|
-
child :images => :images do
|
13
|
-
extends "spree/api/images/show"
|
14
|
-
end
|
10
|
+
child :variants => :variants do
|
11
|
+
extends "spree/api/variants/show"
|
15
12
|
end
|
16
13
|
|
17
14
|
child :option_types => :option_types do
|
@@ -1,5 +1,4 @@
|
|
1
1
|
object @variant
|
2
2
|
cache @variant
|
3
|
-
extends "spree/api/variants/
|
4
|
-
child(:
|
5
|
-
child(:images => :images) { extends "spree/api/images/show" }
|
3
|
+
extends "spree/api/variants/variant_full"
|
4
|
+
child(:images => :images) { extends "spree/api/images/show" }
|
File without changes
|
data/config/routes.rb
CHANGED
@@ -31,10 +31,6 @@ Spree::Core::Engine.add_routes do
|
|
31
31
|
get '/orders/mine', :to => 'orders#mine', :as => 'my_orders'
|
32
32
|
|
33
33
|
resources :orders do
|
34
|
-
member do
|
35
|
-
put :apply_coupon_code
|
36
|
-
end
|
37
|
-
|
38
34
|
resources :addresses, :only => [:show, :update]
|
39
35
|
|
40
36
|
resources :return_authorizations do
|
@@ -47,6 +43,7 @@ Spree::Core::Engine.add_routes do
|
|
47
43
|
member do
|
48
44
|
put :cancel
|
49
45
|
put :empty
|
46
|
+
put :apply_coupon_code
|
50
47
|
end
|
51
48
|
|
52
49
|
resources :line_items
|
@@ -84,7 +81,9 @@ Spree::Core::Engine.add_routes do
|
|
84
81
|
end
|
85
82
|
end
|
86
83
|
end
|
84
|
+
|
87
85
|
resources :taxons, :only => [:index]
|
86
|
+
|
88
87
|
resources :inventory_units, :only => [:show, :update]
|
89
88
|
resources :users
|
90
89
|
resources :properties
|
@@ -95,5 +94,8 @@ Spree::Core::Engine.add_routes do
|
|
95
94
|
|
96
95
|
get '/config/money', :to => 'config#money'
|
97
96
|
get '/config', :to => 'config#show'
|
97
|
+
|
98
|
+
put '/classifications', :to => 'classifications#update', :as => :classifications
|
99
|
+
get '/taxons/products', :to => 'taxons#products', :as => :taxon_products
|
98
100
|
end
|
99
101
|
end
|
@@ -7,50 +7,76 @@ module Spree
|
|
7
7
|
before do
|
8
8
|
stub_authentication!
|
9
9
|
@address = create(:address)
|
10
|
-
@order = create(:order, :bill_address => @address)
|
11
10
|
end
|
12
|
-
|
13
|
-
context "with
|
11
|
+
|
12
|
+
context "with order" do
|
14
13
|
before do
|
15
|
-
|
14
|
+
@order = create(:order, :bill_address => @address)
|
16
15
|
end
|
16
|
+
|
17
|
+
context "with their own address" do
|
18
|
+
before do
|
19
|
+
Order.any_instance.stub :user => current_api_user
|
20
|
+
end
|
17
21
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
+
it "gets an address" do
|
23
|
+
api_get :show, :id => @address.id, :order_id => @order.number
|
24
|
+
json_response['address1'].should eq @address.address1
|
25
|
+
end
|
22
26
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
27
|
+
it "updates an address" do
|
28
|
+
api_put :update, :id => @address.id, :order_id => @order.number,
|
29
|
+
:address => { :address1 => "123 Test Lane" }
|
30
|
+
json_response['address1'].should eq '123 Test Lane'
|
31
|
+
end
|
28
32
|
|
29
|
-
|
30
|
-
|
31
|
-
|
33
|
+
it "receives the errors object if address is invalid" do
|
34
|
+
api_put :update, :id => @address.id, :order_id => @order.number,
|
35
|
+
:address => { :address1 => "" }
|
32
36
|
|
33
|
-
|
34
|
-
|
35
|
-
|
37
|
+
json_response['error'].should_not be_nil
|
38
|
+
json_response['errors'].should_not be_nil
|
39
|
+
json_response['errors']['address1'].first.should eq "can't be blank"
|
40
|
+
end
|
36
41
|
end
|
37
|
-
end
|
38
42
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
+
context "on an address that does not belong to this order" do
|
44
|
+
before do
|
45
|
+
@order.bill_address_id = nil
|
46
|
+
@order.ship_address = nil
|
47
|
+
end
|
48
|
+
|
49
|
+
it "cannot retreive address information" do
|
50
|
+
api_get :show, :id => @address.id, :order_id => @order.number
|
51
|
+
assert_unauthorized!
|
52
|
+
end
|
53
|
+
|
54
|
+
it "cannot update address information" do
|
55
|
+
api_get :update, :id => @address.id, :order_id => @order.number
|
56
|
+
assert_unauthorized!
|
57
|
+
end
|
43
58
|
end
|
59
|
+
end
|
60
|
+
|
61
|
+
context "without order" do
|
62
|
+
context "with their own address" do
|
63
|
+
before do
|
64
|
+
Address.any_instance.stub :user => current_api_user
|
65
|
+
end
|
44
66
|
|
45
|
-
|
46
|
-
|
47
|
-
|
67
|
+
it "gets an address" do
|
68
|
+
api_get :show, :id => @address.id
|
69
|
+
json_response['address1'].should eq @address.address1
|
70
|
+
end
|
48
71
|
end
|
49
72
|
|
50
|
-
|
51
|
-
|
52
|
-
|
73
|
+
context "on an address that does not belong to this user" do
|
74
|
+
it "cannot update address information" do
|
75
|
+
api_put :update, :id => @address.id, :address => { :address1 => "123 Test Lane" }
|
76
|
+
json_response['address1'].should be_nil
|
77
|
+
assert_unauthorized!
|
78
|
+
end
|
53
79
|
end
|
54
80
|
end
|
55
81
|
end
|
56
|
-
end
|
82
|
+
end
|
@@ -21,42 +21,6 @@ describe Spree::Api::BaseController do
|
|
21
21
|
end
|
22
22
|
end
|
23
23
|
|
24
|
-
context "when validating based on an order token" do
|
25
|
-
let!(:order) { create :order }
|
26
|
-
|
27
|
-
context "with a correct order token" do
|
28
|
-
it "succeeds" do
|
29
|
-
api_get :index, order_token: order.token, order_id: order.number
|
30
|
-
response.status.should == 200
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
context "with an incorrect order token" do
|
35
|
-
it "returns unauthorized" do
|
36
|
-
api_get :index, order_token: "NOT_A_TOKEN", order_id: order.number
|
37
|
-
response.status.should == 401
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
context "when validating based on an order token" do
|
43
|
-
let!(:order) { create :order }
|
44
|
-
|
45
|
-
context "with a correct order token" do
|
46
|
-
it "succeeds" do
|
47
|
-
api_get :index, order_token: order.token, order_id: order.number
|
48
|
-
response.status.should == 200
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
context "with an incorrect order token" do
|
53
|
-
it "returns unauthorized" do
|
54
|
-
api_get :index, order_token: "NOT_A_TOKEN", order_id: order.number
|
55
|
-
response.status.should == 401
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
24
|
context "cannot make a request to the API" do
|
61
25
|
it "without an API key" do
|
62
26
|
api_get :index
|