spree_api 2.0.4 → 2.0.5

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