spree_api 2.0.4 → 2.0.5

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: 9f5519b716277f189e3ca709d60342a6644f63e6
4
- data.tar.gz: 5d8d83310106f05dee2dd8ed5a0f01aa66d1f6f1
3
+ metadata.gz: 0c5fb9fd878e6c935137a8f09d6b4cffa35f78db
4
+ data.tar.gz: aef11d5c34c3cfa8f55c78fa0f987e493220618c
5
5
  SHA512:
6
- metadata.gz: 5f850cf66f2e7a8bd57940b7961f1e740be4a0d0aeabe87ffe5e45f0a3641c7a7c81ffa72301517b5ca07ac5761a3071cb09dabbe69652593656ad382a487367
7
- data.tar.gz: 03ac9cf7f05c894ebab107a30c6f0d6613835e8c55a2407e4b62f30e2b257fbdcf38cd97842f72a8a10f9032068e252f4c10f8e1b024e852036acdc82621eefa
6
+ metadata.gz: 4ccb7dc808ccfe6a0badbcca88f2fee1c7f40bff832051b851384be324fbe1c9d97c128b9447d18c6d836a1f77b921fa8dab75c19be1ad73a48c68ea6f2e3652
7
+ data.tar.gz: 560ebb4f8b5019b23c3686e8f92131b5ec4a692923e6173e0c93b6740568527b2466b039787c84503c07908caf008a9aee2971cb7434514cb87df920eaed3e37
data/CHANGELOG.md CHANGED
@@ -1,6 +1,4 @@
1
- ## Spree 2.0.5 (unreleased)
2
-
3
- ## Spree 2.0.4
1
+ ## Spree 2.0.x ##
4
2
 
5
3
  * PUT requests to Checkouts API endpoints now require authorization to alter an order.
6
4
 
@@ -29,3 +27,17 @@
29
27
  * Attributes other than "quantity" and "variant_id" will be added to a line item when creating along with an order. #3404
30
28
 
31
29
  *Alex Marles & Ryan Bigg*
30
+
31
+ * Taxon attributes from `/api/taxons` are now returned within `taxons` subkey. Before:
32
+
33
+ ```json
34
+ [{ name: 'Ruby' ... }]
35
+ ```
36
+
37
+ Now:
38
+
39
+ ```json
40
+ { taxons: [{ name: 'Ruby' }]}
41
+ ```
42
+
43
+ * Ryan Bigg
@@ -1,16 +1,17 @@
1
1
  module Spree
2
2
  module Api
3
3
  class AddressesController < Spree::Api::BaseController
4
+ before_filter :find_order
4
5
 
5
6
  def show
6
- @address = Address.find(params[:id])
7
- authorize! :read, @address
7
+ authorize! :read, @order, params[:order_token]
8
+ find_address
8
9
  respond_with(@address)
9
10
  end
10
11
 
11
12
  def update
12
- @address = Address.find(params[:id])
13
- authorize! :read, @address
13
+ authorize! :update, @order, params[:order_token]
14
+ find_address
14
15
 
15
16
  if @address.update_attributes(params[:address])
16
17
  respond_with(@address, :default_template => :show)
@@ -18,6 +19,22 @@ module Spree
18
19
  invalid_resource!(@address)
19
20
  end
20
21
  end
22
+
23
+ private
24
+
25
+ def find_order
26
+ @order = Spree::Order.find_by_number!(params[:order_id])
27
+ end
28
+
29
+ def find_address
30
+ @address = if @order.bill_address_id == params[:id].to_i
31
+ @order.bill_address
32
+ elsif @order.ship_address_id == params[:id].to_i
33
+ @order.ship_address
34
+ else
35
+ raise CanCan::AccessDenied
36
+ end
37
+ end
21
38
  end
22
39
  end
23
40
  end
@@ -1,8 +1,9 @@
1
1
  module Spree
2
2
  module Api
3
3
  class CheckoutsController < Spree::Api::BaseController
4
- before_filter :load_order, :only => [:update, :next]
5
- before_filter :associate_user, :only => :update
4
+
5
+ before_filter :load_order, only: [:show, :update, :next, :advance]
6
+ before_filter :associate_user, only: :update
6
7
 
7
8
  include Spree::Core::ControllerHelpers::Auth
8
9
  include Spree::Core::ControllerHelpers::Order
@@ -13,7 +14,25 @@ module Spree
13
14
 
14
15
  def create
15
16
  @order = Order.build_from_api(current_api_user, nested_params)
