spree_api 2.0.5 → 2.0.6

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 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