spree_api 2.0.5 → 2.0.6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0c5fb9fd878e6c935137a8f09d6b4cffa35f78db
4
- data.tar.gz: aef11d5c34c3cfa8f55c78fa0f987e493220618c
3
+ metadata.gz: 9cb2106c19046c8db51461b87b224d461e21fec1
4
+ data.tar.gz: e6acefe01a95c4b55e83b2ea0d651d7c205cf30f
5
5
  SHA512:
6
- metadata.gz: 4ccb7dc808ccfe6a0badbcca88f2fee1c7f40bff832051b851384be324fbe1c9d97c128b9447d18c6d836a1f77b921fa8dab75c19be1ad73a48c68ea6f2e3652
7
- data.tar.gz: 560ebb4f8b5019b23c3686e8f92131b5ec4a692923e6173e0c93b6740568527b2466b039787c84503c07908caf008a9aee2971cb7434514cb87df920eaed3e37
6
+ metadata.gz: f93f7762a47e706f13da9958f4d3993c9a69662cace7a8f68e3b47ee066e3df5a054309265d9a11bd59db7a5bb0c6df1cce8c3e5562617921317cc618b616578
7
+ data.tar.gz: 5da0e8c9a2b8960985e22049190a677d7415bbedf3e03d29b47a66a68c7707152df13a5336fa2433628d10337078f6a647893ec19c28f260defa7c10387710ef
@@ -1,3 +1,9 @@
1
+ ## Spree 2.0.6 ##
2
+
3
+ * Normal users can no longer read stock item, stock location or stock movements API endpoints.
4
+
5
+ *Ryan Bigg*
6
+
1
7
  ## Spree 2.0.x ##
2
8
 
3
9
  * PUT requests to Checkouts API endpoints now require authorization to alter an order.
@@ -1,6 +1,8 @@
1
1
  module Spree
2
2
  module Api
3
3
  class CountriesController < Spree::Api::BaseController
4
+ skip_before_filter :check_for_user_or_api_key
5
+ skip_before_filter :authenticate_user
4
6
 
5
7
  def index
6
8
  @countries = Country.ransack(params[:q]).result.
@@ -17,6 +17,7 @@ module Spree
17
17
  end
18
18
 
19
19
  def create
20
+ nested_params[:line_items_attributes] = sanitize_line_items(nested_params[:line_items_attributes])
20
21
  @order = Order.build_from_api(current_api_user, nested_params)
21
22
  respond_with(order, :default_template => :show, :status => 201)
22
23
  end
@@ -26,7 +27,7 @@ module Spree
26
27
  # Parsing line items through as an update_attributes call in the API will result in
27
28
  # many line items for the same variant_id being created. We must be smarter about this,
28
29
  # hence the use of the update_line_items method, defined within order_decorator.rb.
29
- line_items_params = params[:order].delete("line_items")
30
+ line_items_params = sanitize_line_items(nested_params.delete("line_items_attributes"))
30
31
  if order.update_attributes(nested_params)
31
32
  order.update_line_items(line_items_params)
32
33
  order.line_items.reload
@@ -51,7 +52,20 @@ module Spree
51
52
  private
52
53
 
53
54
  def nested_params
54
- map_nested_attributes_keys Order, params[:order] || {}
55
+ @nested_params ||= map_nested_attributes_keys(Order, params[:order] || {})
56
+ end
57
+
58
+ def sanitize_line_items(line_item_attributes)
59
+ return {} if line_item_attributes.blank?
60
+ line_item_attributes = line_item_attributes.map do |id, attributes|
61
+ # Faux Strong-Parameters code to strip price if user isn't an admin
62
+ if current_api_user.has_spree_role?("admin")
63
+ [id, attributes.slice(*Spree::LineItem.attr_accessible[:api])]
64
+ else
65
+ [id, attributes.slice(*Spree::LineItem.attr_accessible[:default])]
66
+ end
67
+ end
68
+ line_item_attributes = Hash[line_item_attributes].delete_if { |k,v| v.empty? }
55
69
  end
56
70
 
57
71
  def order
@@ -4,7 +4,7 @@ module Spree
4
4
  respond_to :json
5
5
 
6
6
  before_filter :find_order
7
- before_filter :find_payment, :only => [:show, :authorize, :purchase, :capture, :void, :credit]
7
+ before_filter :find_payment, only: [:update, :show, :authorize, :purchase, :capture, :void, :credit]
8
8
 
9
9
  def index
10
10
  @payments = @order.payments.ransack(params[:q]).result.page(params[:page]).per(params[:per_page])
@@ -25,6 +25,17 @@ module Spree
25
25
  end
26
26
  end
27
27
 
28
+ def update
29
+ authorize! params[:action], @payment
30
+ if !@payment.pending?
31
+ render 'update_forbidden', status: 403
32
+ elsif @payment.update_attributes(params[:payment])
33
+ respond_with(@payment, default_template: :show)
34
+ else
35
+ invalid_resource!(@payment)
36
+ end
37
+ end
38
+
28
39
  def show
29
40
  respond_with(@payment)
30
41
  end
@@ -47,7 +58,7 @@ module Spree
47
58
 
48
59
  def credit
49
60
  if params[:amount].to_f > @payment.credit_allowed
50
- render "spree/api/payments/credit_over_limit", :status => 422
61
+ render 'credit_over_limit', status: 422
51
62
  else
52
63
  perform_payment_action(:credit, params[:amount])
53
64
  end
@@ -1,6 +1,8 @@
1
1
  module Spree
2
2
  module Api
3
3
  class StatesController < Spree::Api::BaseController
4
+ skip_before_filter :check_for_user_or_api_key
5
+ skip_before_filter :authenticate_user
4
6
 
5
7
  def index
6
8
  @states = scope.ransack(params[:q]).result.
@@ -4,11 +4,13 @@ module Spree
4
4
  before_filter :stock_location, except: [:update, :destroy]
5
5
 
6
6
  def index