16
- respond_with(@order, :default_template => 'spree/api/orders/show', :status => 201)
17
+ respond_with(@order, default_template: 'spree/api/orders/show', status: 201)
18
+ end
19
+
20
+ def next
21
+ authorize! :update, @order, params[:order_token]
22
+ @order.next!
23
+ respond_with(@order, default_template: 'spree/api/orders/show', status: 200)
24
+ rescue StateMachine::InvalidTransition
25
+ respond_with(@order, default_template: 'spree/api/orders/could_not_transition', status: 422)
26
+ end
27
+
28
+ def advance
29
+ authorize! :update, @order, params[:order_token]
30
+ while @order.next; end
31
+ respond_with(@order, default_template: 'spree/api/orders/show', status: 200)
32
+ end
33
+
34
+ def show
35
+ respond_with(@order, default_template: 'spree/api/orders/show', status: 200)
17
36
  end
18
37
 
19
38
  def update
@@ -23,8 +42,6 @@ module Spree
23
42
  line_items = order_params.delete("line_items_attributes")
24
43
  if @order.update_attributes(order_params)
25
44
  @order.update_line_items(line_items)
26
- # TODO: Replace with better code when we switch to strong_parameters
27
- # Also remove above user_id stripping
28
45
  if current_api_user.has_spree_role?("admin") && user_id.present?
29
46
  @order.associate_user!(Spree.user_class.find(user_id))
30
47
  end
@@ -23,7 +23,13 @@ module Spree
23
23
 
24
24
  def update
25
25
  authorize! :update, Order
26
+ # Parsing line items through as an update_attributes call in the API will result in
27
+ # many line items for the same variant_id being created. We must be smarter about this,
28
+ # hence the use of the update_line_items method, defined within order_decorator.rb.
29
+ line_items_params = params[:order].delete("line_items")
26
30
  if order.update_attributes(nested_params)
31
+ order.update_line_items(line_items_params)
32
+ order.line_items.reload
27
33
  order.update!
28
34
  respond_with(order, :default_template => :show)
29
35
  else
@@ -37,7 +43,7 @@ module Spree
37
43
  end
38
44
 
39
45
  def empty
40
- order.line_items.destroy_all
46
+ order.empty!
41
47
  order.update!
42
48
  render :text => nil, :status => 200
43
49
  end
@@ -41,7 +41,10 @@ module Spree
41
41
  params[:stock_item].delete(:count_on_hand)
42
42
  end
43
43
 
44
- if @stock_item.adjust_count_on_hand(count_on_hand)
44
+ updated = params[:stock_item][:force] ? @stock_item.set_count_on_hand(count_on_hand)
45
+ : @stock_item.adjust_count_on_hand(count_on_hand)
46
+
47
+ if updated
45
48
  respond_with(@stock_item, status: 200, default_template: :show)
46
49
  else
47
50
  invalid_resource!(@stock_item)
@@ -8,11 +8,13 @@ module Spree
8
8
  @taxons = taxonomy.root.children
9
9
  else
10
10
  if params[:ids]
11
- @taxons = Taxon.where(:id => params[:ids].split(","))
11
+ @taxons = Taxon.accessible_by(current_ability, :read).where(:id => params[:ids].split(","))
12
12
  else
13
- @taxons = Taxon.ransack(params[:q]).result
13
+ @taxons = Taxon.accessible_by(current_ability, :read).order(:taxonomy_id, :lft).ransack(params[:q]).result
14
14
  end
15
15
  end
16
+
17
+ @taxons = @taxons.page(params[:page]).per(params[:per_page])
16
18
  respond_with(@taxons)
17
19
  end
18
20
 
@@ -6,7 +6,7 @@ module Spree
6
6
  before_filter :product
7
7
 
8
8
  def index
9
- @variants = scope.includes(:option_values).ransack(params[:q]).result.
9
+ @variants = scope.includes(:option_values, :stock_items, :product, :images, :prices).ransack(params[:q]).result.
10
10
  page(params[:page]).per(params[:per_page])
11
11
  respond_with(@variants)
12
12
  end
@@ -71,6 +71,10 @@ module Spree
71
71
  [:id, :number, :state, :amount, :order_id, :reason, :created_at, :updated_at]
72
72
  end
73
73
 
74
+ def address_attributes
75
+ [:id, :firstname, :lastname, :full_name, :address1, :address2, :city, :zipcode, :phone, :company, :alternative_phone, :country_id, :state_id, :state_name]
76
+ end
77
+
74
78
  def country_attributes
75
79
  [:id, :iso_name, :iso, :iso3, :name, :numcode]
76
80
  end
@@ -1,20 +1,155 @@
1
1
  Spree::Order.class_eval do
2
2
  def self.build_from_api(user, params)
3
- line_items = params.delete(:line_items_attributes) || []
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) || []
4
8
 
