solidus_api 1.0.0.pre
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 +7 -0
- data/.gitignore +17 -0
- data/CHANGELOG.md +1 -0
- data/Gemfile +5 -0
- data/LICENSE +27 -0
- data/Rakefile +16 -0
- data/app/controllers/spree/api/addresses_controller.rb +43 -0
- data/app/controllers/spree/api/base_controller.rb +189 -0
- data/app/controllers/spree/api/checkouts_controller.rb +133 -0
- data/app/controllers/spree/api/classifications_controller.rb +18 -0
- data/app/controllers/spree/api/config_controller.rb +6 -0
- data/app/controllers/spree/api/countries_controller.rb +23 -0
- data/app/controllers/spree/api/credit_cards_controller.rb +25 -0
- data/app/controllers/spree/api/images_controller.rb +47 -0
- data/app/controllers/spree/api/inventory_units_controller.rb +52 -0
- data/app/controllers/spree/api/line_items_controller.rb +74 -0
- data/app/controllers/spree/api/option_types_controller.rb +49 -0
- data/app/controllers/spree/api/option_values_controller.rb +58 -0
- data/app/controllers/spree/api/orders_controller.rb +155 -0
- data/app/controllers/spree/api/payments_controller.rb +81 -0
- data/app/controllers/spree/api/product_properties_controller.rb +72 -0
- data/app/controllers/spree/api/products_controller.rb +129 -0
- data/app/controllers/spree/api/promotions_controller.rb +26 -0
- data/app/controllers/spree/api/properties_controller.rb +71 -0
- data/app/controllers/spree/api/return_authorizations_controller.rb +71 -0
- data/app/controllers/spree/api/shipments_controller.rb +172 -0
- data/app/controllers/spree/api/states_controller.rb +35 -0
- data/app/controllers/spree/api/stock_items_controller.rb +84 -0
- data/app/controllers/spree/api/stock_locations_controller.rb +50 -0
- data/app/controllers/spree/api/stock_movements_controller.rb +42 -0
- data/app/controllers/spree/api/stock_transfers_controller.rb +19 -0
- data/app/controllers/spree/api/store_credit_events_controller.rb +9 -0
- data/app/controllers/spree/api/stores_controller.rb +55 -0
- data/app/controllers/spree/api/taxonomies_controller.rb +64 -0
- data/app/controllers/spree/api/taxons_controller.rb +93 -0
- data/app/controllers/spree/api/transfer_items_controller.rb +42 -0
- data/app/controllers/spree/api/users_controller.rb +56 -0
- data/app/controllers/spree/api/variants_controller.rb +75 -0
- data/app/controllers/spree/api/zones_controller.rb +50 -0
- data/app/helpers/spree/api/api_helpers.rb +190 -0
- data/app/models/spree/api_configuration.rb +5 -0
- data/app/models/spree/option_value_decorator.rb +9 -0
- data/app/views/spree/api/addresses/show.v1.rabl +10 -0
- data/app/views/spree/api/adjustments/show.v1.rabl +4 -0
- data/app/views/spree/api/config/money.v1.rabl +2 -0
- data/app/views/spree/api/config/show.v1.rabl +2 -0
- data/app/views/spree/api/countries/index.v1.rabl +7 -0
- data/app/views/spree/api/countries/show.v1.rabl +5 -0
- data/app/views/spree/api/credit_cards/index.v1.rabl +7 -0
- data/app/views/spree/api/credit_cards/show.v1.rabl +3 -0
- data/app/views/spree/api/errors/gateway_error.v1.rabl +2 -0
- data/app/views/spree/api/errors/invalid_api_key.v1.rabl +2 -0
- data/app/views/spree/api/errors/invalid_resource.v1.rabl +3 -0
- data/app/views/spree/api/errors/must_specify_api_key.v1.rabl +2 -0
- data/app/views/spree/api/errors/not_found.v1.rabl +2 -0
- data/app/views/spree/api/errors/unauthorized.v1.rabl +2 -0
- data/app/views/spree/api/errors/variant_not_in_stock_transfer.v1.rabl +2 -0
- data/app/views/spree/api/images/index.v1.rabl +4 -0
- data/app/views/spree/api/images/show.v1.rabl +6 -0
- data/app/views/spree/api/inventory_units/show.rabl +2 -0
- data/app/views/spree/api/line_items/new.v1.rabl +3 -0
- data/app/views/spree/api/line_items/show.v1.rabl +15 -0
- data/app/views/spree/api/option_types/index.v1.rabl +3 -0
- data/app/views/spree/api/option_types/show.v1.rabl +5 -0
- data/app/views/spree/api/option_values/index.v1.rabl +3 -0
- data/app/views/spree/api/option_values/show.v1.rabl +2 -0
- data/app/views/spree/api/orders/address.v1.rabl +0 -0
- data/app/views/spree/api/orders/canceled.v1.rabl +0 -0
- data/app/views/spree/api/orders/cart.v1.rabl +0 -0
- data/app/views/spree/api/orders/complete.v1.rabl +0 -0
- data/app/views/spree/api/orders/could_not_apply_coupon.v1.rabl +2 -0
- data/app/views/spree/api/orders/could_not_transition.v1.rabl +3 -0
- data/app/views/spree/api/orders/expected_total_mismatch.v1.rabl +2 -0
- data/app/views/spree/api/orders/index.v1.rabl +7 -0
- data/app/views/spree/api/orders/invalid_shipping_method.v1.rabl +2 -0
- data/app/views/spree/api/orders/mine.v1.rabl +9 -0
- data/app/views/spree/api/orders/order.v1.rabl +9 -0
- data/app/views/spree/api/orders/payment.v1.rabl +3 -0
- data/app/views/spree/api/orders/show.v1.rabl +52 -0
- data/app/views/spree/api/payments/credit_over_limit.v1.rabl +2 -0
- data/app/views/spree/api/payments/index.v1.rabl +7 -0
- data/app/views/spree/api/payments/new.v1.rabl +5 -0
- data/app/views/spree/api/payments/show.v1.rabl +2 -0
- data/app/views/spree/api/payments/update_forbidden.v1.rabl +2 -0
- data/app/views/spree/api/product_properties/index.v1.rabl +7 -0
- data/app/views/spree/api/product_properties/new.v1.rabl +2 -0
- data/app/views/spree/api/product_properties/show.v1.rabl +2 -0
- data/app/views/spree/api/products/index.v1.rabl +9 -0
- data/app/views/spree/api/products/new.v1.rabl +3 -0
- data/app/views/spree/api/products/product.v1.rabl +1 -0
- data/app/views/spree/api/products/show.v1.rabl +31 -0
- data/app/views/spree/api/promotions/handler.v1.rabl +5 -0
- data/app/views/spree/api/promotions/show.v1.rabl +2 -0
- data/app/views/spree/api/properties/index.v1.rabl +7 -0
- data/app/views/spree/api/properties/new.v1.rabl +2 -0
- data/app/views/spree/api/properties/show.v1.rabl +2 -0
- data/app/views/spree/api/return_authorizations/index.v1.rabl +7 -0
- data/app/views/spree/api/return_authorizations/new.v1.rabl +3 -0
- data/app/views/spree/api/return_authorizations/show.v1.rabl +2 -0
- data/app/views/spree/api/shared/stock_location_required.v1.rabl +2 -0
- data/app/views/spree/api/shipments/big.v1.rabl +48 -0
- data/app/views/spree/api/shipments/cannot_ready_shipment.v1.rabl +2 -0
- data/app/views/spree/api/shipments/mine.v1.rabl +9 -0
- data/app/views/spree/api/shipments/show.v1.rabl +32 -0
- data/app/views/spree/api/shipments/small.v1.rabl +37 -0
- data/app/views/spree/api/shipping_rates/show.v1.rabl +2 -0
- data/app/views/spree/api/states/index.v1.rabl +14 -0
- data/app/views/spree/api/states/show.v1.rabl +2 -0
- data/app/views/spree/api/stock_items/index.v1.rabl +7 -0
- data/app/views/spree/api/stock_items/show.v1.rabl +5 -0
- data/app/views/spree/api/stock_locations/index.v1.rabl +7 -0
- data/app/views/spree/api/stock_locations/show.v1.rabl +8 -0
- data/app/views/spree/api/stock_movements/index.v1.rabl +7 -0
- data/app/views/spree/api/stock_movements/show.v1.rabl +5 -0
- data/app/views/spree/api/stock_transfers/receive.v1.rabl +5 -0
- data/app/views/spree/api/store_credit_events/mine.v1.rabl +10 -0
- data/app/views/spree/api/stores/index.v1.rabl +4 -0
- data/app/views/spree/api/stores/show.v1.rabl +2 -0
- data/app/views/spree/api/taxonomies/index.v1.rabl +7 -0
- data/app/views/spree/api/taxonomies/jstree.rabl +8 -0
- data/app/views/spree/api/taxonomies/nested.v1.rabl +11 -0
- data/app/views/spree/api/taxonomies/new.v1.rabl +3 -0
- data/app/views/spree/api/taxonomies/show.v1.rabl +15 -0
- data/app/views/spree/api/taxons/index.v1.rabl +12 -0
- data/app/views/spree/api/taxons/jstree.rabl +8 -0
- data/app/views/spree/api/taxons/new.v1.rabl +3 -0
- data/app/views/spree/api/taxons/show.v1.rabl +6 -0
- data/app/views/spree/api/taxons/taxons.v1.rabl +5 -0
- data/app/views/spree/api/transfer_items/show.v1.rabl +6 -0
- data/app/views/spree/api/users/index.v1.rabl +7 -0
- data/app/views/spree/api/users/new.v1.rabl +3 -0
- data/app/views/spree/api/users/show.v1.rabl +10 -0
- data/app/views/spree/api/variants/big.v1.rabl +17 -0
- data/app/views/spree/api/variants/index.v1.rabl +9 -0
- data/app/views/spree/api/variants/new.v1.rabl +2 -0
- data/app/views/spree/api/variants/show.v1.rabl +3 -0
- data/app/views/spree/api/variants/small.v1.rabl +17 -0
- data/app/views/spree/api/zones/index.v1.rabl +7 -0
- data/app/views/spree/api/zones/show.v1.rabl +6 -0
- data/config/initializers/metal_load_paths.rb +1 -0
- data/config/locales/en.yml +29 -0
- data/config/routes.rb +139 -0
- data/db/migrate/20100107141738_add_api_key_to_spree_users.rb +7 -0
- data/db/migrate/20120411123334_resize_api_key_field.rb +7 -0
- data/db/migrate/20120530054546_rename_api_key_to_spree_api_key.rb +7 -0
- data/db/migrate/20131017162334_add_index_to_user_spree_api_key.rb +7 -0
- data/lib/solidus_api.rb +1 -0
- data/lib/spree/api/engine.rb +38 -0
- data/lib/spree/api/responders/rabl_template.rb +31 -0
- data/lib/spree/api/responders.rb +11 -0
- data/lib/spree/api/testing_support/caching.rb +10 -0
- data/lib/spree/api/testing_support/helpers.rb +44 -0
- data/lib/spree/api/testing_support/setup.rb +16 -0
- data/lib/spree/api.rb +10 -0
- data/lib/spree_api.rb +3 -0
- data/script/rails +9 -0
- data/solidus_api.gemspec +21 -0
- data/spec/controllers/spree/api/addresses_controller_spec.rb +56 -0
- data/spec/controllers/spree/api/base_controller_spec.rb +164 -0
- data/spec/controllers/spree/api/checkouts_controller_spec.rb +386 -0
- data/spec/controllers/spree/api/classifications_controller_spec.rb +48 -0
- data/spec/controllers/spree/api/config_controller_spec.rb +23 -0
- data/spec/controllers/spree/api/countries_controller_spec.rb +48 -0
- data/spec/controllers/spree/api/credit_cards_controller_spec.rb +80 -0
- data/spec/controllers/spree/api/images_controller_spec.rb +93 -0
- data/spec/controllers/spree/api/inventory_units_controller_spec.rb +50 -0
- data/spec/controllers/spree/api/line_items_controller_spec.rb +186 -0
- data/spec/controllers/spree/api/option_types_controller_spec.rb +116 -0
- data/spec/controllers/spree/api/option_values_controller_spec.rb +135 -0
- data/spec/controllers/spree/api/orders_controller_spec.rb +759 -0
- data/spec/controllers/spree/api/payments_controller_spec.rb +254 -0
- data/spec/controllers/spree/api/product_properties_controller_spec.rb +116 -0
- data/spec/controllers/spree/api/products_controller_spec.rb +454 -0
- data/spec/controllers/spree/api/promotion_application_spec.rb +50 -0
- data/spec/controllers/spree/api/promotions_controller_spec.rb +64 -0
- data/spec/controllers/spree/api/properties_controller_spec.rb +102 -0
- data/spec/controllers/spree/api/return_authorizations_controller_spec.rb +173 -0
- data/spec/controllers/spree/api/shipments_controller_spec.rb +252 -0
- data/spec/controllers/spree/api/states_controller_spec.rb +82 -0
- data/spec/controllers/spree/api/stock_items_controller_spec.rb +307 -0
- data/spec/controllers/spree/api/stock_locations_controller_spec.rb +172 -0
- data/spec/controllers/spree/api/stock_movements_controller_spec.rb +84 -0
- data/spec/controllers/spree/api/stock_transfers_controller_spec.rb +83 -0
- data/spec/controllers/spree/api/store_credit_events_controller_spec.rb +68 -0
- data/spec/controllers/spree/api/stores_controller_spec.rb +133 -0
- data/spec/controllers/spree/api/taxonomies_controller_spec.rb +114 -0
- data/spec/controllers/spree/api/taxons_controller_spec.rb +177 -0
- data/spec/controllers/spree/api/transfer_items_controller_spec.rb +152 -0
- data/spec/controllers/spree/api/unauthenticated_products_controller_spec.rb +26 -0
- data/spec/controllers/spree/api/users_controller_spec.rb +153 -0
- data/spec/controllers/spree/api/variants_controller_spec.rb +235 -0
- data/spec/controllers/spree/api/zones_controller_spec.rb +115 -0
- data/spec/features/checkout_spec.rb +187 -0
- data/spec/fixtures/thinking-cat.jpg +0 -0
- data/spec/models/spree/legacy_user_spec.rb +45 -0
- data/spec/requests/rabl_cache_spec.rb +32 -0
- data/spec/shared_examples/protect_product_actions.rb +17 -0
- data/spec/spec_helper.rb +60 -0
- data/spec/support/controller_hacks.rb +38 -0
- data/spec/support/database_cleaner.rb +14 -0
- data/spec/support/have_attributes_matcher.rb +13 -0
- metadata +334 -0
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
module Spree
|
|
4
|
+
describe Api::StockItemsController, :type => :controller do
|
|
5
|
+
render_views
|
|
6
|
+
|
|
7
|
+
let!(:stock_location) { create(:stock_location_with_items) }
|
|
8
|
+
let!(:stock_item) { stock_location.stock_items.order(:id).first }
|
|
9
|
+
let!(:attributes) { [:id, :count_on_hand, :backorderable,
|
|
10
|
+
:stock_location_id, :variant_id] }
|
|
11
|
+
|
|
12
|
+
before do
|
|
13
|
+
stub_authentication!
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
context "as a normal user" do
|
|
17
|
+
describe "#index" do
|
|
18
|
+
it "can list stock items for an active stock location" do
|
|
19
|
+
api_get :index, stock_location_id: stock_location.to_param
|
|
20
|
+
expect(response).to be_success
|
|
21
|
+
json_response['stock_items'].first.should have_attributes(attributes)
|
|
22
|
+
json_response['stock_items'].first['variant']['sku'].should match /\ASKU-\d+\z/
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
it "cannot list stock items for an inactive stock location" do
|
|
26
|
+
stock_location.update_attributes!(active: false)
|
|
27
|
+
api_get :index, stock_location_id: stock_location.to_param
|
|
28
|
+
expect(response).to be_not_found
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
describe "#show" do
|
|
33
|
+
it "can see a stock item for an active stock location" do
|
|
34
|
+
api_get :show, stock_location_id: stock_location.to_param, id: stock_item.to_param
|
|
35
|
+
json_response.should have_attributes(attributes)
|
|
36
|
+
json_response['count_on_hand'].should eq stock_item.count_on_hand
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
it "cannot see a stock item for an inactive stock location" do
|
|
40
|
+
stock_location.update_attributes!(active: false)
|
|
41
|
+
api_get :show, stock_location_id: stock_location.to_param, id: stock_item.to_param
|
|
42
|
+
response.status.should == 404
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
describe "#create" do
|
|
47
|
+
it "cannot create a stock item" do
|
|
48
|
+
variant = create(:variant)
|
|
49
|
+
params = {
|
|
50
|
+
stock_location_id: stock_location.to_param,
|
|
51
|
+
stock_item: {
|
|
52
|
+
variant_id: variant.id,
|
|
53
|
+
count_on_hand: '20'
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
api_post :create, params
|
|
58
|
+
response.status.should == 404
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
describe "#update" do
|
|
63
|
+
it "cannot update a stock item" do
|
|
64
|
+
api_put :update, stock_location_id: stock_location.to_param, id: stock_item.to_param
|
|
65
|
+
response.status.should == 404
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
describe "#destroy" do
|
|
70
|
+
it "cannot destroy a stock item" do
|
|
71
|
+
api_delete :destroy, stock_location_id: stock_location.to_param, id: stock_item.to_param
|
|
72
|
+
response.status.should == 404
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
context "as an admin" do
|
|
78
|
+
sign_in_as_admin!
|
|
79
|
+
|
|
80
|
+
it 'cannot list of stock items' do
|
|
81
|
+
api_get :index, stock_location_id: stock_location.to_param
|
|
82
|
+
expect(json_response['stock_items'].first).to have_attributes(attributes)
|
|
83
|
+
expect(json_response['stock_items'].first['variant']['sku']).to include 'SKU'
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
it 'requires a stock_location_id to be passed as a parameter' do
|
|
87
|
+
api_get :index
|
|
88
|
+
expect(json_response['error']).to match(/stock_location_id parameter must be provided/)
|
|
89
|
+
expect(response.status).to eq(422)
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
it 'can control the page size through a parameter' do
|
|
93
|
+
api_get :index, stock_location_id: stock_location.to_param, per_page: 1
|
|
94
|
+
expect(json_response['count']).to eq(1)
|
|
95
|
+
expect(json_response['current_page']).to eq(1)
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
it 'can query the results through a paramter' do
|
|
99
|
+
stock_item.update_column(:count_on_hand, 30)
|
|
100
|
+
api_get :index, stock_location_id: stock_location.to_param, q: { count_on_hand_eq: '30' }
|
|
101
|
+
expect(json_response['count']).to eq(1)
|
|
102
|
+
expect(json_response['stock_items'].first['count_on_hand']).to eq 30
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
it 'gets a stock item' do
|
|
106
|
+
api_get :show, stock_location_id: stock_location.to_param, id: stock_item.to_param
|
|
107
|
+
expect(json_response).to have_attributes(attributes)
|
|
108
|
+
expect(json_response['count_on_hand']).to eq stock_item.count_on_hand
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
context 'creating a stock item' do
|
|
112
|
+
let!(:variant) do
|
|
113
|
+
variant = create(:variant)
|
|
114
|
+
# Creating a variant also creates stock items.
|
|
115
|
+
# We don't want any to exist (as they would conflict with what we're about to create)
|
|
116
|
+
StockItem.delete_all
|
|
117
|
+
variant
|
|
118
|
+
end
|
|
119
|
+
let(:count_on_hand) { '20' }
|
|
120
|
+
let(:params) do
|
|
121
|
+
{
|
|
122
|
+
stock_location_id: stock_location.to_param,
|
|
123
|
+
stock_item: {
|
|
124
|
+
variant_id: variant.id,
|
|
125
|
+
count_on_hand: count_on_hand
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
subject { api_post :create, params }
|
|
131
|
+
|
|
132
|
+
it 'can create a new stock item' do
|
|
133
|
+
subject
|
|
134
|
+
expect(response.status).to eq 201
|
|
135
|
+
expect(json_response).to have_attributes(attributes)
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
it 'creates a stock movement' do
|
|
139
|
+
expect { subject }.to change { Spree::StockMovement.count }.by(1)
|
|
140
|
+
expect(assigns(:stock_movement).quantity).to eq 20
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
context 'variant tracks inventory' do
|
|
144
|
+
before do
|
|
145
|
+
expect(variant.track_inventory).to eq true
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
it "sets the stock item's count_on_hand" do
|
|
149
|
+
subject
|
|
150
|
+
expect(assigns(:stock_item).count_on_hand).to eq 20
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
context 'variant does not track inventory' do
|
|
155
|
+
before do
|
|
156
|
+
variant.update_attributes(track_inventory: false)
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
it "doesn't set the stock item's count_on_hand" do
|
|
160
|
+
subject
|
|
161
|
+
expect(assigns(:stock_item).count_on_hand).to eq 0
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
context "attempting to set negative inventory" do
|
|
166
|
+
let(:count_on_hand) { '-1' }
|
|
167
|
+
|
|
168
|
+
it "does not allow negative inventory for the stock item" do
|
|
169
|
+
subject
|
|
170
|
+
expect(response.status).to eq 422
|
|
171
|
+
expect(response.body).to match Spree.t(:stock_not_below_zero)
|
|
172
|
+
expect(assigns(:stock_item).count_on_hand).to eq 0
|
|
173
|
+
end
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
context 'updating a stock item' do
|
|
178
|
+
before do
|
|
179
|
+
expect(stock_item.count_on_hand).to eq 10
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
subject { api_put :update, params }
|
|
183
|
+
|
|
184
|
+
context 'adjusting count_on_hand' do
|
|
185
|
+
let(:count_on_hand) { 40 }
|
|
186
|
+
let(:params) do
|
|
187
|
+
{
|
|
188
|
+
id: stock_item.to_param,
|
|
189
|
+
stock_item: {
|
|
190
|
+
count_on_hand: count_on_hand,
|
|
191
|
+
backorderable: true
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
it 'can update a stock item to add new inventory' do
|
|
197
|
+
subject
|
|
198
|
+
expect(response.status).to eq 200
|
|
199
|
+
expect(json_response['count_on_hand']).to eq 50
|
|
200
|
+
expect(json_response['backorderable']).to eq true
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
it 'creates a stock movement for the adjusted quantity' do
|
|
204
|
+
expect { subject }.to change { Spree::StockMovement.count }.by(1)
|
|
205
|
+
expect(Spree::StockMovement.last.quantity).to eq 40
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
context 'tracking inventory' do
|
|
209
|
+
before do
|
|
210
|
+
expect(stock_item.should_track_inventory?).to eq true
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
it "sets the stock item's count_on_hand" do
|
|
214
|
+
subject
|
|
215
|
+
expect(assigns(:stock_item).count_on_hand).to eq 50
|
|
216
|
+
end
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
context 'not tracking inventory' do
|
|
220
|
+
before do
|
|
221
|
+
stock_item.variant.update_attributes(track_inventory: false)
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
it "doesn't set the stock item's count_on_hand" do
|
|
225
|
+
subject
|
|
226
|
+
expect(assigns(:stock_item).count_on_hand).to eq 10
|
|
227
|
+
end
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
context "attempting to set negative inventory" do
|
|
231
|
+
let(:count_on_hand) { '-11' }
|
|
232
|
+
|
|
233
|
+
it "does not allow negative inventory for the stock item" do
|
|
234
|
+
subject
|
|
235
|
+
expect(response.status).to eq 422
|
|
236
|
+
expect(response.body).to match Spree.t(:stock_not_below_zero)
|
|
237
|
+
expect(assigns(:stock_item).count_on_hand).to eq 10
|
|
238
|
+
end
|
|
239
|
+
end
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
context 'setting count_on_hand' do
|
|
243
|
+
let(:count_on_hand) { 40 }
|
|
244
|
+
let(:params) do
|
|
245
|
+
{
|
|
246
|
+
id: stock_item.to_param,
|
|
247
|
+
stock_item: {
|
|
248
|
+
count_on_hand: count_on_hand,
|
|
249
|
+
force: true,
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
it 'can set a stock item to modify the current inventory' do
|
|
255
|
+
subject
|
|
256
|
+
expect(response.status).to eq 200
|
|
257
|
+
expect(json_response['count_on_hand']).to eq 40
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
it 'creates a stock movement for the adjusted quantity' do
|
|
261
|
+
expect { subject }.to change { Spree::StockMovement.count }.by(1)
|
|
262
|
+
expect(assigns(:stock_movement).quantity).to eq 30
|
|
263
|
+
end
|
|
264
|
+
|
|
265
|
+
context 'tracking inventory' do
|
|
266
|
+
before do
|
|
267
|
+
expect(stock_item.should_track_inventory?).to eq true
|
|
268
|
+
end
|
|
269
|
+
|
|
270
|
+
it "updates the stock item's count_on_hand" do
|
|
271
|
+
subject
|
|
272
|
+
expect(assigns(:stock_item).count_on_hand).to eq 40
|
|
273
|
+
end
|
|
274
|
+
end
|
|
275
|
+
|
|
276
|
+
context 'not tracking inventory' do
|
|
277
|
+
before do
|
|
278
|
+
stock_item.variant.update_attributes(track_inventory: false)
|
|
279
|
+
end
|
|
280
|
+
|
|
281
|
+
it "doesn't update the stock item's count_on_hand" do
|
|
282
|
+
subject
|
|
283
|
+
expect(assigns(:stock_item).count_on_hand).to eq 10
|
|
284
|
+
end
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
context "attempting to set negative inventory" do
|
|
288
|
+
let(:count_on_hand) { '-1' }
|
|
289
|
+
|
|
290
|
+
it "does not allow negative inventory for the stock item" do
|
|
291
|
+
subject
|
|
292
|
+
expect(response.status).to eq 422
|
|
293
|
+
expect(response.body).to match Spree.t(:stock_not_below_zero)
|
|
294
|
+
expect(assigns(:stock_item).count_on_hand).to eq 10
|
|
295
|
+
end
|
|
296
|
+
end
|
|
297
|
+
end
|
|
298
|
+
end
|
|
299
|
+
|
|
300
|
+
it 'can delete a stock item' do
|
|
301
|
+
api_delete :destroy, id: stock_item.to_param
|
|
302
|
+
expect(response.status).to eq(204)
|
|
303
|
+
expect { Spree::StockItem.find(stock_item.id) }.to raise_error(ActiveRecord::RecordNotFound)
|
|
304
|
+
end
|
|
305
|
+
end
|
|
306
|
+
end
|
|
307
|
+
end
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
module Spree
|
|
4
|
+
describe Api::StockLocationsController, :type => :controller do
|
|
5
|
+
render_views
|
|
6
|
+
|
|
7
|
+
let!(:stock_location) { create(:stock_location) }
|
|
8
|
+
let!(:attributes) { [:id, :name, :address1, :address2, :city, :state_id, :state_name, :country_id, :zipcode, :phone, :active] }
|
|
9
|
+
|
|
10
|
+
before do
|
|
11
|
+
stub_authentication!
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
context "as a user" do
|
|
15
|
+
describe "#index" do
|
|
16
|
+
it "can see active stock locations" do
|
|
17
|
+
api_get :index
|
|
18
|
+
expect(response).to be_success
|
|
19
|
+
stock_locations = json_response['stock_locations'].map { |sl| sl['name'] }
|
|
20
|
+
expect(stock_locations).to include stock_location.name
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it "cannot see inactive stock locations" do
|
|
24
|
+
stock_location.update_attributes!(active: false)
|
|
25
|
+
api_get :index
|
|
26
|
+
expect(response).to be_success
|
|
27
|
+
stock_locations = json_response['stock_locations'].map { |sl| sl['name'] }
|
|
28
|
+
expect(stock_locations).not_to include stock_location.name
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
describe "#show" do
|
|
33
|
+
it "can see active stock locations" do
|
|
34
|
+
api_get :show, id: stock_location.id
|
|
35
|
+
expect(response).to be_success
|
|
36
|
+
expect(json_response['name']).to eq stock_location.name
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
it "cannot see inactive stock locations" do
|
|
40
|
+
stock_location.update_attributes!(active: false)
|
|
41
|
+
api_get :show, id: stock_location.id
|
|
42
|
+
expect(response).to be_not_found
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
describe "#create" do
|
|
47
|
+
it "cannot create a new stock location" do
|
|
48
|
+
params = {
|
|
49
|
+
stock_location: {
|
|
50
|
+
name: "North Pole",
|
|
51
|
+
active: true
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
api_post :create, params
|
|
56
|
+
response.status.should == 401
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
describe "#update" do
|
|
61
|
+
it "cannot update a stock location" do
|
|
62
|
+
api_put :update, :stock_location => { :name => "South Pole" }, :id => stock_location.to_param
|
|
63
|
+
response.status.should == 401
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
describe "#destroy" do
|
|
68
|
+
it "cannot delete a stock location" do
|
|
69
|
+
api_put :destroy, :id => stock_location.to_param
|
|
70
|
+
response.status.should == 401
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
context "as an admin" do
|
|
76
|
+
sign_in_as_admin!
|
|
77
|
+
|
|
78
|
+
describe "#index" do
|
|
79
|
+
it "can see active stock locations" do
|
|
80
|
+
api_get :index
|
|
81
|
+
expect(response).to be_success
|
|
82
|
+
stock_locations = json_response['stock_locations'].map { |sl| sl['name'] }
|
|
83
|
+
expect(stock_locations).to include stock_location.name
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
it "can see inactive stock locations" do
|
|
87
|
+
stock_location.update_attributes!(active: false)
|
|
88
|
+
api_get :index
|
|
89
|
+
expect(response).to be_success
|
|
90
|
+
stock_locations = json_response['stock_locations'].map { |sl| sl['name'] }
|
|
91
|
+
expect(stock_locations).to include stock_location.name
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
it "gets stock location information" do
|
|
95
|
+
api_get :index
|
|
96
|
+
json_response['stock_locations'].first.should have_attributes(attributes)
|
|
97
|
+
json_response['stock_locations'].first['country'].should_not be_nil
|
|
98
|
+
json_response['stock_locations'].first['state'].should_not be_nil
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
it 'can control the page size through a parameter' do
|
|
102
|
+
create(:stock_location)
|
|
103
|
+
api_get :index, per_page: 1
|
|
104
|
+
json_response['count'].should == 1
|
|
105
|
+
json_response['current_page'].should == 1
|
|
106
|
+
json_response['pages'].should == 2
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
it 'can query the results through a paramter' do
|
|
110
|
+
expected_result = create(:stock_location, name: 'South America')
|
|
111
|
+
api_get :index, q: { name_cont: 'south' }
|
|
112
|
+
json_response['count'].should == 1
|
|
113
|
+
json_response['stock_locations'].first['name'].should eq expected_result.name
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
describe "#show" do
|
|
119
|
+
it "can see active stock locations" do
|
|
120
|
+
api_get :show, id: stock_location.id
|
|
121
|
+
expect(response).to be_success
|
|
122
|
+
expect(json_response['name']).to eq stock_location.name
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
it "can see inactive stock locations" do
|
|
126
|
+
stock_location.update_attributes!(active: false)
|
|
127
|
+
api_get :show, id: stock_location.id
|
|
128
|
+
expect(response).to be_success
|
|
129
|
+
expect(json_response['name']).to eq stock_location.name
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
describe "#create" do
|
|
134
|
+
it "can create a new stock location" do
|
|
135
|
+
params = {
|
|
136
|
+
stock_location: {
|
|
137
|
+
name: "North Pole",
|
|
138
|
+
active: true
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
api_post :create, params
|
|
143
|
+
response.status.should == 201
|
|
144
|
+
json_response.should have_attributes(attributes)
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
describe "#update" do
|
|
149
|
+
it "can update a stock location" do
|
|
150
|
+
params = {
|
|
151
|
+
id: stock_location.to_param,
|
|
152
|
+
stock_location: {
|
|
153
|
+
name: "South Pole"
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
api_put :update, params
|
|
158
|
+
response.status.should == 200
|
|
159
|
+
json_response['name'].should eq 'South Pole'
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
describe "#destroy" do
|
|
164
|
+
it "can delete a stock location" do
|
|
165
|
+
api_delete :destroy, id: stock_location.to_param
|
|
166
|
+
response.status.should == 204
|
|
167
|
+
lambda { stock_location.reload }.should raise_error(ActiveRecord::RecordNotFound)
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
end
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
module Spree
|
|
4
|
+
describe Api::StockMovementsController, :type => :controller do
|
|
5
|
+
render_views
|
|
6
|
+
|
|
7
|
+
let!(:stock_location) { create(:stock_location_with_items) }
|
|
8
|
+
let!(:stock_item) { stock_location.stock_items.order(:id).first }
|
|
9
|
+
let!(:stock_movement) { create(:stock_movement, stock_item: stock_item) }
|
|
10
|
+
let!(:attributes) { [:id, :quantity, :stock_item_id] }
|
|
11
|
+
|
|
12
|
+
before do
|
|
13
|
+
stub_authentication!
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
context 'as a user' do
|
|
17
|
+
it 'cannot see a list of stock movements' do
|
|
18
|
+
api_get :index, stock_location_id: stock_location.to_param
|
|
19
|
+
expect(response.status).to eq(401)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
it 'cannot see a stock movement' do
|
|
23
|
+
api_get :show, stock_location_id: stock_location.to_param, id: stock_movement.id
|
|
24
|
+
expect(response.status).to eq(404)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
it 'cannot create a stock movement' do
|
|
28
|
+
params = {
|
|
29
|
+
stock_location_id: stock_location.to_param,
|
|
30
|
+
stock_movement: {
|
|
31
|
+
stock_item_id: stock_item.to_param
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
api_post :create, params
|
|
36
|
+
expect(response.status).to eq(401)
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
context 'as an admin' do
|
|
41
|
+
sign_in_as_admin!
|
|
42
|
+
|
|
43
|
+
it 'gets list of stock movements' do
|
|
44
|
+
api_get :index, stock_location_id: stock_location.to_param
|
|
45
|
+
expect(json_response['stock_movements'].first).to have_attributes(attributes)
|
|
46
|
+
expect(json_response['stock_movements'].first['stock_item']['count_on_hand']).to eq 11
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
it 'can control the page size through a parameter' do
|
|
50
|
+
create(:stock_movement, stock_item: stock_item)
|
|
51
|
+
api_get :index, stock_location_id: stock_location.to_param, per_page: 1
|
|
52
|
+
expect(json_response['count']).to eq(1)
|
|
53
|
+
expect(json_response['current_page']).to eq(1)
|
|
54
|
+
expect(json_response['pages']).to eq(2)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
it 'can query the results through a paramter' do
|
|
58
|
+
expected_result = create(:stock_movement, :received, quantity: 10, stock_item: stock_item)
|
|
59
|
+
api_get :index, stock_location_id: stock_location.to_param, q: { quantity_eq: '10' }
|
|
60
|
+
expect(json_response['count']).to eq(1)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
it 'gets a stock movement' do
|
|
64
|
+
api_get :show, stock_location_id: stock_location.to_param, id: stock_movement.to_param
|
|
65
|
+
expect(json_response).to have_attributes(attributes)
|
|
66
|
+
expect(json_response['stock_item_id']).to eq stock_movement.stock_item_id
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
it 'can create a new stock movement' do
|
|
70
|
+
params = {
|
|
71
|
+
stock_location_id: stock_location.to_param,
|
|
72
|
+
stock_movement: {
|
|
73
|
+
stock_item_id: stock_item.to_param
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
api_post :create, params
|
|
78
|
+
expect(response.status).to eq(201)
|
|
79
|
+
expect(json_response).to have_attributes(attributes)
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
module Spree
|
|
4
|
+
describe Api::StockTransfersController do
|
|
5
|
+
render_views
|
|
6
|
+
|
|
7
|
+
let!(:stock_transfer) { create(:stock_transfer_with_items) }
|
|
8
|
+
let(:transfer_item) { stock_transfer.transfer_items.first }
|
|
9
|
+
|
|
10
|
+
before do
|
|
11
|
+
stub_authentication!
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
context "as a normal user" do
|
|
15
|
+
describe "#receive" do
|
|
16
|
+
it "cannot receive transfer items from a stock transfer" do
|
|
17
|
+
api_post :receive, id: stock_transfer.to_param, variant_id: transfer_item.variant.to_param
|
|
18
|
+
expect(response.status).to eq 401
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
context "as an admin" do
|
|
24
|
+
sign_in_as_admin!
|
|
25
|
+
|
|
26
|
+
describe "#receive" do
|
|
27
|
+
subject do
|
|
28
|
+
api_post :receive, id: stock_transfer.to_param, variant_id: variant_id
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
context "valid parameters" do
|
|
32
|
+
let(:variant_id) { transfer_item.variant.to_param }
|
|
33
|
+
|
|
34
|
+
it "can receive a transfer items from a stock transfer" do
|
|
35
|
+
subject
|
|
36
|
+
expect(response.status).to eq 200
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
it "increments the received quantity for the transfer_item" do
|
|
40
|
+
expect { subject }.to change { transfer_item.reload.received_quantity }.by(1)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
it "returns the received transfer item in the response" do
|
|
44
|
+
subject
|
|
45
|
+
expect(JSON.parse(response.body)["received_item"]["id"]).to eq transfer_item.id
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
context "transfer item has been fully received" do
|
|
50
|
+
let(:variant_id) { transfer_item.variant.to_param }
|
|
51
|
+
|
|
52
|
+
before do
|
|
53
|
+
transfer_item.update_attributes!(expected_quantity: 1, received_quantity: 1)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
it "returns a 422" do
|
|
57
|
+
subject
|
|
58
|
+
expect(response.status).to eq 422
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
it "returns a specific error message" do
|
|
62
|
+
subject
|
|
63
|
+
expect(JSON.parse(response.body)["errors"]["received_quantity"]).to eq ["must be less than or equal to 1"]
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
context "variant is not in the transfer order" do
|
|
68
|
+
let(:variant_id) { create(:variant).to_param }
|
|
69
|
+
|
|
70
|
+
it "returns a 422" do
|
|
71
|
+
subject
|
|
72
|
+
expect(response.status).to eq 422
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
it "returns a specific error message" do
|
|
76
|
+
subject
|
|
77
|
+
expect(JSON.parse(response.body)["error"]).to eq Spree.t(:item_not_in_stock_transfer)
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|