7
+ authorize! :read, StockItem
7
8
  @stock_items = scope.ransack(params[:q]).result.page(params[:page]).per(params[:per_page])
8
9
  respond_with(@stock_items)
9
10
  end
10
11
 
11
12
  def show
13
+ authorize! :read, StockItem
12
14
  @stock_item = scope.find(params[:id])
13
15
  respond_with(@stock_item)
14
16
  end
@@ -66,7 +68,8 @@ module Spree
66
68
  end
67
69
 
68
70
  def scope
69
- @stock_location.stock_items.includes(:variant => :product)
71
+ includes = {:variant => [{ :option_values => :option_type }, :product] }
72
+ @stock_location.stock_items.includes(includes)
70
73
  end
71
74
  end
72
75
  end
@@ -2,11 +2,13 @@ module Spree
2
2
  module Api
3
3
  class StockLocationsController < Spree::Api::BaseController
4
4
  def index
5
- @stock_locations = StockLocation.order('name ASC').ransack(params[:q]).result.page(params[:page]).per(params[:per_page])
5
+ authorize! :read, StockLocation
6
+ @stock_locations = StockLocation.accessible_by(current_ability, :read).order('name ASC').ransack(params[:q]).result.page(params[:page]).per(params[:per_page])
6
7
  respond_with(@stock_locations)
7
8
  end
8
9
 
9
10
  def show
11
+ authorize! :read, StockLocation
10
12
  respond_with(stock_location)
11
13
  end
12
14
 
@@ -4,11 +4,13 @@ module Spree
4
4
  before_filter :stock_location, except: [:update, :destroy]
5
5
 
6
6
  def index
7
+ authorize! :read, StockMovement
7
8
  @stock_movements = scope.ransack(params[:q]).result.page(params[:page]).per(params[:per_page])
8
9
  respond_with(@stock_movements)
9
10
  end
10
11
 
11
12
  def show
13
+ authorize! :read, StockMovement
12
14
  @stock_movement = scope.find(params[:id])
13
15
  respond_with(@stock_movement)
14
16
  end
@@ -28,7 +28,7 @@ module Spree
28
28
  end
29
29
 
30
30
  def option_value_attributes
31
- [:id, :name, :presentation, :option_type_name, :option_type_id]
31
+ [:id, :name, :presentation, :option_type_name, :option_type_id, :option_type_presentation]
32
32
  end
33
33
 
34
34
  def order_attributes
@@ -44,7 +44,7 @@ module Spree
44
44
  end
45
45
 
46
46
  def payment_attributes
47
- [:id, :source_type, :source_id, :amount, :payment_method_id, :response_code, :state, :avs_response, :created_at, :updated_at]
47
+ [:id, :source_type, :source_id, :amount, :display_amount, :payment_method_id, :response_code, :state, :avs_response, :created_at, :updated_at]
48
48
  end
49
49
 
50
50
  def payment_method_attributes
@@ -113,4 +113,3 @@ module Spree
113
113
  end
114
114
  end
115
115
  end
116
-
@@ -1,3 +1,3 @@
1
1
  Spree::LineItem.class_eval do
2
- attr_accessible :quantity, :variant_id, :as => :api
2
+ attr_accessible :quantity, :variant_id, :price, :as => :api
3
3
  end
@@ -2,4 +2,8 @@ Spree::OptionValue.class_eval do
2
2
  def option_type_name
3
3
  option_type.name
4
4
  end
5
+
6
+ def option_type_presentation
7
+ option_type.presentation
8
+ end
5
9
  end
@@ -1,28 +1,34 @@
1
1
  Spree::Order.class_eval do
2
2
  def self.build_from_api(user, params)
3
- completed_at = params.delete(:completed_at)
4
- line_items = params.delete(:line_items_attributes) || {}
5
- shipments = params.delete(:shipments_attributes) || []
6
- payments = params.delete(:payments_attributes) || []
7
- adjustments = params.delete(:adjustments_attributes) || []
3
+ begin
4
+ ensure_country_id_from_api params[:ship_address_attributes]
5
+ ensure_state_id_from_api params[:ship_address_attributes]
6
+ ensure_country_id_from_api params[:bill_address_attributes]
7
+ ensure_state_id_from_api params[:bill_address_attributes]
8
8
 
9
- ensure_country_id_from_api params[:ship_address_attributes]
10
- ensure_state_id_from_api params[:ship_address_attributes]
9
+ order = create!
10
+ order.associate_user!(user)
11
11
 
12
- ensure_country_id_from_api params[:bill_address_attributes]
13
- ensure_state_id_from_api params[:bill_address_attributes]
12
+ order.create_shipments_from_api params.delete(:shipments_attributes) || []
13
+ order.create_line_items_from_api params.delete(:line_items_attributes) || {}
14
+ order.create_adjustments_from_api params.delete(:adjustments_attributes) || []
15
+ order.create_payments_from_api params.delete(:payments_attributes) || []
16
+ order.complete_from_api params.delete(:completed_at)
14
17
 
15
- order = create!(params)
16
- order.associate_user!(user)
18
+ destroy_automatic_taxes_on_import(order, params)
19
+ order.update_attributes!(params)
17
20
 
18
- order.create_shipments_from_api(shipments)
19
- order.create_line_items_from_api(line_items)
20
- order.create_adjustments_from_api(adjustments)
21
- order.create_payments_from_api(payments)
22
- order.complete_from_api(completed_at)
21
+ order.reload
22
+ rescue Exception => e
23
+ order.destroy if order && order.persisted?
24
+ raise e.message
25
+ end
26
+ end
23
27
 
24
- order.save!
25
- order.reload
28
+ def self.destroy_automatic_taxes_on_import(order, params)
29
+ if params.delete :import
30
+ order.adjustments.tax.destroy_all
31
+ end
26
32
  end
27
33
 
28
34
  def complete_from_api(completed_at)
@@ -37,6 +43,7 @@ Spree::Order.class_eval do
37
43
  begin
38
44
  shipment = shipments.build