5
- order = create(params)
9
+ ensure_country_id_from_api params[:ship_address_attributes]
10
+ ensure_state_id_from_api params[:ship_address_attributes]
11
+
12
+ ensure_country_id_from_api params[:bill_address_attributes]
13
+ ensure_state_id_from_api params[:bill_address_attributes]
14
+
15
+ order = create!(params)
6
16
  order.associate_user!(user)
7
17
 
8
- unless line_items.empty?
9
- line_items.each_key do |k|
10
- line_item = line_items[k]
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)
23
+
24
+ order.save!
25
+ order.reload
26
+ end
27
+
28
+ def complete_from_api(completed_at)
29
+ if completed_at
30
+ self.completed_at = completed_at
31
+ self.state = 'complete'
32
+ end
33
+ end
34
+
35
+ def create_shipments_from_api(shipments_hash)
36
+ shipments_hash.each do |s|
37
+ begin
38
+ shipment = shipments.build
39
+ shipment.tracking = s[:tracking]
40
+
41
+ inventory_units = s[:inventory_units] || []
42
+ inventory_units.each do |iu|
43
+ self.class.ensure_variant_id_from_api(iu)
44
+
45
+ unit = shipment.inventory_units.build
46
+ unit.order = self
47
+ unit.variant_id = iu[:variant_id]
48
+ end
49
+
50
+ shipment.save!
51
+
52
+ shipping_method = Spree::ShippingMethod.find_by_name!(s[:shipping_method])
53
+ shipment.shipping_rates.create!(:shipping_method => shipping_method,
54
+ :cost => s[:cost])
55
+ rescue Exception => e
56
+ raise "#{e.message} #{s}"
57
+ end
58
+ end
59
+ end
60
+
61
+ def create_payments_from_api(payments_hash)
62
+ payments_hash.each do |p|
63
+ begin
64
+ payment = payments.build
65
+ payment.amount = p[:amount].to_f
66
+ payment.state = p.fetch(:state, 'completed')
67
+ payment.payment_method = Spree::PaymentMethod.find_by_name!(p[:payment_method])
68
+ payment.save!
69
+ rescue Exception => e
70
+ raise "#{e.message} #{p}"
71
+ end
72
+ end
73
+ end
74
+
75
+ def create_line_items_from_api(line_items_hash)
76
+ line_items_hash.each_key do |k|
77
+ begin
78
+ line_item = line_items_hash[k]
79
+ self.class.ensure_variant_id_from_api(line_item)
80
+
11
81
  extra_params = line_item.except(:variant_id, :quantity)
12
- line_item = order.contents.add(Spree::Variant.find(line_item[:variant_id]), line_item[:quantity])
82
+ line_item = self.contents.add(Spree::Variant.find(line_item[:variant_id]), line_item[:quantity])
13
83
  line_item.update_attributes(extra_params) unless extra_params.empty?
84
+ rescue Exception => e
85
+ raise "#{e.message} #{line_item}"
14
86
  end
15
87
  end
88
+ end
89
+
90
+ def create_adjustments_from_api(adjustments)
91
+ adjustments.each do |a|
92
+ begin
93
+ adjustment = self.adjustments.build(:amount => a['amount'].to_f,
94
+ :label => a['label'])
95
+ adjustment.save!
96
+ adjustment.finalize!
97
+ rescue Exception => e
98
+ raise "#{e.message} #{a}"
99
+ end
100
+ end
101
+ end
102
+
103
+ def self.ensure_variant_id_from_api(hash)
104
+ begin
105
+ unless hash[:variant_id].present?
106
+ hash[:variant_id] = Spree::Variant.active.find_by_sku!(hash[:sku]).id
107
+ hash.delete(:sku)
108
+ end
109
+ rescue Exception => e
110
+ raise "#{e.message} #{hash}"
111
+ end
112
+ end
113
+
114
+ def self.ensure_country_id_from_api(address)
115
+ return if address.nil? or address[:country_id].present? or address[:country].nil?
16
116
 
17
- order
117
+ begin
118
+ search = {}
119
+ if name = address[:country]['name']
120
+ search[:name] = name
121
+ elsif iso_name = address[:country]['iso_name']
122
+ search[:iso_name] = iso_name.upcase
123
+ elsif iso = address[:country]['iso']
124
+ search[:iso] = iso.upcase
125
+ elsif iso3 = address[:country]['iso3']
126
+ search[:iso3] = iso3.upcase
127
+ end
128
+
129
+ address.delete(:country)
130
+ address[:country_id] = Spree::Country.where(search).first!.id
131
+
132
+ rescue Exception => e
133
+ raise "#{e.message} #{search}"
134
+ end
135
+ end
136
+
137
+ def self.ensure_state_id_from_api(address)
138
+ return if address.nil? or address[:state_id].present? or address[:state].nil?
139
+
140
+ begin
141
+ search = {}
142
+ if name = address[:state]['name']
143
+ search[:name] = name
144
+ elsif abbr = address[:state]['abbr']
145
+ search[:abbr] = abbr.upcase
146
+ end
147
+
148
+ address.delete(:state)
149
+ address[:state_id] = Spree::State.where(search).first!.id
150
+ rescue Exception => e
151
+ raise "#{e.message} #{search}"
152
+ end
18
153
  end
