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 +4 -4
- data/CHANGELOG.md +15 -3
- data/app/controllers/spree/api/addresses_controller.rb +21 -4
- data/app/controllers/spree/api/checkouts_controller.rb +22 -5
- data/app/controllers/spree/api/orders_controller.rb +7 -1
- data/app/controllers/spree/api/stock_items_controller.rb +4 -1
- data/app/controllers/spree/api/taxons_controller.rb +4 -2
- data/app/controllers/spree/api/variants_controller.rb +1 -1
- data/app/helpers/spree/api/api_helpers.rb +4 -0
- data/app/models/spree/order_decorator.rb +143 -7
- data/app/views/spree/api/addresses/show.v1.rabl +2 -4
- data/app/views/spree/api/taxons/index.v1.rabl +10 -4
- data/config/routes.rb +3 -1
- data/spec/controllers/spree/api/addresses_controller_spec.rb +10 -8
- data/spec/controllers/spree/api/checkouts_controller_spec.rb +13 -2
- data/spec/controllers/spree/api/orders_controller_spec.rb +30 -3
- data/spec/controllers/spree/api/stock_items_controller_spec.rb +20 -2
- data/spec/controllers/spree/api/taxons_controller_spec.rb +18 -6
- data/spec/models/spree/order_spec.rb +235 -5
- metadata +5 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0c5fb9fd878e6c935137a8f09d6b4cffa35f78db
|
4
|
+
data.tar.gz: aef11d5c34c3cfa8f55c78fa0f987e493220618c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4ccb7dc808ccfe6a0badbcca88f2fee1c7f40bff832051b851384be324fbe1c9d97c128b9447d18c6d836a1f77b921fa8dab75c19be1ad73a48c68ea6f2e3652
|
7
|
+
data.tar.gz: 560ebb4f8b5019b23c3686e8f92131b5ec4a692923e6173e0c93b6740568527b2466b039787c84503c07908caf008a9aee2971cb7434514cb87df920eaed3e37
|
data/CHANGELOG.md
CHANGED
@@ -1,6 +1,4 @@
|
|
1
|
-
## Spree 2.0.
|
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
|
-
@
|
7
|
-
|
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
|
-
@
|
13
|
-
|
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
|
-
|
5
|
-
before_filter :
|
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, :
|
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.
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
9
|
-
|
10
|
-
|
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 =
|
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
|
-
|
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
|
3
|
-
|
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
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
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
|
-
|
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
|
39
|
+
context "on an address that does not belong to this order" do
|
39
40
|
before do
|
40
|
-
|
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 => {
|
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.
|
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.
|
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(:
|
6
|
-
let(:
|
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
|
-
|
9
|
-
|
10
|
-
|
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
|
+
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-
|
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.
|
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.
|
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.
|
247
|
+
rubygems_version: 2.1.0
|
248
248
|
signing_key:
|
249
249
|
specification_version: 4
|
250
250
|
summary: Spree's API
|