39
45
  shipment.tracking = s[:tracking]
46
+ shipment.stock_location = Spree::StockLocation.find_by_name!(s[:stock_location])
40
47
 
41
48
  inventory_units = s[:inventory_units] || []
42
49
  inventory_units.each do |iu|
@@ -80,7 +87,7 @@ Spree::Order.class_eval do
80
87
 
81
88
  extra_params = line_item.except(:variant_id, :quantity)
82
89
  line_item = self.contents.add(Spree::Variant.find(line_item[:variant_id]), line_item[:quantity])
83
- line_item.update_attributes(extra_params) unless extra_params.empty?
90
+ line_item.update_attributes(extra_params, as: :api) unless extra_params.empty?
84
91
  rescue Exception => e
85
92
  raise "#{e.message} #{line_item}"
86
93
  end
@@ -155,7 +162,7 @@ Spree::Order.class_eval do
155
162
  def update_line_items(line_item_params)
156
163
  return if line_item_params.blank?
157
164
  line_item_params.each do |id, attributes|
158
- self.line_items.find(id).update_attributes!(attributes)
165
+ self.line_items.find(id).update_attributes!(attributes, :as => :api)
159
166
  end
160
167
  self.ensure_updated_shipments
161
168
  end
@@ -1,2 +1,2 @@
1
1
  object false
2
- node(:error) { I18n.t(:credit_over_limit, :limit => @payment.credit_allowed, :scope => 'spree.api') }
2
+ node(:error) { I18n.t(:credit_over_limit, :limit => @payment.credit_allowed, :scope => 'spree.api.payment') }
@@ -3,4 +3,3 @@ node(:attributes) { [*payment_attributes] }
3
3
  child @payment_methods => :payment_methods do
4
4
  attributes *payment_method_attributes
5
5
  end
6
-
@@ -0,0 +1,2 @@
1
+ object false
2
+ node(:error) { I18n.t(:update_forbidden, :state => @payment.state, :scope => 'spree.api.payment') }
@@ -7,7 +7,6 @@ en:
7
7
  invalid_resource: "Invalid resource. Please fix errors and try again."
8
8
  resource_not_found: "The resource you were looking for could not be found."
9
9
  gateway_error: "There was a problem with the payment gateway: %{text}"
10
- credit_over_limit: "This payment can only be credited up to %{limit}. Please specify an amount less than or equal to this number."
11
10
  access: "API Access"
12
11
  key: "Key"
13
12
  clear_key: "Clear key"
@@ -19,6 +18,9 @@ en:
19
18
  order:
20
19
  could_not_transition: "The order could not be transitioned. Please fix the errors and try again."
21
20
  invalid_shipping_method: "Invalid shipping method specified."
21
+ payment:
22
+ credit_over_limit: "This payment can only be credited up to %{limit}. Please specify an amount less than or equal to this number."
23
+ update_forbidden: "This payment cannot be updated because it is %{state}."
22
24
  shipment:
23
25
  cannot_ready: "Cannot ready shipment."
24
26
  stock_location_required: "A stock_location_id parameter must be provided in order to retrieve stock movements."
@@ -76,37 +76,23 @@ module Spree
76
76
  json_response["user_id"].should == current_api_user.id
77
77
  end
78
78
 
79
- # Regression test for #3404
80
- it "can specify additional parameters for a line item" do
79
+ it "cannot create an order with an abitrary price for the line item" do
81
80
  variant = create(:variant)
82
- Order.should_receive(:create!).and_return(order = Spree::Order.new)
83
- order.stub(:associate_user!)
84
- order.stub_chain(:contents, :add).and_return(line_item = double('LineItem'))
85
- line_item.should_receive(:update_attributes).with("special" => true)
86
- api_post :create, :order => {
81
+ api_post :create, :order => {
87
82
  :line_items => {
88
83
  "0" => {
89
- :variant_id => variant.to_param, :quantity => 5, :special => true
84
+ :variant_id => variant.to_param,
85
+ :quantity => 5,
86
+ :price => 0.44
90
87
  }
91
88
  }
92
89
  }
93
90
  response.status.should == 201
94
- end
95
-
96
- # Regression test for #3404
97
- it "does not update line item needlessly" do
98
- variant = create(:variant)
99
- Order.should_receive(:create!).and_return(order = Spree::Order.new)
100
- order.stub(:associate_user!)
101
- order.stub_chain(:contents, :add).and_return(line_item = double('LineItem'))
102
- line_item.should_not_receive(:update_attributes)
103
- api_post :create, :order => {
104
- :line_items => {
105
- "0" => {
106
- :variant_id => variant.to_param, :quantity => 5
107
- }
108
- }
109
- }
91
+ order = Order.last
92
+ order.line_items.count.should == 1
93
+ order.line_items.first.variant.should == variant
94
+ order.line_items.first.quantity.should == 5
95
+ order.line_items.first.price.should == order.line_items.first.variant.price
110
96
  end
111
97
  end
112
98
 
@@ -155,17 +141,6 @@ module Spree
155
141
  :country_id => Country.first.id, :state_id => State.first.id} }
156
142
  let!(:payment_method) { create(:payment_method) }
157
143
 
158
- it "can add line items" do
159
- api_put :update, :id => order.to_param, :order => {
160
- :line_items_attributes => [{:variant_id => create(:variant).id, :quantity => 2}] }
161
-
162
- response.status.should == 200
163
- json_response['item_total'].to_f.should_not == order.item_total.to_f
164
- json_response['line_items'].count.should == 2
165
- json_response['line_items'].first['quantity'].should == 1
166
- json_response['line_items'].last['quantity'].should == 2
167
- end
168
-
169
144
  it "updates quantities of existing line items" do