19
154
 
20
155
  def update_line_items(line_item_params)
@@ -22,5 +157,6 @@ Spree::Order.class_eval do
22
157
  line_item_params.each do |id, attributes|
23
158
  self.line_items.find(id).update_attributes!(attributes)
24
159
  end
160
+ self.ensure_updated_shipments
25
161
  end
26
162
  end
@@ -1,8 +1,6 @@
1
1
  object @address
2
- attributes :id, :firstname, :lastname, :address1, :address2,
3
- :city, :zipcode, :phone,
4
- :company, :alternative_phone, :country_id, :state_id,
5
- :state_name
2
+ attributes *address_attributes
3
+
6
4
  child(:country) do |address|
7
5
  attributes *country_attributes
8
6
  end
@@ -1,4 +1,10 @@
1
- collection @taxons
2
- attributes *taxon_attributes
3
-
4
- extends "spree/api/taxons/taxons"
1
+ object false
2
+ node(:count) { @taxons.count }
3
+ node(:total_count) { @taxons.total_count }
4
+ node(:current_page) { params[:page] ? params[:page].to_i : 1 }
5
+ node(:per_page) { params[:per_page] || Kaminari.config.default_per_page }
6
+ node(:pages) { @taxons.num_pages }
7
+ child(@taxons) do
8
+ attributes *taxon_attributes
9
+ extends "spree/api/taxons/taxons"
10
+ end
data/config/routes.rb CHANGED
@@ -18,6 +18,7 @@ Spree::Core::Engine.routes.draw do
18
18
  resources :checkouts do
19
19
  member do
20
20
  put :next
21
+ put :advance
21
22
  end
22
23
  end
23
24
 
@@ -28,6 +29,8 @@ Spree::Core::Engine.routes.draw do
28
29
  end
29
30
 
30
31
  resources :orders do
32
+ resources :addresses, :only => [:show, :update]
33
+
31
34
  resources :return_authorizations do
32
35
  member do
33
36
  put :add
@@ -64,7 +67,6 @@ Spree::Core::Engine.routes.draw do
64
67
  resources :zones
65
68
  resources :countries, :only => [:index, :show]
66
69
  resources :states, :only => [:index, :show]
67
- resources :addresses, :only => [:show, :update]
68
70
 
69
71
  resources :taxonomies do
70
72
  member do
@@ -7,26 +7,27 @@ module Spree
7
7
  before do
8
8
  stub_authentication!
9
9
  @address = create(:address)
10
+ @order = create(:order, :bill_address => @address)
10
11
  end
11
12
 
12
13
  context "with their own address" do
13
14
  before do
14
- Address.any_instance.stub :user => current_api_user
15
+ Order.any_instance.stub :user => current_api_user
15
16
  end
16
17
 
17
18
  it "gets an address" do
18
- api_get :show, :id => @address.id
19
+ api_get :show, :id => @address.id, :order_id => @order.number
19
20
  json_response['address1'].should eq @address.address1
20
21
  end
21
22
 
22
23
  it "updates an address" do
23
- api_put :update, :id => @address.id,
24
+ api_put :update, :id => @address.id, :order_id => @order.number,
24
25
  :address => { :address1 => "123 Test Lane" }
25
26
  json_response['address1'].should eq '123 Test Lane'
26
27
  end
27
28
 
28
29
  it "receives the errors object if address is invalid" do
29
- api_put :update, :id => @address.id,
30
+ api_put :update, :id => @address.id, :order_id => @order.number,
30
31
  :address => { :address1 => "" }
31
32
 
32
33
  json_response['error'].should_not be_nil
@@ -35,18 +36,19 @@ module Spree
35
36
  end
36
37
  end
37
38
 
38
- context "on somebody else's address" do
39
+ context "on an address that does not belong to this order" do
39
40
  before do
40
- Address.any_instance.stub :user => stub_model(Spree::LegacyUser)
41
+ @order.bill_address_id = nil
42
+ @order.ship_address = nil
41
43
  end
42
44
 
43
45
  it "cannot retreive address information" do
44
- api_get :show, :id => @address.id
46
+ api_get :show, :id => @address.id, :order_id => @order.number
45
47
  assert_unauthorized!
46
48
  end
47
49
 
48
50
  it "cannot update address information" do
