solidus_core 1.0.2 → 1.0.3

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.
Files changed (216) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +1 -0
  3. data/Gemfile +3 -0
  4. data/Rakefile +16 -0
  5. data/script/rails +9 -0
  6. data/solidus_core.gemspec +48 -0
  7. data/spec/fixtures/thinking-cat.jpg +0 -0
  8. data/spec/helpers/base_helper_spec.rb +173 -0
  9. data/spec/helpers/order_helper_spec.rb +12 -0
  10. data/spec/helpers/products_helper_spec.rb +220 -0
  11. data/spec/helpers/taxons_helper_spec.rb +17 -0
  12. data/spec/lib/calculated_adjustments_spec.rb +7 -0
  13. data/spec/lib/i18n_spec.rb +123 -0
  14. data/spec/lib/search/base_spec.rb +86 -0
  15. data/spec/lib/search/variant_spec.rb +92 -0
  16. data/spec/lib/spree/core/controller_helpers/auth_spec.rb +66 -0
  17. data/spec/lib/spree/core/controller_helpers/order_spec.rb +92 -0
  18. data/spec/lib/spree/core/controller_helpers/search_spec.rb +17 -0
  19. data/spec/lib/spree/core/controller_helpers/store_spec.rb +16 -0
  20. data/spec/lib/spree/core/controller_helpers/strong_parameters_spec.rb +39 -0
  21. data/spec/lib/spree/core/current_store_spec.rb +36 -0
  22. data/spec/lib/spree/core/delegate_belongs_to_spec.rb +22 -0
  23. data/spec/lib/spree/core/importer/order_spec.rb +431 -0
  24. data/spec/lib/spree/core/role_configuration_spec.rb +138 -0
  25. data/spec/lib/spree/core/validators/email_spec.rb +48 -0
  26. data/spec/lib/spree/localized_number_spec.rb +38 -0
  27. data/spec/lib/spree/migrations_spec.rb +36 -0
  28. data/spec/lib/spree/money_spec.rb +127 -0
  29. data/spec/lib/tasks/exchanges_spec.rb +231 -0
  30. data/spec/lib/tasks/migrations/copy_shipped_shipments_to_cartons_spec.rb +115 -0
  31. data/spec/lib/tasks/order_capturing_spec.rb +56 -0
  32. data/spec/mailers/carton_mailer_spec.rb +43 -0
  33. data/spec/mailers/order_mailer_spec.rb +122 -0
  34. data/spec/mailers/reimbursement_mailer_spec.rb +40 -0
  35. data/spec/mailers/test_mailer_spec.rb +15 -0
  36. data/spec/models/spree/ability_spec.rb +276 -0
  37. data/spec/models/spree/address_spec.rb +250 -0
  38. data/spec/models/spree/adjustment_reason_spec.rb +13 -0
  39. data/spec/models/spree/adjustment_spec.rb +177 -0
  40. data/spec/models/spree/app_configuration_spec.rb +20 -0
  41. data/spec/models/spree/asset_spec.rb +24 -0
  42. data/spec/models/spree/calculator/default_tax_spec.rb +127 -0
  43. data/spec/models/spree/calculator/flat_percent_item_total_spec.rb +25 -0
  44. data/spec/models/spree/calculator/flat_rate_spec.rb +47 -0
  45. data/spec/models/spree/calculator/flexi_rate_spec.rb +41 -0
  46. data/spec/models/spree/calculator/percent_on_line_item_spec.rb +15 -0
  47. data/spec/models/spree/calculator/price_sack_spec.rb +30 -0
  48. data/spec/models/spree/calculator/refunds/default_refund_amount_spec.rb +51 -0
  49. data/spec/models/spree/calculator/shipping/flat_percent_item_total_spec.rb +23 -0
  50. data/spec/models/spree/calculator/shipping/flat_rate_spec.rb +13 -0
  51. data/spec/models/spree/calculator/shipping/flexi_rate_spec.rb +52 -0
  52. data/spec/models/spree/calculator/shipping/per_item_spec.rb +20 -0
  53. data/spec/models/spree/calculator/shipping/price_sack_spec.rb +30 -0
  54. data/spec/models/spree/calculator/tiered_flat_rate_spec.rb +36 -0
  55. data/spec/models/spree/calculator/tiered_percent_spec.rb +47 -0
  56. data/spec/models/spree/calculator_spec.rb +36 -0
  57. data/spec/models/spree/carton_spec.rb +133 -0
  58. data/spec/models/spree/classification_spec.rb +15 -0
  59. data/spec/models/spree/concerns/display_money_spec.rb +43 -0
  60. data/spec/models/spree/concerns/user_methods_spec.rb +41 -0
  61. data/spec/models/spree/credit_card_spec.rb +334 -0
  62. data/spec/models/spree/customer_return_spec.rb +276 -0
  63. data/spec/models/spree/exchange_spec.rb +79 -0
  64. data/spec/models/spree/gateway/bogus_simple.rb +20 -0
  65. data/spec/models/spree/gateway/bogus_spec.rb +13 -0
  66. data/spec/models/spree/gateway_spec.rb +82 -0
  67. data/spec/models/spree/inventory_unit_spec.rb +307 -0
  68. data/spec/models/spree/item_adjustments_spec.rb +256 -0
  69. data/spec/models/spree/line_item_spec.rb +191 -0
  70. data/spec/models/spree/option_type_spec.rb +14 -0
  71. data/spec/models/spree/option_value_spec.rb +22 -0
  72. data/spec/models/spree/order/address_spec.rb +50 -0
  73. data/spec/models/spree/order/adjustments_spec.rb +39 -0
  74. data/spec/models/spree/order/callbacks_spec.rb +42 -0
  75. data/spec/models/spree/order/checkout_spec.rb +902 -0
  76. data/spec/models/spree/order/currency_updater_spec.rb +32 -0
  77. data/spec/models/spree/order/finalizing_spec.rb +111 -0
  78. data/spec/models/spree/order/payment_spec.rb +210 -0
  79. data/spec/models/spree/order/risk_assessment_spec.rb +68 -0
  80. data/spec/models/spree/order/state_machine_spec.rb +221 -0
  81. data/spec/models/spree/order/tax_spec.rb +84 -0
  82. data/spec/models/spree/order/totals_spec.rb +24 -0
  83. data/spec/models/spree/order/updating_spec.rb +18 -0
  84. data/spec/models/spree/order/validations_spec.rb +15 -0
  85. data/spec/models/spree/order_cancellations_spec.rb +120 -0
  86. data/spec/models/spree/order_capturing_spec.rb +116 -0
  87. data/spec/models/spree/order_contents_spec.rb +265 -0
  88. data/spec/models/spree/order_inventory_spec.rb +228 -0
  89. data/spec/models/spree/order_mutex_spec.rb +85 -0
  90. data/spec/models/spree/order_promotion_spec.rb +31 -0
  91. data/spec/models/spree/order_shipping_spec.rb +247 -0
  92. data/spec/models/spree/order_spec.rb +1412 -0
  93. data/spec/models/spree/order_stock_location_spec.rb +18 -0
  94. data/spec/models/spree/order_updater_spec.rb +299 -0
  95. data/spec/models/spree/payment_method/store_credit_spec.rb +294 -0
  96. data/spec/models/spree/payment_method_spec.rb +96 -0
  97. data/spec/models/spree/payment_spec.rb +1044 -0
  98. data/spec/models/spree/permission_sets/base_spec.rb +12 -0
  99. data/spec/models/spree/permission_sets/configuration_display.rb +82 -0
  100. data/spec/models/spree/permission_sets/configuration_management_spec.rb +50 -0
  101. data/spec/models/spree/permission_sets/dashboard_display_spec.rb +22 -0
  102. data/spec/models/spree/permission_sets/order_display_spec.rb +49 -0
  103. data/spec/models/spree/permission_sets/order_management_spec.rb +36 -0
  104. data/spec/models/spree/permission_sets/product_display_spec.rb +60 -0
  105. data/spec/models/spree/permission_sets/product_management_spec.rb +40 -0
  106. data/spec/models/spree/permission_sets/promotion_display_spec.rb +34 -0
  107. data/spec/models/spree/permission_sets/promotion_management_spec.rb +26 -0
  108. data/spec/models/spree/permission_sets/report_display_spec.rb +24 -0
  109. data/spec/models/spree/permission_sets/restricted_transfer_management_spec.rb +132 -0
  110. data/spec/models/spree/permission_sets/stock_display_spec.rb +26 -0
  111. data/spec/models/spree/permission_sets/stock_management_spec.rb +24 -0
  112. data/spec/models/spree/permission_sets/user_display_spec.rb +36 -0
  113. data/spec/models/spree/permission_sets/user_management_spec.rb +28 -0
  114. data/spec/models/spree/preference_spec.rb +80 -0
  115. data/spec/models/spree/preferences/configuration_spec.rb +30 -0
  116. data/spec/models/spree/preferences/preferable_spec.rb +294 -0
  117. data/spec/models/spree/preferences/scoped_store_spec.rb +58 -0
  118. data/spec/models/spree/preferences/static_model_preferences_spec.rb +78 -0
  119. data/spec/models/spree/preferences/statically_configurable_spec.rb +60 -0
  120. data/spec/models/spree/preferences/store_spec.rb +39 -0
  121. data/spec/models/spree/price_spec.rb +42 -0
  122. data/spec/models/spree/product/scopes_spec.rb +148 -0
  123. data/spec/models/spree/product_duplicator_spec.rb +103 -0
  124. data/spec/models/spree/product_filter_spec.rb +26 -0
  125. data/spec/models/spree/product_property_spec.rb +20 -0
  126. data/spec/models/spree/product_spec.rb +437 -0
  127. data/spec/models/spree/promotion/actions/create_adjustment_spec.rb +96 -0
  128. data/spec/models/spree/promotion/actions/create_item_adjustments_spec.rb +165 -0
  129. data/spec/models/spree/promotion/actions/create_quantity_adjustments_spec.rb +115 -0
  130. data/spec/models/spree/promotion/actions/free_shipping_spec.rb +40 -0
  131. data/spec/models/spree/promotion/rules/first_order_spec.rb +75 -0
  132. data/spec/models/spree/promotion/rules/item_total_spec.rb +67 -0
  133. data/spec/models/spree/promotion/rules/nth_order_spec.rb +70 -0
  134. data/spec/models/spree/promotion/rules/one_use_per_user_spec.rb +42 -0
  135. data/spec/models/spree/promotion/rules/option_value_spec.rb +94 -0
  136. data/spec/models/spree/promotion/rules/product_spec.rb +143 -0
  137. data/spec/models/spree/promotion/rules/taxon_spec.rb +102 -0
  138. data/spec/models/spree/promotion/rules/user_logged_in_spec.rb +27 -0
  139. data/spec/models/spree/promotion/rules/user_spec.rb +37 -0
  140. data/spec/models/spree/promotion_builder_spec.rb +118 -0
  141. data/spec/models/spree/promotion_category_spec.rb +17 -0
  142. data/spec/models/spree/promotion_code/code_builder_spec.rb +79 -0
  143. data/spec/models/spree/promotion_code_spec.rb +187 -0
  144. data/spec/models/spree/promotion_handler/cart_spec.rb +114 -0
  145. data/spec/models/spree/promotion_handler/coupon_spec.rb +335 -0
  146. data/spec/models/spree/promotion_handler/free_shipping_spec.rb +47 -0
  147. data/spec/models/spree/promotion_handler/page_spec.rb +44 -0
  148. data/spec/models/spree/promotion_rule_spec.rb +28 -0
  149. data/spec/models/spree/promotion_spec.rb +767 -0
  150. data/spec/models/spree/refund_spec.rb +204 -0
  151. data/spec/models/spree/reimbursement/credit_spec.rb +36 -0
  152. data/spec/models/spree/reimbursement/reimbursement_type_engine_spec.rb +140 -0
  153. data/spec/models/spree/reimbursement/reimbursement_type_validator_spec.rb +83 -0
  154. data/spec/models/spree/reimbursement_performer_spec.rb +30 -0
  155. data/spec/models/spree/reimbursement_spec.rb +231 -0
  156. data/spec/models/spree/reimbursement_tax_calculator_spec.rb +51 -0
  157. data/spec/models/spree/reimbursement_type/credit_spec.rb +53 -0
  158. data/spec/models/spree/reimbursement_type/exchange_spec.rb +46 -0
  159. data/spec/models/spree/reimbursement_type/original_payment_spec.rb +107 -0
  160. data/spec/models/spree/reimbursement_type/store_credit_spec.rb +97 -0
  161. data/spec/models/spree/return_authorization_spec.rb +290 -0
  162. data/spec/models/spree/return_item/eligibility_validator/default_spec.rb +77 -0
  163. data/spec/models/spree/return_item/eligibility_validator/inventory_shipped_spec.rb +58 -0
  164. data/spec/models/spree/return_item/eligibility_validator/no_reimbursements_spec.rb +85 -0
  165. data/spec/models/spree/return_item/eligibility_validator/order_completed_spec.rb +32 -0
  166. data/spec/models/spree/return_item/eligibility_validator/rma_required_spec.rb +29 -0
  167. data/spec/models/spree/return_item/eligibility_validator/time_since_purchase_spec.rb +35 -0
  168. data/spec/models/spree/return_item/exchange_variant_eligibility/same_option_value_spec.rb +65 -0
  169. data/spec/models/spree/return_item/exchange_variant_eligibility/same_product_spec.rb +43 -0
  170. data/spec/models/spree/return_item_spec.rb +775 -0
  171. data/spec/models/spree/returns_calculator_spec.rb +14 -0
  172. data/spec/models/spree/shipment_spec.rb +709 -0
  173. data/spec/models/spree/shipping_calculator_spec.rb +45 -0
  174. data/spec/models/spree/shipping_method_spec.rb +88 -0
  175. data/spec/models/spree/shipping_rate_spec.rb +142 -0
  176. data/spec/models/spree/state_spec.rb +14 -0
  177. data/spec/models/spree/stock/availability_validator_spec.rb +83 -0
  178. data/spec/models/spree/stock/coordinator_spec.rb +116 -0
  179. data/spec/models/spree/stock/differentiator_spec.rb +39 -0
  180. data/spec/models/spree/stock/estimator_spec.rb +146 -0
  181. data/spec/models/spree/stock/inventory_unit_builder_spec.rb +38 -0
  182. data/spec/models/spree/stock/package_spec.rb +163 -0
  183. data/spec/models/spree/stock/packer_spec.rb +91 -0
  184. data/spec/models/spree/stock/prioritizer_spec.rb +125 -0
  185. data/spec/models/spree/stock/quantifier_spec.rb +115 -0
  186. data/spec/models/spree/stock/splitter/backordered_spec.rb +29 -0
  187. data/spec/models/spree/stock/splitter/base_spec.rb +21 -0
  188. data/spec/models/spree/stock/splitter/shipping_category_spec.rb +50 -0
  189. data/spec/models/spree/stock/splitter/weight_spec.rb +29 -0
  190. data/spec/models/spree/stock_item_spec.rb +426 -0
  191. data/spec/models/spree/stock_location_spec.rb +279 -0
  192. data/spec/models/spree/stock_movement_spec.rb +56 -0
  193. data/spec/models/spree/stock_transfer_spec.rb +290 -0
  194. data/spec/models/spree/store_credit_category_spec.rb +17 -0
  195. data/spec/models/spree/store_credit_event_spec.rb +314 -0
  196. data/spec/models/spree/store_credit_spec.rb +876 -0
  197. data/spec/models/spree/store_spec.rb +55 -0
  198. data/spec/models/spree/tax_category_spec.rb +27 -0
  199. data/spec/models/spree/tax_rate_spec.rb +378 -0
  200. data/spec/models/spree/taxon_spec.rb +74 -0
  201. data/spec/models/spree/taxonomy_spec.rb +18 -0
  202. data/spec/models/spree/tracker_spec.rb +21 -0
  203. data/spec/models/spree/transfer_item_spec.rb +264 -0
  204. data/spec/models/spree/unit_cancel_spec.rb +148 -0
  205. data/spec/models/spree/user_spec.rb +223 -0
  206. data/spec/models/spree/validations/db_maximum_length_validator_spec.rb +23 -0
  207. data/spec/models/spree/variant/scopes_spec.rb +55 -0
  208. data/spec/models/spree/variant_spec.rb +546 -0
  209. data/spec/models/spree/zone_spec.rb +305 -0
  210. data/spec/spec_helper.rb +78 -0
  211. data/spec/support/big_decimal.rb +5 -0
  212. data/spec/support/concerns/default_price.rb +34 -0
  213. data/spec/support/dummy_ability.rb +4 -0
  214. data/spec/support/test_gateway.rb +2 -0
  215. metadata +229 -3
  216. data/lib/spree/testing_support/rspec-activemodel-mocks_patch.rb +0 -8