170
145
  api_put :update, :id => order.to_param, :order => {
171
146
  :line_items => {
@@ -178,6 +153,18 @@ module Spree
178
153
  json_response['line_items'].first['quantity'].should == 10
179
154
  end
180
155
 
156
+ it "cannot set a price for a line item" do
157
+ variant = create(:variant)
158
+ api_put :update, :id => order.to_param, :order => {
159
+ :line_items_attributes => { order.line_items.first.id =>
160
+ { :variant_id => variant.id, :quantity => 2, :price => 0.44}
161
+ }
162
+ }
163
+ response.status.should == 200
164
+ json_response['line_items'].count.should == 1
165
+ expect(json_response['line_items'].first['price']).to eq(variant.price.to_s)
166
+ end
167
+
181
168
  it "can add billing address" do
182
169
  api_put :update, :id => order.to_param, :order => { :bill_address_attributes => billing_address }
183
170
 
@@ -5,11 +5,12 @@ module Spree
5
5
  render_views
6
6
  let!(:order) { create(:order) }
7
7
  let!(:payment) { create(:payment, :order => order) }
8
- let!(:attributes) { [:id, :source_type, :source_id, :amount,
8
+ let!(:attributes) { [:id, :source_type, :source_id, :amount, :display_amount,
9
9
  :payment_method_id, :response_code, :state, :avs_response,
10
10
  :created_at, :updated_at] }
11
11
 
12
12
  let(:resource_scoping) { { :order_id => order.to_param } }
13
+
13
14
  before do
14
15
  stub_authentication!
15
16
  end
@@ -43,6 +44,11 @@ module Spree
43
44
  json_response.should have_attributes(attributes)
44
45
  end
45
46
 
47
+ it "cannot update a payment" do
48
+ api_put :update, :id => payment.to_param, :payment => { :amount => 2.01 }
49
+ assert_unauthorized!
50
+ end
51
+
46
52
  it "cannot authorize a payment" do
47
53
  api_put :authorize, :id => payment.to_param
48
54
  assert_unauthorized!
@@ -93,76 +99,120 @@ module Spree
93
99
  end
94
100
 
95
101
  context "for a given payment" do
102
+ context "updating" do
103
+ it "can update" do
104
+ payment.update_column(:state, 'pending')
105
+ api_put :update, :id => payment.to_param, :payment => { :amount => 2.01 }
106
+ response.status.should == 200
107
+ payment.reload.amount.should == 2.01
108
+ end
96
109
 
97
- it "can authorize" do
98
- api_put :authorize, :id => payment.to_param
99
- response.status.should == 200
100
- payment.reload
101
- payment.state.should == "pending"
110
+ context "update fails" do
111
+ it "returns a 422 status when the amount is invalid" do
112
+ payment.update_column(:state, 'pending')
113
+ api_put :update, :id => payment.to_param, :payment => { :amount => 'invalid' }
114
+ response.status.should == 422
115
+ json_response["error"].should == "Invalid resource. Please fix errors and try again."
116
+ end
117
+
118
+ it "returns a 403 status when the payment is not pending" do
119
+ payment.update_column(:state, 'complete')
120
+ api_put :update, :id => payment.to_param, :payment => { :amount => 2.01 }
121
+ response.status.should == 403
122
+ json_response["error"].should == "This payment cannot be updated because it is complete."
123
+ end
124
+ end
102
125
  end
103
126
 
104
- it "returns a 422 status when authorization fails" do
105
- fake_response = double(:success? => false, :to_s => "Could not authorize card")
106
- Spree::Gateway::Bogus.any_instance.should_receive(:authorize).and_return(fake_response)
107
- api_put :authorize, :id => payment.to_param
108
- response.status.should == 422
109
- json_response["error"].should == "There was a problem with the payment gateway: Could not authorize card"
110
- payment.reload
111
- payment.state.should == "failed"
112
- end
127
+ context "authorizing" do
128
+ it "can authorize" do
129
+ api_put :authorize, :id => payment.to_param
130
+ response.status.should == 200
131
+ payment.reload.state.should == "pending"
132
+ end
113
133
 
114
- it "can capture" do
115
- api_put :capture, :id => payment.to_param
116
- response.status.should == 200
117
- payment.reload
118
- payment.state.should == "completed"
134
+ context "authorization fails" do
135
+ before do
136
+ fake_response = double(:success? => false, :to_s => "Could not authorize card")
137
+ Spree::Gateway::Bogus.any_instance.should_receive(:authorize).and_return(fake_response)
138
+ api_put :authorize, :id => payment.to_param
139
+ end
140
+
141
+ it "returns a 422 status" do
142
+ response.status.should == 422
143
+ json_response["error"].should == "There was a problem with the payment gateway: Could not authorize card"
144
+ end
145
+
146
+ it "does not raise a stack level error" do
147
+ pending "Investigate why a payment.reload after the request raises 'stack level too deep'"
148
+ payment.reload.state.should == "failed"
149
+ end
150
+ end
119
151
  end
120
152
 
121
- it "returns a 422 status when purchasing fails" do
122
- fake_response = double(:success? => false, :to_s => "Insufficient funds")
123
- Spree::Gateway::Bogus.any_instance.should_receive(:capture).and_return(fake_response)
124
- api_put :capture, :id => payment.to_param
125
- response.status.should == 422
126
- json_response["error"].should == "There was a problem with the payment gateway: Insufficient funds"
127
-
128
- payment.reload
129
- payment.state.should == "failed"
130
- end
153
+ context "capturing" do
154
+ it "can capture" do
155
+ api_put :capture, :id => payment.to_param
156
+ response.status.should == 200
157
+ payment.reload.state.should == "completed"
158
+ end
131
159
 
132
- it "can purchase" do
133
- api_put :purchase, :id => payment.to_param
134
- response.status.should == 200
135
- payment.reload
136
- payment.state.should == "completed"
160
+ context "capturing fails" do
161
+ before do
162
+ fake_response = double(:success? => false, :to_s => "Insufficient funds")
163
+ Spree::Gateway::Bogus.any_instance.should_receive(:capture).and_return(fake_response)
164
+ end
165
+
166
+ it "returns a 422 status" do
167
+ api_put :capture, :id => payment.to_param
168
+ response.status.should == 422
169
+ json_response["error"].should == "There was a problem with the payment gateway: Insufficient funds"
170
+ end
171
+ end
137
172
  end
138
173
 
139
- it "returns a 422 status when purchasing fails" do
140
- fake_response = double(:success? => false, :to_s => "Insufficient funds")
141
- Spree::Gateway::Bogus.any_instance.should_receive(:purchase).and_return(fake_response)
142
- api_put :purchase, :id => payment.to_param
143
- response.status.should == 422
144
- json_response["error"].should == "There was a problem with the payment gateway: Insufficient funds"
174
+ context "purchasing" do
175
+ it "can purchase" do
176
+ api_put :purchase, :id => payment.to_param
177
+ response.status.should == 200
178
+ payment.reload.state.should == "completed"
179
+ end
145
180
 
146
- payment.reload
147
- payment.state.should == "failed"
181
+ context "purchasing fails" do
182
+ before do
183
+ fake_response = double(:success? => false, :to_s => "Insufficient funds")
184
+ Spree::Gateway::Bogus.any_instance.should_receive(:purchase).and_return(fake_response)
185
+ end
186
+
187
+ it "returns a 422 status" do
188
+ api_put :purchase, :id => payment.to_param
189
+ response.status.should == 422
190
+ json_response["error"].should == "There was a problem with the payment gateway: Insufficient funds"
191
+ end
192
+ end
148
193
  end
149
194
 
150
- it "can void" do
151
- api_put :void, :id => payment.to_param
152
- response.status.should == 200
153
- payment.reload
154
- payment.state.should == "void"
155
- end
195
+ context "voiding" do
196
+ it "can void" do
197
+ api_put :void, :id => payment.to_param
198
+ response.status.should == 200
199
+ payment.reload.state.should == "void"
200
+ end
156
201
 
157
- it "returns a 422 status when voiding fails" do
158
- fake_response = double(:success? => false, :to_s => "NO REFUNDS")
159
- Spree::Gateway::Bogus.any_instance.should_receive(:void).and_return(fake_response)
160
- api_put :void, :id => payment.to_param
161
- response.status.should == 422
162
- json_response["error"].should == "There was a problem with the payment gateway: NO REFUNDS"
202
+ context "voiding fails" do
203
+ before do
204
+ fake_response = double(:success? => false, :to_s => "NO REFUNDS")
205
+ Spree::Gateway::Bogus.any_instance.should_receive(:void).and_return(fake_response)
206
+ end
163
207
 
164
- payment.reload
165
- payment.state.should == "checkout"
208
+ it "returns a 422 status" do
209
+ api_put :void, :id => payment.to_param
210
+ response.status.should == 422
211
+ json_response["error"].should == "There was a problem with the payment gateway: NO REFUNDS"
212
+
213
+ payment.reload.state.should == "checkout"
214
+ end
215
+ end
166
216
  end
167
217
 
168
218
  context "crediting" do
@@ -173,31 +223,30 @@ module Spree
173
223
  it "can credit" do
174
224
  api_put :credit, :id => payment.to_param
175
225
  response.status.should == 200
176
- payment.reload
177
- payment.state.should == "completed"
226
+ payment.reload.state.should == "completed"
178
227
 
179
- # Ensur that a credit payment was created, and it has correct credit amount
228
+ # Ensure that a credit payment was created, and it has correct credit amount
180
229
  credit_payment = Payment.where(:source_type => 'Spree::Payment', :source_id => payment.id).last
181
230
  credit_payment.amount.to_f.should == -45.75
182
231
  end
183
232
 
184
- it "returns a 422 status when crediting fails" do
185
- fake_response = double(:success? => false, :to_s => "NO CREDIT FOR YOU")
186
- Spree::Gateway::Bogus.any_instance.should_receive(:credit).and_return(fake_response)
187
- api_put :credit, :id => payment.to_param
188
- response.status.should == 422
189
- json_response["error"].should == "There was a problem with the payment gateway: NO CREDIT FOR YOU"
190
- end
191
-
192
- it "cannot credit over credit_allowed limit" do
193
- api_put :credit, :id => payment.to_param, :amount => 1000000
194
- response.status.should == 422
195
- json_response["error"].should == "This payment can only be credited up to 45.75. Please specify an amount less than or equal to this number."
233
+ context "crediting fails" do
234
+ it "returns a 422 status" do
235
+ fake_response = double(:success? => false, :to_s => "NO CREDIT FOR YOU")
236
+ Spree::Gateway::Bogus.any_instance.should_receive(:credit).and_return(fake_response)
237
+ api_put :credit, :id => payment.to_param
238
+ response.status.should == 422
239
+ json_response["error"].should == "There was a problem with the payment gateway: NO CREDIT FOR YOU"
240
+ end
241
+
242
+ it "cannot credit over credit_allowed limit" do
243
+ api_put :credit, :id => payment.to_param, :amount => 1000000
244
+ response.status.should == 422
245
+ json_response["error"].should == "This payment can only be credited up to 45.75. Please specify an amount less than or equal to this number."
246
+ end
196
247
  end
197
248
  end
198
249
  end
199
-
200
250
  end
201
-
202
251
  end
203
252
  end
@@ -13,40 +13,76 @@ module Spree
13
13
  stub_authentication!
14
14
  end
15
15
 
16
- it 'gets list of stock items' do
17
- api_get :index, stock_location_id: stock_location.to_param
18
- json_response['stock_items'].first.should have_attributes(attributes)
19
- json_response['stock_items'].first['variant']['sku'].should eq 'ABC'
20
- end
16
+ context "as a normal user" do
17
+ it "cannot list stock items for a stock location" do
18
+ api_get :index, stock_location_id: stock_location.to_param
19
+ response.status.should == 401
20
+ end
21
21
 
22
- it 'requires a stock_location_id to be passed as a parameter' do
23
- api_get :index
24
- json_response['error'].should =~ /stock_location_id parameter must be provided/
25
- response.status.should == 422
26
- end
22
+ it "cannot see a stock item" do
23
+ api_get :show, stock_location_id: stock_location.to_param, id: stock_item.to_param
24
+ response.status.should == 401
25
+ end
27
26
 
28
- it 'can control the page size through a parameter' do
29
- api_get :index, stock_location_id: stock_location.to_param, per_page: 1
30
- json_response['count'].should == 1
31
- json_response['current_page'].should == 1
32
- end
27
+ it "cannot create a stock item" do
28
+ variant = create(:variant)
29
+ params = {
30
+ stock_location_id: stock_location.to_param,
31
+ stock_item: {
32
+ variant_id: variant.id,
33
+ count_on_hand: '20'
34
+ }
35
+ }
33
36
 
34
- it 'can query the results through a paramter' do
35
- stock_item.update_column(:count_on_hand, 30)
36
- api_get :index, stock_location_id: stock_location.to_param, q: { count_on_hand_eq: '30' }
37
- json_response['count'].should == 1
38
- json_response['stock_items'].first['count_on_hand'].should eq 30
39
- end
37
+ api_post :create, params
38
+ response.status.should == 401
39
+ end
40
+
41
+ it "cannot update a stock item" do
42
+ api_put :update, stock_location_id: stock_location.to_param, stock_item_id: stock_item.to_param
43
+ response.status.should == 401
44
+ end
40
45
 
41
- it 'gets a stock item' do
42
- api_get :show, stock_location_id: stock_location.to_param, id: stock_item.to_param
43
- json_response.should have_attributes(attributes)
44
- json_response['count_on_hand'].should eq stock_item.count_on_hand
46
+ it "cannot destroy a stock item" do
47
+ api_delete :destroy, stock_location_id: stock_location.to_param, stock_item_id: stock_item.to_param
48
+ response.status.should == 401
49
+ end
45
50
  end
46
51
 
47
- context 'as an admin' do
52
+ context "as an admin" do
48
53
  sign_in_as_admin!
49
54
 
55
+ it 'cannot list of stock items' do
56
+ api_get :index, stock_location_id: stock_location.to_param
57
+ json_response['stock_items'].first.should have_attributes(attributes)
58
+ json_response['stock_items'].first['variant']['sku'].should eq 'ABC'
59
+ end
60
+
61
+ it 'requires a stock_location_id to be passed as a parameter' do
62
+ api_get :index
63
+ json_response['error'].should =~ /stock_location_id parameter must be provided/
64
+ response.status.should == 422
65
+ end
66
+
67
+ it 'can control the page size through a parameter' do
68
+ api_get :index, stock_location_id: stock_location.to_param, per_page: 1
69
+ json_response['count'].should == 1
70
+ json_response['current_page'].should == 1
71
+ end
72
+
73
+ it 'can query the results through a paramter' do
74
+ stock_item.update_column(:count_on_hand, 30)
75
+ api_get :index, stock_location_id: stock_location.to_param, q: { count_on_hand_eq: '30' }
76
+ json_response['count'].should == 1
77
+ json_response['stock_items'].first['count_on_hand'].should eq 30
78
+ end
79
+
80
+ it 'gets a stock item' do
81
+ api_get :show, stock_location_id: stock_location.to_param, id: stock_item.to_param
82
+ json_response.should have_attributes(attributes)
83
+ json_response['count_on_hand'].should eq stock_item.count_on_hand
84
+ end
85
+
50
86
  it 'can create a new stock item' do
51
87
  variant = create(:variant)
52
88
  # Creating a variant also creates stock items.
@@ -11,45 +11,72 @@ module Spree
11
11
  stub_authentication!
12
12
  end
13
13
 
14
- it "gets list of stock locations" do
15
- api_get :index
16
- json_response['stock_locations'].first.should have_attributes(attributes)
17
- end
14
+ context "as a user" do
15
+ it "cannot see stock locations" do
16
+ api_get :index
17
+ response.status.should == 401
18
+ end
18
19
 
19
- it "includes the country" do
20
- api_get :index
21
- json_response['stock_locations'].first['country'].should_not be_nil
22
- end
20
+ it "cannot see a single stock location" do
21
+ api_get :show, :id => stock_location.id
22
+ response.status.should == 401
23
+ end
23
24
 
24
- it "includes the state" do
25
- api_get :index
26
- json_response['stock_locations'].first['state'].should_not be_nil
27
- end
25
+ it "cannot create a new stock location" do
26
+ params = {
27
+ stock_location: {
28
+ name: "North Pole",
29
+ active: true
30
+ }
31
+ }
28
32
 
29
- it 'can control the page size through a parameter' do
30
- create(:stock_location)
31
- api_get :index, per_page: 1
32
- json_response['count'].should == 1
33
- json_response['current_page'].should == 1
34
- json_response['pages'].should == 2
35
- end
33
+ api_post :create, params
34
+ response.status.should == 401
35
+ end
36
36
 
37
- it 'can query the results through a paramter' do
38
- expected_result = create(:stock_location, name: 'South America')
39
- api_get :index, q: { name_cont: 'south' }
40
- json_response['count'].should == 1
41
- json_response['stock_locations'].first['name'].should eq expected_result.name
42
- end
37
+ it "cannot update a stock location" do
38
+ api_put :update, :stock_location => { :name => "South Pole" }, :id => stock_location.to_param
39
+ response.status.should == 401
40
+ end
43
41
 
44
- it "gets a stock location" do
45
- api_get :show, id: stock_location.to_param
46
- json_response.should have_attributes(attributes)
47
- json_response['name'].should eq stock_location.name
42
+ it "cannot delete a stock location" do
43
+ api_put :destroy, :id => stock_location.to_param
44
+ response.status.should == 401
45
+ end
48
46
  end
49
47
 
48
+
50
49
  context "as an admin" do
51
50
  sign_in_as_admin!
52
51
 
52
+ it "gets list of stock locations" do
53
+ api_get :index
54
+ json_response['stock_locations'].first.should have_attributes(attributes)
55
+ json_response['stock_locations'].first['country'].should_not be_nil
56
+ json_response['stock_locations'].first['state'].should_not be_nil
57
+ end
58
+
59
+ it 'can control the page size through a parameter' do
60
+ create(:stock_location)
61
+ api_get :index, per_page: 1
62
+ json_response['count'].should == 1
63
+ json_response['current_page'].should == 1
64
+ json_response['pages'].should == 2
65
+ end
66
+
67
+ it 'can query the results through a paramter' do
68
+ expected_result = create(:stock_location, name: 'South America')
69
+ api_get :index, q: { name_cont: 'south' }
70
+ json_response['count'].should == 1
71
+ json_response['stock_locations'].first['name'].should eq expected_result.name
72
+ end
73
+
74
+ it "gets a stock location" do
75
+ api_get :show, id: stock_location.to_param
76
+ json_response.should have_attributes(attributes)
77
+ json_response['name'].should eq stock_location.name
78
+ end
79
+
53
80
  it "can create a new stock location" do
54
81
  params = {
55
82
  stock_location: {
@@ -13,41 +13,65 @@ module Spree
13
13
  stub_authentication!
14
14
  end
15
15
 
16
- it 'gets list of stock movements' do
17
- api_get :index, stock_location_id: stock_location.to_param
18
- json_response['stock_movements'].first.should have_attributes(attributes)
19
- json_response['stock_movements'].first['stock_item']['count_on_hand'].should eq 11
20
- end
21
-
22
- it 'requires a stock_location_id to be passed as a parameter' do
23
- api_get :index
24
- json_response['error'].should =~ /stock_location_id parameter must be provided/
25
- response.status.should == 422
26
- end
16
+ context 'as a user' do
17
+ it 'cannot see a list of stock movements' do
18
+ api_get :index, stock_location_id: stock_location.to_param
19
+ response.status.should == 401
20
+ end
27
21
 
28
- it 'can control the page size through a parameter' do
29
- create(:stock_movement, stock_item: stock_item)
30
- api_get :index, stock_location_id: stock_location.to_param, per_page: 1
31
- json_response['count'].should == 1
32
- json_response['current_page'].should == 1
33
- json_response['pages'].should == 2
34
- end
22
+ it 'cannot see a stock movement' do
23
+ api_get :show, stock_location_id: stock_location.to_param, id: stock_movement.id
24
+ response.status.should == 401
25
+ end
35
26
 
36
- it 'can query the results through a paramter' do
37
- expected_result = create(:stock_movement, :received, quantity: 10, stock_item: stock_item)
38
- api_get :index, stock_location_id: stock_location.to_param, q: { quantity_eq: '10' }
39
- json_response['count'].should == 1
40
- end
27
+ it 'cannot create a stock movement' do
28
+ params = {
29
+ stock_location_id: stock_location.to_param,
30
+ stock_movement: {
31
+ stock_item_id: stock_item.to_param
32
+ }
33
+ }
41
34
 
42
- it 'gets a stock movement' do
43
- api_get :show, stock_location_id: stock_location.to_param, id: stock_movement.to_param
44
- json_response.should have_attributes(attributes)
45
- json_response['stock_item_id'].should eq stock_movement.stock_item_id
35
+ api_post :create, params
36
+ response.status.should == 401
37
+ end
46
38
  end
47
39
 
48
40
  context 'as an admin' do
49
41
  sign_in_as_admin!
50
42
 
43
+ it 'gets list of stock movements' do
44
+ api_get :index, stock_location_id: stock_location.to_param
45
+ json_response['stock_movements'].first.should have_attributes(attributes)
46
+ json_response['stock_movements'].first['stock_item']['count_on_hand'].should eq 11
47
+ end
48
+
49
+ it 'requires a stock_location_id to be passed as a parameter' do
50
+ api_get :index
51
+ json_response['error'].should =~ /stock_location_id parameter must be provided/
52
+ response.status.should == 422
53
+ end
54
+
55
+ it 'can control the page size through a parameter' do
56
+ create(:stock_movement, stock_item: stock_item)
57
+ api_get :index, stock_location_id: stock_location.to_param, per_page: 1
58
+ json_response['count'].should == 1
59
+ json_response['current_page'].should == 1
60
+ json_response['pages'].should == 2
61
+ end
62
+
63
+ it 'can query the results through a paramter' do
64
+ expected_result = create(:stock_movement, :received, quantity: 10, stock_item: stock_item)
65
+ api_get :index, stock_location_id: stock_location.to_param, q: { quantity_eq: '10' }
66
+ json_response['count'].should == 1
67
+ end
68
+
69
+ it 'gets a stock movement' do
70
+ api_get :show, stock_location_id: stock_location.to_param, id: stock_movement.to_param
71
+ json_response.should have_attributes(attributes)
72
+ json_response['stock_item_id'].should eq stock_movement.stock_item_id
73
+ end
74
+
51
75
  it 'can create a new stock movement' do
52
76
  params = {
53
77
  stock_location_id: stock_location.to_param,
@@ -2,22 +2,25 @@ require 'spec_helper'
2
2
 
3
3
  module Spree
4
4
  describe Order do
5
- let!(:country) { FactoryGirl.create(:country) }
6
- let!(:state) { country.states.first || FactoryGirl.create(:state, :country => country) }
7
- let!(:stock_location) { FactoryGirl.create(:stock_location) }
5
+ let!(:country) { create(:country) }
6
+ let!(:state) { country.states.first || create(:state, :country => country) }
7
+ let!(:stock_location) { create(:stock_location) }
8
8
 
9
9
  let(:user) { stub_model(LegacyUser, :email => 'fox@mudler.com') }
10
10
  let(:shipping_method) { create(:shipping_method) }
11
11
  let(:payment_method) { create(:payment_method) }
12
+
12
13
  let(:product) { product = Spree::Product.create(:name => 'Test',
13
14
  :sku => 'TEST-1',
14
15
  :price => 33.22)
15
- product.shipping_category = FactoryGirl.create(:shipping_category)
16
+ product.shipping_category = create(:shipping_category)
16
17
  product.save
17
18
  product }
19
+
18
20
  let(:variant) { variant = product.master
19
21
  variant.stock_items.each { |si| si.update_attribute(:count_on_hand, 10) }
20
22
  variant }
23
+
21
24
  let(:sku) { variant.sku }
22
25
  let(:variant_id) { variant.id }
23
26
 
@@ -49,15 +52,23 @@ module Spree
49
52
  order.state.should eq 'complete'
50
53
  end
51
54
 
52
- it 'can build an order from API with just line items' do
53
- params = { :line_items_attributes => line_items }
55
+ context "build order with line items" do
56
+ let(:attributes) do
57
+ { :variant_id => variant.id, :quantity => 5, :price => 33.77 }
58
+ end
54
59
 
55
- Order.should_receive(:ensure_variant_id_from_api)
56
- order = Order.build_from_api(user, params)
57
- order.user.should == nil
58
- line_item = order.line_items.first
59
- line_item.quantity.should == 5
60
- line_item.variant_id.should == variant_id
60
+ it 'can build an order from API with just line items' do
61
+ params = { :line_items_attributes => { "0" => attributes } }
62
+ Order.should_receive(:ensure_variant_id_from_api)
63
+ order = Order.build_from_api(user, params)
64
+
65
+ order.user.should == nil
66
+ line_item = order.line_items.first
67
+
68
+ expect(line_item.quantity).to eq attributes[:quantity]
69
+ expect(line_item.variant_id).to eq attributes[:variant_id]
70
+ expect(line_item.price).to eq attributes[:price]
71
+ end
61
72
  end
62
73
 
63
74
  it 'handles line_item building exceptions' do
@@ -164,6 +175,13 @@ module Spree
164
175
  end
165
176
  end
166
177
 
178
+ it "raises with proper message when cant find country" do
179
+ address = { :country => { "name" => "NoNoCountry" } }
180
+ expect {
181
+ Order.ensure_country_id_from_api(address)
182
+ }.to raise_error /NoNoCountry/
183
+ end
184
+
167
185
  it 'ensures_state_id for state fields' do
168
186
  [:name, :abbr].each do |field|
169
187
  address = { :state => { field => state.send(field) }}
@@ -172,12 +190,20 @@ module Spree
172
190
  end
173
191
  end
174
192
 
193
+ it "raises with proper message when cant find state" do
194
+ address = { :state => { "name" => "NoNoState" } }
195
+ expect {
196
+ Order.ensure_state_id_from_api(address)
197
+ }.to raise_error /NoNoState/
198
+ end
199
+
175
200
  context "shippments" do
176
201
  let(:params) do
177
202
  { :shipments_attributes => [
178
203
  { :tracking => '123456789',
179
204
  :cost => '4.99',
180
205
  :shipping_method => shipping_method.name,
206
+ :stock_location => stock_location.name,
181
207
  :inventory_units => [{ :sku => sku }]
182
208
  }
183
209
  ] }
@@ -195,6 +221,14 @@ module Spree
195
221
  shipment.inventory_units.first.variant_id.should eq product.master.id
196
222
  shipment.tracking.should eq '123456789'
197
223
  shipment.shipping_rates.first.cost.should eq 4.99
224
+ shipment.stock_location.should eq stock_location
225
+ end
226
+
227
+ it "raises if cant find stock location" do
228
+ params[:shipments_attributes][0][:stock_location] = "doesnt exist"
229
+ expect {
230
+ order = Order.build_from_api(user, params)
231
+ }.to raise_error
198
232
  end
199
233
  end
200
234
 
@@ -244,5 +278,40 @@ module Spree
244
278
  order = Order.build_from_api(user, params)
245
279
  }.to raise_error /XXX/
246
280
  end
281
+
282
+ context "raises error" do
283
+ it "clears out order from db" do
284
+ params = { :payments_attributes => [{ payment_method: "XXX" }] }
285
+ count = Order.count
286
+
287
+ expect { order = Order.build_from_api(user, params) }.to raise_error
288
+ expect(Order.count).to eq count
289
+ end
290
+ end
291
+
292
+ context "import param and tax adjustments" do
293
+ let!(:tax_rate) { create(:tax_rate, amount: 0.05, calculator: Calculator::DefaultTax.create) }
294
+ let(:other_variant) { create(:variant) }
295
+
296
+ let(:line_item_attributes) do
297
+ line_items.merge({ "1" => { :variant_id => other_variant.id, :quantity => 5 }})
298
+ end
299
+
300
+ before { Zone.stub default_tax: tax_rate.zone }
301
+
302
+ it "doesnt create any tax ajustments when importing order" do
303
+ params = { import: true, line_items_attributes: line_item_attributes }
304
+ expect {
305
+ Order.build_from_api(user, params)
306
+ }.not_to change { Adjustment.count }
307
+ end
308
+
309
+ it "does create tax adjustments if not importing order" do
310
+ params = { import: false, line_items_attributes: line_item_attributes }
311
+ expect {
312
+ Order.build_from_api(user, params)
313
+ }.to change { Adjustment.count }
314
+ end
315
+ end
247
316
  end
248
317
  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.0.5
4
+ version: 2.0.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ryan Bigg
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-09-16 00:00:00.000000000 Z
11
+ date: 2013-10-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.0.5
19
+ version: 2.0.6
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.0.5
26
+ version: 2.0.6
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rabl
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -131,6 +131,7 @@ files:
131
131
  - app/views/spree/api/payments/index.v1.rabl
132
132
  - app/views/spree/api/payments/new.v1.rabl
133
133
  - app/views/spree/api/payments/show.v1.rabl
134
+ - app/views/spree/api/payments/update_forbidden.v1.rabl
134
135
  - app/views/spree/api/product_properties/index.v1.rabl
135
136
  - app/views/spree/api/product_properties/new.v1.rabl
136
137
  - app/views/spree/api/product_properties/show.v1.rabl