49
- api_get :update, :id => @address.id
51
+ api_get :update, :id => @address.id, :order_id => @order.number
50
52
  assert_unauthorized!
51
53
  end
52
54
  end
@@ -66,7 +66,6 @@ module Spree
66
66
  api_put :update, :id => order.to_param, :order_token => order.token,
67
67
  :order => { :line_items_attributes => { line_item.id => { :quantity => 1 } } }
68
68
  response.status.should == 200
69
- order.reload.state.should eq "address"
70
69
  end
71
70
 
72
71
  it "can take line_items as a parameter" do
@@ -74,7 +73,6 @@ module Spree
74
73
  api_put :update, :id => order.to_param, :order_token => order.token,
75
74
  :order => { :line_items => { line_item.id => { :quantity => 1 } } }
76
75
  response.status.should == 200
77
- order.reload.state.should eq "address"
78
76
  end
79
77
 
80
78
  it "will return an error if the order cannot transition" do
@@ -234,5 +232,18 @@ module Spree
234
232
  json_response["errors"]["base"].should include(Spree.t(:no_pending_payments))
235
233
  end
236
234
  end
235
+
236
+ context "PUT 'advance'" do
237
+ let!(:order) { create(:order_with_line_items) }
238
+ it 'continues to advance advances an order while it can move forward' do
239
+ Spree::Order.any_instance.should_receive(:next).exactly(3).times.and_return(true, true, false)
240
+ api_put :advance, :id => order.to_param, :order_token => order.token
241
+ end
242
+ it 'returns the order' do
243
+ api_put :advance, :id => order.to_param, :order_token => order.token
244
+ json_response['id'].should == order.id
245
+ end
246
+
247
+ end
237
248
  end
238
249
  end
@@ -79,7 +79,7 @@ module Spree
79
79
  # Regression test for #3404
80
80
  it "can specify additional parameters for a line item" do
81
81
  variant = create(:variant)
82
- Order.should_receive(:create).and_return(order = Spree::Order.new)
82
+ Order.should_receive(:create!).and_return(order = Spree::Order.new)
83
83
  order.stub(:associate_user!)
84
84
  order.stub_chain(:contents, :add).and_return(line_item = double('LineItem'))
85
85
  line_item.should_receive(:update_attributes).with("special" => true)
@@ -96,7 +96,7 @@ module Spree
96
96
  # Regression test for #3404
97
97
  it "does not update line item needlessly" do
98
98
  variant = create(:variant)
99
- Order.should_receive(:create).and_return(order = Spree::Order.new)
99
+ Order.should_receive(:create!).and_return(order = Spree::Order.new)
100
100
  order.stub(:associate_user!)
101
101
  order.stub_chain(:contents, :add).and_return(line_item = double('LineItem'))
102
102
  line_item.should_not_receive(:update_attributes)
@@ -156,7 +156,8 @@ module Spree
156
156
  let!(:payment_method) { create(:payment_method) }
157
157
 
158
158
  it "can add line items" do
159
- api_put :update, :id => order.to_param, :order => { :line_items => [{:variant_id => create(:variant).id, :quantity => 2}] }
159
+ api_put :update, :id => order.to_param, :order => {
160
+ :line_items_attributes => [{:variant_id => create(:variant).id, :quantity => 2}] }
160
161
 
161
162
  response.status.should == 200
162
163
  json_response['item_total'].to_f.should_not == order.item_total.to_f
@@ -165,6 +166,18 @@ module Spree
165
166
  json_response['line_items'].last['quantity'].should == 2
166
167
  end
167
168
 
169
+ it "updates quantities of existing line items" do
170
+ api_put :update, :id => order.to_param, :order => {
171
+ :line_items => {
172
+ line_item.id => { :quantity => 10 }
173
+ }
174
+ }
175
+
176
+ response.status.should == 200
177
+ json_response['line_items'].count.should == 1
178
+ json_response['line_items'].first['quantity'].should == 10
179
+ end
180
+
168
181
  it "can add billing address" do
169
182
  api_put :update, :id => order.to_param, :order => { :bill_address_attributes => billing_address }
170
183
 
@@ -201,6 +214,20 @@ module Spree
201
214
  json_response['errors']['ship_address.firstname'].first.should eq "can't be blank"
202
215
  end
203
216
 
217
+ context "order has shipments" do
218
+ before { order.create_proposed_shipments }
219
+
220
+ it "clears out all existing shipments on line item udpate" do
221
+ previous_shipments = order.shipments
222
+ api_put :update, :id => order.to_param, :order => {
223
+ :line_items => {
224
+ line_item.id => { :quantity => 10 }
225
+ }
226
+ }
227
+ expect(order.reload.shipments).to be_empty
228
+ end
229
+ end
230
+
204
231
  context "with a line item" do