@@ -0,0 +1,279 @@
1
+ require 'spec_helper'
2
+
3
+ module Spree
4
+ describe StockLocation, :type => :model do
5
+ subject { create(:stock_location_with_items, backorderable_default: true) }
6
+ let(:stock_item) { subject.stock_items.order(:id).first }
7
+ let(:variant) { stock_item.variant }
8
+
9
+ it 'creates stock_items for all variants' do
10
+ expect(subject.stock_items.count).to eq Variant.count
11
+ end
12
+
13
+ context "handling stock items" do
14
+ let!(:variant) { create(:variant) }
15
+
16
+ context "given a variant" do
17
+ subject { StockLocation.create(name: "testing", propagate_all_variants: false) }
18
+
19
+ context "set up" do
20
+ it "creates stock item" do
21
+ expect(subject).to receive(:propagate_variant)
22
+ subject.set_up_stock_item(variant)
23
+ end
24
+
25
+ context "stock item exists" do
26
+ let!(:stock_item) { subject.propagate_variant(variant) }
27
+
28
+ it "returns existing stock item" do
29
+ expect(subject.set_up_stock_item(variant)).to eq(stock_item)
30
+ end
31
+ end
32
+ end
33
+
34
+ context "propagate variants" do
35
+ let(:stock_item) { subject.propagate_variant(variant) }
36
+
37
+ it "creates a new stock item" do
38
+ expect {
39
+ subject.propagate_variant(variant)
40
+ }.to change{ StockItem.count }.by(1)
41
+ end
42
+
43
+ context "passes backorderable default config" do
44
+ context "true" do
45
+ before { subject.backorderable_default = true }
46
+ it { expect(stock_item.backorderable).to be true }
47
+ end
48
+
49
+ context "false" do
50
+ before { subject.backorderable_default = false }
51
+ it { expect(stock_item.backorderable).to be false }
52
+ end
53
+ end
54
+ end
55
+
56
+ context "propagate all variants" do
57
+ subject { StockLocation.new(name: "testing") }
58
+
59
+ context "true" do
60
+ before { subject.propagate_all_variants = true }
61
+
62
+ specify do
63
+ expect(subject).to receive(:propagate_variant).at_least(:once)
64
+ subject.save!
65
+ end
66
+ end
67
+
68
+ context "false" do
69
+ before { subject.propagate_all_variants = false }
70
+
71
+ specify do
72
+ expect(subject).not_to receive(:propagate_variant)
73
+ subject.save!
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
79
+
80
+ it 'finds a stock_item for a variant' do
81
+ stock_item = subject.stock_item(variant)
82
+ expect(stock_item.count_on_hand).to eq 10
83
+ end
84
+
85
+ it 'finds a stock_item for a variant by id' do
86
+ stock_item = subject.stock_item(variant.id)
87
+ expect(stock_item.variant).to eq variant
88
+ end
89
+
90
+ it 'returns nil when stock_item is not found for variant' do
91
+ stock_item = subject.stock_item(100)
92
+ expect(stock_item).to be_nil
93
+ end
94
+
95
+ describe '#stock_item_or_create' do
96
+ before do
97
+ variant = create(:variant)
98
+ variant.stock_items.destroy_all
99
+ variant.save
100
+ end
101
+
102
+ it 'creates a stock_item if not found for a variant' do
103
+ stock_item = subject.stock_item_or_create(variant)
104
+ expect(stock_item.variant).to eq variant
105
+ end
106
+
107
+ it 'creates a stock_item if not found for a variant_id' do
108
+ stock_item = subject.stock_item_or_create(variant.id)
109
+ expect(stock_item.variant).to eq variant
110
+ end
111
+ end
112
+
113
+ it 'finds a count_on_hand for a variant' do
114
+ expect(subject.count_on_hand(variant)).to eq 10
115
+ end
116
+
117
+ it 'finds determines if you a variant is backorderable' do
118
+ expect(subject.backorderable?(variant)).to be true
119
+ end
120
+
121
+ it 'restocks a variant with a positive stock movement' do
122
+ originator = double
123
+ expect(subject).to receive(:move).with(variant, 5, originator)
124
+ subject.restock(variant, 5, originator)
125
+ end
126
+
127
+ it 'unstocks a variant with a negative stock movement' do
128
+ originator = double
129
+ expect(subject).to receive(:move).with(variant, -5, originator)
130
+ subject.unstock(variant, 5, originator)
131
+ end
132
+
133
+ it 'it creates a stock_movement' do
134
+ expect {
135
+ subject.move variant, 5
136
+ }.to change { subject.stock_movements.where(stock_item_id: stock_item).count }.by(1)
137
+ end
138
+
139
+ it 'can be deactivated' do
140
+ create(:stock_location, :active => true)
141
+ create(:stock_location, :active => false)
142
+ expect(Spree::StockLocation.active.count).to eq 1
143
+ end
144
+
145
+ it 'ensures only one stock location is default at a time' do
146
+ first = create(:stock_location, :active => true, :default => true)
147
+ second = create(:stock_location, :active => true, :default => true)
148
+
149
+ expect(first.reload.default).to eq false
150
+ expect(second.reload.default).to eq true
151
+
152
+ first.default = true
153
+ first.save!
154
+
155
+ expect(first.reload.default).to eq true
156
+ expect(second.reload.default).to eq false
157
+ end
158
+
159
+ context 'fill_status' do
160
+ it 'all on_hand with no backordered' do
161
+ on_hand, backordered = subject.fill_status(variant, 5)
162
+ expect(on_hand).to eq 5
163
+ expect(backordered).to eq 0
164
+ end
165
+
166
+ it 'some on_hand with some backordered' do
167
+ on_hand, backordered = subject.fill_status(variant, 20)
168
+ expect(on_hand).to eq 10
169
+ expect(backordered).to eq 10
170
+ end
171
+
172
+ it 'zero on_hand with all backordered' do
173
+ zero_stock_item = mock_model(StockItem,
174
+ count_on_hand: 0,
175
+ backorderable?: true)
176
+ expect(subject).to receive(:stock_item).with(variant).and_return(zero_stock_item)
177
+
178
+ on_hand, backordered = subject.fill_status(variant, 20)
179
+ expect(on_hand).to eq 0
180
+ expect(backordered).to eq 20
181
+ end
182
+
183
+ context 'when backordering is not allowed' do
184
+ before do
185
+ @stock_item = mock_model(StockItem, backorderable?: false)
186
+ expect(subject).to receive(:stock_item).with(variant).and_return(@stock_item)
187
+ end
188
+
189
+ it 'all on_hand' do
190
+ allow(@stock_item).to receive_messages(count_on_hand: 10)
191
+
192
+ on_hand, backordered = subject.fill_status(variant, 5)
193
+ expect(on_hand).to eq 5
194
+ expect(backordered).to eq 0
195
+ end
196
+
197
+ it 'some on_hand' do
198
+ allow(@stock_item).to receive_messages(count_on_hand: 10)
199
+
200
+ on_hand, backordered = subject.fill_status(variant, 20)
201
+ expect(on_hand).to eq 10
202
+ expect(backordered).to eq 0
203
+ end
204
+
205
+ it 'zero on_hand' do
206
+ allow(@stock_item).to receive_messages(count_on_hand: 0)
207
+
208
+ on_hand, backordered = subject.fill_status(variant, 20)
209
+ expect(on_hand).to eq 0
210
+ expect(backordered).to eq 0
211
+ end
212
+ end
213
+
214
+ context 'without stock_items' do
215
+ subject { create(:stock_location) }
216
+ let(:variant) { create(:base_variant) }
217
+
218
+ it 'zero on_hand and backordered' do
219
+ subject
220
+ variant.stock_items.destroy_all
221
+ on_hand, backordered = subject.fill_status(variant, 1)
222
+ expect(on_hand).to eq 0
223
+ expect(backordered).to eq 0
224
+ end
225
+ end
226
+ end
227
+
228
+ context '#state_text' do
229
+ context 'state is blank' do
230
+ subject { StockLocation.create(name: "testing", state: nil, state_name: 'virginia') }
231
+ specify { expect(subject.state_text).to eq('virginia') }
232
+ end
233
+
234
+ context 'both name and abbr is present' do
235
+ let(:state) { stub_model(Spree::State, name: 'virginia', abbr: 'va') }
236
+ subject { StockLocation.create(name: "testing", state: state, state_name: nil) }
237
+ specify { expect(subject.state_text).to eq('va') }
238
+ end
239
+
240
+ context 'only name is present' do
241
+ let(:state) { stub_model(Spree::State, name: 'virginia', abbr: nil) }
242
+ subject { StockLocation.create(name: "testing", state: state, state_name: nil) }
243
+ specify { expect(subject.state_text).to eq('virginia') }
244
+ end
245
+ end
246
+
247
+
248
+ describe "#move" do
249
+ let!(:variant) { create(:variant) }
250
+ def move
251
+ subject.move(variant, quantity)
252
+ end
253
+
254
+ context "no stock item exists" do
255
+ before { subject.stock_items.destroy_all }
256
+ context "positive movement" do
257
+ let(:quantity) { 1 }
258
+ it "creates a stock item" do
259
+ expect { move }.to change { subject.stock_items.count }.by 1
260
+ end
261
+ end
262
+
263
+ # We should not be creating stock items that do not exist
264
+ # for the sake of a negative movement.
265
+ context "negative movement" do
266
+ let(:quantity) { -1 }
267
+ it "raises an error" do
268
+ expect {
269
+ expect {
270
+ move
271
+ }.to raise_error StockLocation::InvalidMovementError
272
+ }.not_to change { subject.stock_items.count }
273
+ end
274
+ end
275
+
276
+ end
277
+ end
278
+ end
279
+ end
@@ -0,0 +1,56 @@
1
+ require 'spec_helper'
2
+
3
+ describe Spree::StockMovement, :type => :model do
4
+ let(:stock_location) { create(:stock_location_with_items) }
5
+ let(:stock_item) { stock_location.stock_items.order(:id).first }
6
+ subject { build(:stock_movement, stock_item: stock_item) }
7
+
8
+ it 'should belong to a stock item' do
9
+ expect(subject).to respond_to(:stock_item)
10
+ end
11
+
12
+ it 'is readonly unless new' do
13
+ subject.save
14
+ expect {
15
+ subject.save
16
+ }.to raise_error(ActiveRecord::ReadOnlyRecord)
17
+ end
18
+
19
+ it 'does not update count on hand when track inventory levels is false' do
20
+ Spree::Config[:track_inventory_levels] = false
21
+ subject.quantity = 1
22
+ subject.save
23
+ stock_item.reload
24
+ expect(stock_item.count_on_hand).to eq(10)
25
+ end
26
+
27
+ it 'does not update count on hand when variant inventory tracking is off' do
28
+ stock_item.variant.track_inventory = false
29
+ subject.quantity = 1
30
+ subject.save
31
+ stock_item.reload
32
+ expect(stock_item.count_on_hand).to eq(10)
33
+ end
34
+
35
+ context "when quantity is negative" do
36
+ context "after save" do
37
+ it "should decrement the stock item count on hand" do
38
+ subject.quantity = -1
39
+ subject.save
40
+ stock_item.reload
41
+ expect(stock_item.count_on_hand).to eq(9)
42
+ end
43
+ end
44
+ end
45
+
46
+ context "when quantity is positive" do
47
+ context "after save" do
48
+ it "should increment the stock item count on hand" do
49
+ subject.quantity = 1
50
+ subject.save
51
+ stock_item.reload
52
+ expect(stock_item.count_on_hand).to eq(11)
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,290 @@
1
+ require 'spec_helper'
2
+
3
+ module Spree
4
+ describe StockTransfer, :type => :model do
5
+ let(:destination_location) { create(:stock_location_with_items) }
6
+ let(:source_location) { create(:stock_location_with_items) }
7
+ let(:stock_item) { source_location.stock_items.order(:id).first }
8
+ let(:variant) { stock_item.variant }
9
+ let(:stock_transfer) do
10
+ StockTransfer.create(description: 'PO123', source_location: source_location, destination_location: destination_location)
11
+ end
12
+
13
+ subject { stock_transfer }
14
+
15
+ describe '#description' do
16
+ subject { super().description }
17
+ it { is_expected.to eq 'PO123' }
18
+ end
19
+
20
+ describe '#to_param' do
21
+ subject { super().to_param }
22
+ it { is_expected.to match /T\d+/ }
23
+ end
24
+
25
+ describe "transfer item building" do
26
+ let(:stock_transfer) do
27
+ variant = source_location.stock_items.first.variant
28
+ stock_transfer = Spree::StockTransfer.new(
29
+ number: "T123",
30
+ source_location: source_location,
31
+ destination_location: destination_location
32
+ )
33
+ stock_transfer.transfer_items.build(variant: variant, expected_quantity: 5)
34
+ stock_transfer
35
+ end
36
+
37
+ subject { stock_transfer.save }
38
+
39
+ it { is_expected.to eq true }
40
+
41
+ it "creates the associated transfer item" do
42
+ expect { subject }.to change { Spree::TransferItem.count }.by(1)
43
+ end
44
+ end
45
+
46
+ describe "#receivable?" do
47
+ subject { stock_transfer.receivable? }
48
+
49
+ context "finalized" do
50
+ before do
51
+ stock_transfer.update_attributes(finalized_at: Time.now)
52
+ end
53
+
54
+ it { is_expected.to eq false }
55
+ end
56
+
57
+ context "shipped" do
58
+ before do
59
+ stock_transfer.update_attributes(shipped_at: Time.now)
60
+ end
61
+
62
+ it { is_expected.to eq false }
63
+ end
64
+
65
+ context "closed" do
66
+ before do
67
+ stock_transfer.update_attributes(closed_at: Time.now)
68
+ end
69
+
70
+ it { is_expected.to eq false }
71
+ end
72
+
73
+ context "finalized and closed" do
74
+ before do
75
+ stock_transfer.update_attributes(finalized_at: Time.now, closed_at: Time.now)
76
+ end
77
+
78
+ it { is_expected.to eq false }
79
+ end
80
+
81
+ context "shipped and closed" do
82
+ before do
83
+ stock_transfer.update_attributes(shipped_at: Time.now, closed_at: Time.now)
84
+ end
85
+
86
+ it { is_expected.to eq false }
87
+ end
88
+
89
+ context "finalized and shipped" do
90
+ before do
91
+ stock_transfer.update_attributes(finalized_at: Time.now, shipped_at: Time.now)
92
+ end
93
+
94
+ it { is_expected.to eq true }
95
+ end
96
+ end
97
+
98
+ describe "#finalizable?" do
99
+ subject { stock_transfer.finalizable? }
100
+
101
+ context "finalized" do
102
+ before do
103
+ stock_transfer.update_attributes(finalized_at: Time.now)
104
+ end
105
+
106
+ it { is_expected.to eq false }
107
+ end
108
+
109
+ context "shipped" do
110
+ before do
111
+ stock_transfer.update_attributes(shipped_at: Time.now)
112
+ end
113
+
114
+ it { is_expected.to eq false }
115
+ end
116
+
117
+ context "closed" do
118
+ before do
119
+ stock_transfer.update_attributes(closed_at: Time.now)
120
+ end
121
+
122
+ it { is_expected.to eq false }
123
+ end
124
+
125
+ context "finalized and closed" do
126
+ before do
127
+ stock_transfer.update_attributes(finalized_at: Time.now, closed_at: Time.now)
128
+ end
129
+
130
+ it { is_expected.to eq false }
131
+ end
132
+
133
+ context "shipped and closed" do
134
+ before do
135
+ stock_transfer.update_attributes(shipped_at: Time.now, closed_at: Time.now)
136
+ end
137
+
138
+ it { is_expected.to eq false }
139
+ end
140
+
141
+ context "no action taken on stock transfer" do
142
+ before do
143
+ stock_transfer.update_attributes(finalized_at: nil, shipped_at: nil, closed_at: nil)
144
+ end
145
+
146
+ it { is_expected.to eq true }
147
+ end
148
+ end
149
+
150
+ describe "#finalize" do
151
+ let(:user) { create(:user) }
152
+
153
+ subject { stock_transfer.finalize(user) }
154
+
155
+ context "can be finalized" do
156
+ it "sets a finalized_at date" do
157
+ expect { subject }.to change { stock_transfer.finalized_at }
158
+ end
159
+
160
+ it "sets the finalized_by to the supplied user" do
161
+ subject
162
+ expect(stock_transfer.finalized_by).to eq user
163
+ end
164
+ end
165
+
166
+ context "can't be finalized" do
167
+ before do
168
+ stock_transfer.update_attributes(finalized_at: Time.now)
169
+ end
170
+
171
+ it "doesn't set a finalized_at date" do
172
+ expect { subject }.to_not change { stock_transfer.finalized_at }
173
+ end
174
+
175
+ it "doesn't set a finalized_by user" do
176
+ expect { subject }.to_not change { stock_transfer.finalized_by }
177
+ end
178
+
179
+ it "adds an error message" do
180
+ subject
181
+ expect(stock_transfer.errors.full_messages).to include Spree.t(:stock_transfer_cannot_be_finalized)
182
+ end
183
+ end
184
+ end
185
+
186
+ describe "#close" do
187
+ let(:user) { create(:user) }
188
+ let(:stock_transfer) { create(:receivable_stock_transfer_with_items) }
189
+
190
+ subject { stock_transfer.close(user) }
191
+
192
+ context "can be closed" do
193
+ it "sets a closed_at date" do
194
+ expect { subject }.to change { stock_transfer.closed_at }
195
+ end
196
+
197
+ it "sets the closed_by to the supplied user" do
198
+ subject
199
+ expect(stock_transfer.closed_by).to eq user
200
+ end
201
+ end
202
+
203
+ context "can't be closed" do
204
+ before do
205
+ stock_transfer.update_attributes(finalized_at: nil)
206
+ end
207
+
208
+ it "doesn't set a closed_at date" do
209
+ expect { subject }.to_not change { stock_transfer.closed_at }
210
+ end
211
+
212
+ it "doesn't set a closed_by user" do
213
+ expect { subject }.to_not change { stock_transfer.closed_by }
214
+ end
215
+
216
+ it "adds an error message" do
217
+ subject
218
+ expect(stock_transfer.errors.full_messages).to include Spree.t(:stock_transfer_must_be_receivable)
219
+ end
220
+ end
221
+ end
222
+
223
+ describe "destroying" do
224
+ subject { stock_transfer.destroy }
225
+
226
+ context "stock transfer is finalized" do
227
+ before do
228
+ stock_transfer.update_attributes!(finalized_at: Time.now)
229
+ end
230
+
231
+ it "doesn't destroy the stock transfer" do
232
+ expect { subject }.to_not change { Spree::StockTransfer.count }
233
+ end
234
+
235
+ it "adds an error message to the model" do
236
+ subject
237
+ expect(stock_transfer.errors.full_messages).to include Spree.t('errors.messages.cannot_delete_finalized_stock_transfer')
238
+ end
239
+ end
240
+
241
+ context "stock transfer is not finalized" do
242
+ before do
243
+ stock_transfer.update_attributes!(finalized_at: nil)
244
+ end
245
+
246
+ it "destroys the stock transfer" do
247
+ expect { subject }.to change { Spree::StockTransfer.count }.by(-1)
248
+ end
249
+ end
250
+ end
251
+
252
+ describe '#transfer' do
253
+ let(:stock_transfer) { create(:stock_transfer_with_items) }
254
+
255
+ before do
256
+ stock_transfer.transfer_items.each { |item| item.update_attributes(expected_quantity: 1) }
257
+ end
258
+
259
+ subject { stock_transfer.transfer }
260
+
261
+ context 'with enough stock' do
262
+
263
+ it 'creates stock movements for transfer items' do
264
+ expect{ subject }.to change{ Spree::StockMovement.count }.by(stock_transfer.transfer_items.count)
265
+ end
266
+ end
267
+
268
+ context 'without enough stock' do
269
+ before do
270
+ stockless_variant = stock_transfer.transfer_items.last.variant
271
+ stock_transfer.source_location.stock_item(stockless_variant).set_count_on_hand(0)
272
+ end
273
+
274
+ it 'rollsback the transaction' do
275
+ expect{ subject }.to_not change{ Spree::StockMovement.count }
276
+ end
277
+
278
+ it 'adds errors' do
279
+ subject
280
+ expect(stock_transfer.errors.full_messages.join(', ')).to match /not enough inventory/
281
+ end
282
+
283
+ it 'returns false' do
284
+ expect(subject).to eq false
285
+ end
286
+
287
+ end
288
+ end
289
+ end
290
+ end