205
232
  before do
206
233
  create(:line_item, :order => order)
@@ -49,7 +49,9 @@ module Spree
49
49
 
50
50
  it 'can create a new stock item' do
51
51
  variant = create(:variant)
52
- variant.stock_items.delete_all
52
+ # Creating a variant also creates stock items.
53
+ # We don't want any to exist (as they would conflict with what we're about to create)
54
+ StockItem.delete_all
53
55
  params = {
54
56
  stock_location_id: stock_location.to_param,
55
57
  stock_item: {
@@ -77,10 +79,26 @@ module Spree
77
79
  json_response['count_on_hand'].should eq 50
78
80
  end
79
81
 
82
+ it 'can set a stock item to modify the current inventory' do
83
+ stock_item.count_on_hand.should == 10
84
+
85
+ params = {
86
+ id: stock_item.to_param,
87
+ stock_item: {
88
+ count_on_hand: 40,
89
+ force: true,
90
+ }
91
+ }
92
+
93
+ api_put :update, params
94
+ response.status.should == 200
95
+ json_response['count_on_hand'].should eq 40
96
+ end
97
+
80
98
  it 'can delete a stock item' do
81
99
  api_delete :destroy, id: stock_item.to_param
82
100
  response.status.should == 204
83
- lambda { stock_item.reload }.should raise_error(ActiveRecord::RecordNotFound)
101
+ lambda { Spree::StockItem.find(stock_item.id) }.should raise_error(ActiveRecord::RecordNotFound)
84
102
  end
85
103
  end
86
104
  end
@@ -20,18 +20,30 @@ module Spree
20
20
  it "gets all taxons for a taxonomy" do
21
21
  api_get :index, :taxonomy_id => taxonomy.id
22
22
 
23
- json_response.first['name'].should eq taxon.name
24
- children = json_response.first['taxons']
23
+ json_response['taxons'].first['name'].should eq taxon.name
24
+ children = json_response['taxons'].first['taxons']
25
25
  children.count.should eq 1
26
26
  children.first['name'].should eq taxon2.name
27
27
  children.first['taxons'].count.should eq 1
28
28
  end
29
29
 
30
+ it "paginates through taxons" do
31
+ new_taxon = create(:taxon, :name => "Go", :taxonomy => taxonomy)
32
+ taxonomy.root.children << new_taxon
33
+ expect(taxonomy.root.children.count).to eql(2)
34
+ api_get :index, :taxonomy_id => taxonomy.id, :page => 1, :per_page => 1
35
+ expect(json_response["count"]).to eql(1)
36
+ expect(json_response["total_count"]).to eql(2)
37
+ expect(json_response["current_page"]).to eql(1)
38
+ expect(json_response["per_page"]).to eql(1)
39
+ expect(json_response["pages"]).to eql(2)
40
+ end
41
+
30
42
  it "gets all taxons" do
31
43
  api_get :index
32
44
 
33
- json_response.first['name'].should eq taxonomy.root.name
34
- children = json_response.first['taxons']
45
+ json_response['taxons'].first['name'].should eq taxonomy.root.name
46
+ children = json_response['taxons'].first['taxons']
35
47
  children.count.should eq 1
36
48
  children.first['name'].should eq taxon.name
37
49
  children.first['taxons'].count.should eq 1
@@ -40,8 +52,8 @@ module Spree
40
52
  it "can search for a single taxon" do
41
53
  api_get :index, :q => { :name_cont => "Ruby" }
42
54
 
43
- json_response.count.should == 1
44
- json_response.first['name'].should eq "Ruby"
55
+ json_response['taxons'].count.should == 1
56
+ json_response['taxons'].first['name'].should eq "Ruby"
45
57
  end
46
58
 
47
59
  it "gets a single taxon" do
@@ -2,17 +2,247 @@ require 'spec_helper'
2
2
 
3
3
  module Spree
4
4
  describe Order do
5
- let(:user) { stub_model(LegacyUser) }
6
- let(:product) { create :product }
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) }
7
8
 
8
- it 'can build an order from API parameters' do
9
- variant_id = product.master.id
10
- order = Order.build_from_api(user, { :line_items_attributes => { "0" => { :variant_id => variant_id, :quantity => 5 }}})
9
+ let(:user) { stub_model(LegacyUser, :email => 'fox@mudler.com') }
10
+ let(:shipping_method) { create(:shipping_method) }
11
+ let(:payment_method) { create(:payment_method) }
12
+ let(:product) { product = Spree::Product.create(:name => 'Test',
13
+ :sku => 'TEST-1',
14
+ :price => 33.22)
15
+ product.shipping_category = FactoryGirl.create(:shipping_category)
16
+ product.save
17
+ product }
18
+ let(:variant) { variant = product.master
19
+ variant.stock_items.each { |si| si.update_attribute(:count_on_hand, 10) }
20
+ variant }
21
+ let(:sku) { variant.sku }
22
+ let(:variant_id) { variant.id }
11
23
 
24
+ let(:line_items) {{ "0" => { :variant_id => variant.id, :quantity => 5 }}}
25
+ let(:ship_address) {{
26
+ :address1 => '123 Testable Way',
27
+ :firstname => 'Fox',
28
+ :lastname => 'Mulder',
29
+ :city => 'Washington',
30
+ :country_id => country.id,
31
+ :state_id => state.id,
32
+ :zipcode => '666',
33
+ :phone => '666-666-6666'
34
+ }}
35
+
36
+ it 'can import an order number' do
37
+ params = { number: '123-456-789' }
38
+ order = Order.build_from_api(user, params)
39
+ order.number.should eq '123-456-789'
40
+ end
41
+
42
+ it 'optionally add completed at' do
43
+ params = { email: 'test@test.com',
44
+ completed_at: Time.now,
45
+ line_items_attributes: line_items }
46
+
47
+ order = Order.build_from_api(user, params)
48
+ order.should be_completed
49
+ order.state.should eq 'complete'
50
+ end
51
+
52
+ it 'can build an order from API with just line items' do
53
+ params = { :line_items_attributes => line_items }
54
+
55
+ Order.should_receive(:ensure_variant_id_from_api)
56
+ order = Order.build_from_api(user, params)
12
57
  order.user.should == nil
13
58
  line_item = order.line_items.first
14
59
  line_item.quantity.should == 5
15
60
  line_item.variant_id.should == variant_id
16
61
  end
62
+
63
+ it 'handles line_item building exceptions' do
64
+ line_items['0'][:variant_id] = 'XXX'
65
+ params = { :line_items_attributes => line_items }
66
+
67
+ expect {
68
+ order = Order.build_from_api(user, params)
69
+ }.to raise_error /XXX/
70
+ end
71
+
72
+ it 'can build an order from API with variant sku' do
73
+ params = { :line_items_attributes => {
74
+ "0" => { :sku => sku, :quantity => 5 } }}
75
+
76
+ order = Order.build_from_api(user, params)
77
+
78
+ line_item = order.line_items.first
79
+ line_item.variant_id.should == variant_id
80
+ line_item.quantity.should == 5
81
+ end
82
+
83
+ it 'handles exceptions when sku is not found' do
84
+ params = { :line_items_attributes => {
85
+ "0" => { :sku => 'XXX', :quantity => 5 } }}
86
+ expect {
87
+ order = Order.build_from_api(user, params)
88
+ }.to raise_error /XXX/
89
+ end
90
+
91
+ it 'can build an order from API shipping address' do
92
+ params = { :ship_address_attributes => ship_address,
93
+ :line_items_attributes => line_items }
94
+
95
+ order = Order.build_from_api(user, params)
96
+ order.ship_address.address1.should eq '123 Testable Way'
97
+ end
98
+
99
+ it 'can build an order from API with country attributes' do
100
+ ship_address.delete(:country_id)
101
+ ship_address[:country] = { 'iso' => 'US' }
102
+ params = { :ship_address_attributes => ship_address,
103
+ :line_items_attributes => line_items }
104
+
105
+ order = Order.build_from_api(user, params)
106
+ order.ship_address.country.iso.should eq 'US'
107
+ end
108
+
109
+ it 'handles country lookup exceptions' do
110
+ ship_address.delete(:country_id)
111
+ ship_address[:country] = { 'iso' => 'XXX' }
112
+ params = { :ship_address_attributes => ship_address,
113
+ :line_items_attributes => line_items }
114
+
115
+ expect {
116
+ order = Order.build_from_api(user, params)
117
+ }.to raise_error /XXX/
118
+ end
119
+
120
+ it 'can build an order from API with state attributes' do
121
+ ship_address.delete(:state_id)
122
+ ship_address[:state] = { 'name' => 'Alabama' }
123
+ params = { :ship_address_attributes => ship_address,
124
+ :line_items_attributes => line_items }
125
+
126
+ order = Order.build_from_api(user, params)
127
+ order.ship_address.state.name.should eq 'Alabama'
128
+ end
129
+
130
+ it 'handles state lookup exceptions' do
131
+ ship_address.delete(:state_id)
132
+ ship_address[:state] = { 'name' => 'XXX' }
133
+ params = { :ship_address_attributes => ship_address,
134
+ :line_items_attributes => line_items }
135
+
136
+ expect {
137
+ order = Order.build_from_api(user, params)
138
+ }.to raise_error /XXX/
139
+ end
140
+
141
+ context 'variant not deleted' do
142
+ it 'ensures variant id from api' do
143
+ hash = { sku: variant.sku }
144
+ Order.ensure_variant_id_from_api(hash)
145
+ expect(hash[:variant_id]).to eq variant.id
146
+ end
147
+ end
148
+
149
+ context 'variant was deleted' do
150
+ it 'raise error as variant shouldnt be found' do
151
+ variant.product.destroy
152
+ hash = { sku: variant.sku }
153
+ expect {
154
+ Order.ensure_variant_id_from_api(hash)
155
+ }.to raise_error
156
+ end
157
+ end
158
+
159
+ it 'ensures_country_id for country fields' do
160
+ [:name, :iso, :iso_name, :iso3].each do |field|
161
+ address = { :country => { field => country.send(field) }}
162
+ Order.ensure_country_id_from_api(address)
163
+ address[:country_id].should eq country.id
164
+ end
165
+ end
166
+
167
+ it 'ensures_state_id for state fields' do
168
+ [:name, :abbr].each do |field|
169
+ address = { :state => { field => state.send(field) }}
170
+ Order.ensure_state_id_from_api(address)
171
+ address[:state_id].should eq state.id
172
+ end
173
+ end
174
+
175
+ context "shippments" do
176
+ let(:params) do
177
+ { :shipments_attributes => [
178
+ { :tracking => '123456789',
179
+ :cost => '4.99',
180
+ :shipping_method => shipping_method.name,
181
+ :inventory_units => [{ :sku => sku }]
182
+ }
183
+ ] }
184
+ end
185
+
186
+ it 'ensures variant exists and is not deleted' do
187
+ Order.should_receive(:ensure_variant_id_from_api)
188
+ order = Order.build_from_api(user, params)
189
+ end
190
+
191
+ it 'builds them properly' do
192
+ order = Order.build_from_api(user, params)
193
+
194
+ shipment = order.shipments.first
195
+ shipment.inventory_units.first.variant_id.should eq product.master.id
196
+ shipment.tracking.should eq '123456789'
197
+ shipment.shipping_rates.first.cost.should eq 4.99
198
+ end
199
+ end
200
+
201
+ it 'handles shipment building exceptions' do
202
+ params = { :shipments_attributes => [{ tracking: '123456789',
203
+ cost: '4.99',
204
+ shipping_method: 'XXX',
205
+ inventory_units: [{ sku: sku }]
206
+ }] }
207
+ expect {
208
+ order = Order.build_from_api(user, params)
209
+ }.to raise_error /XXX/
210
+ end
211
+
212
+ it 'adds adjustments' do
213
+ params = { :adjustments_attributes => [
214
+ { "label" => "Shipping Discount", "amount" => "-4.99" },
215
+ { "label" => "Promotion Discount", "amount" => "-3.00" }] }
216
+
217
+ order = Order.build_from_api(user, params)
218
+ order.adjustments.all?(&:finalized?).should be_true
219
+ order.adjustments.first.label.should eq 'Shipping Discount'
220
+ order.adjustments.first.amount.should eq -4.99
221
+ end
222
+
223
+ it 'handles adjustment building exceptions' do
224
+ params = { :adjustments_attributes => [
225
+ { "amount" => "XXX" },
226
+ { "label" => "Promotion Discount", "amount" => "-3.00" }] }
227
+
228
+ expect {
229
+ order = Order.build_from_api(user, params)
230
+ }.to raise_error /XXX/
231
+ end
232
+
233
+ it 'builds a payment' do
234
+ params = { :payments_attributes => [{ amount: '4.99',
235
+ payment_method: payment_method.name }] }
236
+ order = Order.build_from_api(user, params)
237
+ order.payments.first.amount.should eq 4.99
238
+ end
239
+
240
+ it 'handles payment building exceptions' do
241
+ params = { :payments_attributes => [{ amount: '4.99',
242
+ payment_method: 'XXX' }] }
243
+ expect {
244
+ order = Order.build_from_api(user, params)
245
+ }.to raise_error /XXX/
246
+ end
17
247
  end
18
248
  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.4
4
+ version: 2.0.5
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-08-05 00:00:00.000000000 Z
11
+ date: 2013-09-16 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.4
19
+ version: 2.0.5
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.4
26
+ version: 2.0.5
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rabl
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -244,7 +244,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
244
244
  version: '0'
245
245
  requirements: []
246
246
  rubyforge_project:
247
- rubygems_version: 2.0.0
247
+ rubygems_version: 2.1.0
248
248
  signing_key:
249
249
  specification_version: 4
250
250
  summary: Spree's API