spree_core 3.0.10 → 3.1.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (289) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/spree.js.coffee.erb +12 -3
  3. data/app/helpers/spree/base_helper.rb +4 -1
  4. data/app/helpers/spree/products_helper.rb +37 -6
  5. data/app/mailers/spree/base_mailer.rb +11 -2
  6. data/app/models/concerns/spree/adjustment_source.rb +3 -10
  7. data/app/models/concerns/spree/default_price.rb +7 -1
  8. data/app/models/concerns/spree/named_type.rb +1 -1
  9. data/app/models/concerns/spree/user_api_authentication.rb +7 -1
  10. data/app/models/concerns/spree/user_methods.rb +47 -0
  11. data/app/models/concerns/spree/user_reporting.rb +2 -2
  12. data/app/models/concerns/spree/vat_price_calculation.rb +47 -0
  13. data/app/models/spree/address.rb +8 -7
  14. data/app/models/spree/adjustable/adjuster/base.rb +25 -0
  15. data/app/models/spree/adjustable/adjuster/promotion.rb +41 -0
  16. data/app/models/spree/adjustable/adjuster/tax.rb +26 -0
  17. data/app/models/spree/adjustable/adjustments_updater.rb +22 -45
  18. data/app/models/spree/adjustment.rb +8 -10
  19. data/app/models/spree/app_configuration.rb +5 -2
  20. data/app/models/spree/base.rb +4 -0
  21. data/app/models/spree/calculator.rb +0 -5
  22. data/app/models/spree/calculator/default_tax.rb +2 -10
  23. data/app/models/spree/classification.rb +7 -3
  24. data/app/models/spree/country.rb +14 -3
  25. data/app/models/spree/credit_card.rb +21 -31
  26. data/app/models/spree/customer_return.rb +7 -15
  27. data/app/models/spree/gateway.rb +7 -6
  28. data/app/models/spree/image.rb +1 -1
  29. data/app/models/spree/inventory_unit.rb +9 -6
  30. data/app/models/spree/legacy_user.rb +1 -6
  31. data/app/models/spree/line_item.rb +69 -68
  32. data/app/models/spree/log_entry.rb +1 -4
  33. data/app/models/spree/option_type.rb +15 -6
  34. data/app/models/spree/option_type_prototype.rb +9 -0
  35. data/app/models/spree/option_value.rb +11 -3
  36. data/app/models/spree/option_value_variant.rb +6 -0
  37. data/app/models/spree/order.rb +113 -64
  38. data/app/models/spree/order/checkout.rb +8 -11
  39. data/app/models/spree/order/currency_updater.rb +1 -1
  40. data/app/models/spree/order/store_credit.rb +96 -0
  41. data/app/models/spree/order_contents.rb +6 -1
  42. data/app/models/spree/order_inventory.rb +4 -8
  43. data/app/models/spree/order_promotion.rb +6 -0
  44. data/app/models/spree/order_updater.rb +2 -7
  45. data/app/models/spree/payment.rb +46 -19
  46. data/app/models/spree/payment/gateway_options.rb +8 -4
  47. data/app/models/spree/payment_method.rb +12 -13
  48. data/app/models/spree/payment_method/store_credit.rb +130 -0
  49. data/app/models/spree/preference.rb +1 -1
  50. data/app/models/spree/price.rb +16 -6
  51. data/app/models/spree/product.rb +52 -49
  52. data/app/models/spree/product/scopes.rb +7 -2
  53. data/app/models/spree/product_option_type.rb +7 -2
  54. data/app/models/spree/product_promotion_rule.rb +9 -0
  55. data/app/models/spree/product_property.rb +8 -10
  56. data/app/models/spree/promotion.rb +19 -19
  57. data/app/models/spree/promotion/rules/product.rb +3 -1
  58. data/app/models/spree/promotion/rules/taxon.rb +2 -1
  59. data/app/models/spree/promotion/rules/user.rb +4 -4
  60. data/app/models/spree/promotion_action.rb +3 -3
  61. data/app/models/spree/promotion_category.rb +1 -1
  62. data/app/models/spree/promotion_rule_taxon.rb +9 -0
  63. data/app/models/spree/promotion_rule_user.rb +9 -0
  64. data/app/models/spree/property.rb +2 -1
  65. data/app/models/spree/property_prototype.rb +9 -0
  66. data/app/models/spree/prototype.rb +8 -3
  67. data/app/models/spree/prototype_taxon.rb +9 -0
  68. data/app/models/spree/refund.rb +10 -7
  69. data/app/models/spree/refund_reason.rb +1 -1
  70. data/app/models/spree/reimbursement.rb +12 -16
  71. data/app/models/spree/reimbursement_type/reimbursement_helpers.rb +23 -6
  72. data/app/models/spree/reimbursement_type/store_credit.rb +28 -0
  73. data/app/models/spree/return_authorization.rb +8 -13
  74. data/app/models/spree/return_authorization_reason.rb +1 -1
  75. data/app/models/spree/return_item.rb +13 -12
  76. data/app/models/spree/return_item/eligibility_validator/time_since_purchase.rb +1 -1
  77. data/app/models/spree/role.rb +3 -2
  78. data/app/models/spree/role_user.rb +6 -0
  79. data/app/models/spree/shipment.rb +18 -23
  80. data/app/models/spree/shipment_handler.rb +2 -2
  81. data/app/models/spree/shipping_category.rb +6 -3
  82. data/app/models/spree/shipping_method.rb +11 -10
  83. data/app/models/spree/shipping_method_zone.rb +6 -0
  84. data/app/models/spree/shipping_rate.rb +16 -29
  85. data/app/models/spree/state.rb +3 -2
  86. data/app/models/spree/state_change.rb +1 -1
  87. data/app/models/spree/stock/content_item.rb +10 -12
  88. data/app/models/spree/stock/coordinator.rb +13 -14
  89. data/app/models/spree/stock/estimator.rb +28 -30
  90. data/app/models/spree/stock/inventory_unit_builder.rb +1 -9
  91. data/app/models/spree/stock/packer.rb +1 -1
  92. data/app/models/spree/stock/quantifier.rb +5 -5
  93. data/app/models/spree/stock/splitter/backordered.rb +2 -2
  94. data/app/models/spree/stock_item.rb +12 -18
  95. data/app/models/spree/stock_location.rb +4 -7
  96. data/app/models/spree/stock_movement.rb +11 -9
  97. data/app/models/spree/stock_transfer.rb +11 -12
  98. data/app/models/spree/store.rb +14 -6
  99. data/app/models/spree/store_credit.rb +252 -0
  100. data/app/models/spree/store_credit_category.rb +22 -0
  101. data/app/models/spree/store_credit_event.rb +38 -0
  102. data/app/models/spree/store_credit_type.rb +6 -0
  103. data/app/models/spree/tax_category.rb +3 -8
  104. data/app/models/spree/tax_rate.rb +56 -122
  105. data/app/models/spree/taxon.rb +11 -5
  106. data/app/models/spree/tracker.rb +12 -1
  107. data/app/models/spree/validations/db_maximum_length_validator.rb +2 -1
  108. data/app/models/spree/variant.rb +82 -50
  109. data/app/models/spree/zone.rb +21 -17
  110. data/app/models/spree/zone_member.rb +6 -0
  111. data/app/validators/db_maximum_length_validator.rb +11 -0
  112. data/app/views/layouts/spree/base_mailer.html.erb +38 -781
  113. data/app/views/spree/order_mailer/_adjustment.html.erb +8 -0
  114. data/app/views/spree/order_mailer/_subtotal.html.erb +8 -0
  115. data/app/views/spree/order_mailer/_total.html.erb +8 -0
  116. data/app/views/spree/order_mailer/cancel_email.html.erb +13 -28
  117. data/app/views/spree/order_mailer/cancel_email.text.erb +1 -1
  118. data/app/views/spree/order_mailer/confirm_email.html.erb +49 -63
  119. data/app/views/spree/order_mailer/confirm_email.text.erb +1 -1
  120. data/app/views/spree/shared/_base_mailer_header.html.erb +5 -7
  121. data/app/views/spree/shared/_base_mailer_stylesheets.html.erb +777 -0
  122. data/app/views/spree/shared/_error_messages.html.erb +1 -1
  123. data/app/views/spree/shared/_mailer_line_item.html.erb +12 -0
  124. data/app/views/spree/shipment_mailer/shipped_email.html.erb +21 -14
  125. data/app/views/spree/shipment_mailer/shipped_email.text.erb +3 -3
  126. data/config/initializers/user_class_extensions.rb +7 -38
  127. data/config/locales/en.yml +113 -13
  128. data/config/routes.rb +7 -0
  129. data/db/default/spree/default_reimbursement_type.rb +1 -1
  130. data/db/default/spree/zones.rb +4 -5
  131. data/db/migrate/20150118210639_create_spree_store_credits.rb +24 -0
  132. data/db/migrate/20150118211500_create_spree_store_credit_categories.rb +8 -0
  133. data/db/migrate/20150118212051_create_spree_store_credit_events.rb +17 -0
  134. data/db/migrate/20150118212101_create_spree_store_credit_types.rb +10 -0
  135. data/db/migrate/20150314013438_add_missing_indexes.rb +25 -0
  136. data/db/migrate/20150317174308_remove_duplicated_indexes_from_multi_columns.rb +18 -0
  137. data/db/migrate/20150324104002_remove_user_index_from_spree_state_changes.rb +14 -0
  138. data/db/migrate/20150522071831_add_position_to_spree_payment_methods.rb +5 -0
  139. data/db/migrate/20150626181949_add_taxable_adjustment_total_to_line_item.rb +19 -0
  140. data/db/migrate/20150627090949_migrate_payment_methods_display.rb +12 -0
  141. data/db/migrate/20150714154102_spree_payment_method_store_credits.rb +12 -0
  142. data/db/migrate/20150726141425_rename_has_and_belongs_to_associations_to_model_names.rb +18 -0
  143. data/db/migrate/20150727191614_spree_store_credit_types.rb +11 -0
  144. data/db/migrate/20150819154308_add_discontinued_to_products_and_variants.rb +68 -0
  145. data/db/migrate/20151220072838_remove_shipping_method_id_from_spree_orders.rb +13 -0
  146. data/db/migrate/20160207191757_add_id_column_to_earlier_habtm_tables.rb +16 -0
  147. data/db/migrate/20160219165458_add_indexes.rb +14 -0
  148. data/lib/generators/spree/dummy/templates/rails/database.yml +31 -24
  149. data/lib/generators/spree/dummy/templates/rails/test.rb +2 -1
  150. data/lib/spree/core.rb +16 -0
  151. data/lib/spree/core/controller_helpers/auth.rb +1 -1
  152. data/lib/spree/core/controller_helpers/common.rb +3 -3
  153. data/lib/spree/core/controller_helpers/order.rb +6 -5
  154. data/lib/spree/core/controller_helpers/search.rb +1 -1
  155. data/lib/spree/core/controller_helpers/store.rb +29 -0
  156. data/lib/spree/core/delegate_belongs_to.rb +2 -2
  157. data/lib/spree/core/engine.rb +30 -25
  158. data/lib/spree/core/environment.rb +1 -1
  159. data/lib/spree/core/importer/order.rb +37 -40
  160. data/lib/spree/core/number_generator.rb +52 -0
  161. data/lib/spree/core/product_filters.rb +1 -1
  162. data/lib/spree/core/search/base.rb +4 -3
  163. data/lib/spree/core/version.rb +1 -1
  164. data/lib/spree/localized_number.rb +3 -1
  165. data/lib/spree/permitted_attributes.rb +5 -2
  166. data/lib/spree/testing_support/common_rake.rb +3 -3
  167. data/lib/spree/testing_support/factories.rb +3 -3
  168. data/lib/spree/testing_support/factories/address_factory.rb +1 -1
  169. data/lib/spree/testing_support/factories/country_factory.rb +2 -2
  170. data/lib/spree/testing_support/factories/order_factory.rb +2 -2
  171. data/lib/spree/testing_support/factories/payment_factory.rb +5 -0
  172. data/lib/spree/testing_support/factories/payment_method_factory.rb +8 -0
  173. data/lib/spree/testing_support/factories/promotion_rule_factory.rb +5 -0
  174. data/lib/spree/testing_support/factories/refund_factory.rb +9 -1
  175. data/lib/spree/testing_support/factories/return_authorization_factory.rb +2 -0
  176. data/lib/spree/testing_support/factories/state_factory.rb +2 -2
  177. data/lib/spree/testing_support/factories/store_credit_category_factory.rb +9 -0
  178. data/lib/spree/testing_support/factories/store_credit_event_factory.rb +8 -0
  179. data/lib/spree/testing_support/factories/store_credit_factory.rb +17 -0
  180. data/lib/spree/testing_support/factories/store_credit_type_factory.rb +11 -0
  181. data/lib/spree/testing_support/factories/user_factory.rb +1 -1
  182. data/lib/spree/testing_support/factories/zone_member_factory.rb +6 -0
  183. data/lib/spree/testing_support/microdata.rb +189 -0
  184. data/lib/tasks/core.rake +68 -0
  185. data/lib/tasks/exchanges.rake +2 -2
  186. data/spec/fixtures/microdata.html +22 -0
  187. data/spec/fixtures/microdata_itemref.html +15 -0
  188. data/spec/fixtures/microdata_no_itemscope.html +20 -0
  189. data/spec/helpers/base_helper_spec.rb +64 -1
  190. data/spec/helpers/products_helper_spec.rb +75 -3
  191. data/spec/lib/i18n_spec.rb +2 -2
  192. data/spec/lib/search/base_spec.rb +2 -2
  193. data/spec/lib/spree/core/controller_helpers/auth_spec.rb +4 -2
  194. data/spec/lib/spree/core/controller_helpers/store_spec.rb +56 -0
  195. data/spec/lib/spree/core/importer/order_spec.rb +226 -123
  196. data/spec/lib/spree/core/number_generator_spec.rb +175 -0
  197. data/spec/lib/spree/core_spec.rb +23 -0
  198. data/spec/lib/spree/localized_number_spec.rb +10 -0
  199. data/spec/mailers/order_mailer_spec.rb +11 -13
  200. data/spec/mailers/shipment_mailer_spec.rb +26 -8
  201. data/spec/mailers/test_mailer_spec.rb +15 -1
  202. data/spec/models/option_type_prototype_spec.rb +9 -0
  203. data/spec/models/spree/ability_spec.rb +6 -13
  204. data/spec/models/spree/address_spec.rb +1 -1
  205. data/spec/models/spree/adjustable/adjuster/base_spec.rb +10 -0
  206. data/spec/models/spree/adjustable/adjuster/promotion_spec.rb +211 -0
  207. data/spec/models/spree/adjustable/adjuster/tax_spec.rb +86 -0
  208. data/spec/models/spree/adjustable/adjustments_updater_spec.rb +2 -262
  209. data/spec/models/spree/adjustment_spec.rb +27 -1
  210. data/spec/models/spree/app_configuration_spec.rb +5 -2
  211. data/spec/models/spree/calculator/default_tax_spec.rb +39 -14
  212. data/spec/models/spree/concerns/user_methods_spec.rb +55 -0
  213. data/spec/models/spree/concerns/vat_price_calculation_spec.rb +66 -0
  214. data/spec/models/spree/country_spec.rb +45 -8
  215. data/spec/models/spree/credit_card_spec.rb +8 -8
  216. data/spec/models/spree/customer_return_spec.rb +4 -26
  217. data/spec/models/spree/gateway_spec.rb +7 -0
  218. data/spec/models/spree/image_spec.rb +3 -0
  219. data/spec/models/spree/inventory_unit_spec.rb +1 -18
  220. data/spec/models/spree/line_item_spec.rb +78 -18
  221. data/spec/models/spree/option_type_spec.rb +2 -2
  222. data/spec/models/spree/option_value_spec.rb +8 -3
  223. data/spec/models/spree/order/checkout_spec.rb +49 -39
  224. data/spec/models/spree/order/currency_updater_spec.rb +3 -3
  225. data/spec/models/spree/order/finalizing_spec.rb +0 -3
  226. data/spec/models/spree/order/payment_spec.rb +1 -1
  227. data/spec/models/spree/order/state_machine_spec.rb +1 -6
  228. data/spec/models/spree/order/store_credit_spec.rb +423 -0
  229. data/spec/models/spree/order/updating_spec.rb +2 -2
  230. data/spec/models/spree/order_contents_spec.rb +42 -1
  231. data/spec/models/spree/order_inventory_spec.rb +27 -17
  232. data/spec/models/spree/order_spec.rb +65 -52
  233. data/spec/models/spree/payment/gateway_options_spec.rb +10 -2
  234. data/spec/models/spree/payment/store_credit_spec.rb +60 -0
  235. data/spec/models/spree/payment_method/store_credit_spec.rb +291 -0
  236. data/spec/models/spree/payment_method_spec.rb +22 -14
  237. data/spec/models/spree/payment_spec.rb +37 -44
  238. data/spec/models/spree/price_spec.rb +86 -0
  239. data/spec/models/spree/product/scopes_spec.rb +35 -0
  240. data/spec/models/spree/product_option_type_spec.rb +6 -2
  241. data/spec/models/spree/product_promotion_rule_spec.rb +9 -0
  242. data/spec/models/spree/product_property_spec.rb +11 -0
  243. data/spec/models/spree/product_spec.rb +82 -15
  244. data/spec/models/spree/promotion/actions/create_item_adjustments_spec.rb +1 -1
  245. data/spec/models/spree/promotion/rules/user_spec.rb +8 -0
  246. data/spec/models/spree/promotion_action_spec.rb +1 -1
  247. data/spec/models/spree/promotion_rule_spec.rb +1 -1
  248. data/spec/models/spree/promotion_rule_taxon_spec.rb +9 -0
  249. data/spec/models/spree/promotion_rule_user_spec.rb +9 -0
  250. data/spec/models/spree/promotion_spec.rb +57 -36
  251. data/spec/models/spree/property_prototype_spec.rb +9 -0
  252. data/spec/models/spree/prototype_taxon_spec.rb +9 -0
  253. data/spec/models/spree/refund_reason_spec.rb +7 -0
  254. data/spec/models/spree/reimbursement_spec.rb +3 -30
  255. data/spec/models/spree/reimbursement_tax_calculator_spec.rb +17 -5
  256. data/spec/models/spree/reimbursement_type/store_credit_spec.rb +101 -0
  257. data/spec/models/spree/return_authorization_reason_spec.rb +7 -0
  258. data/spec/models/spree/return_authorization_spec.rb +2 -22
  259. data/spec/models/spree/return_item_spec.rb +50 -1
  260. data/spec/models/spree/returns_calculator_spec.rb +1 -1
  261. data/spec/models/spree/role_spec.rb +7 -0
  262. data/spec/models/spree/shipment_spec.rb +17 -17
  263. data/spec/models/spree/shipping_calculator_spec.rb +2 -2
  264. data/spec/models/spree/shipping_category_spec.rb +14 -0
  265. data/spec/models/spree/shipping_method_spec.rb +9 -2
  266. data/spec/models/spree/shipping_rate_spec.rb +40 -41
  267. data/spec/models/spree/state_spec.rb +12 -1
  268. data/spec/models/spree/stock/content_item_spec.rb +9 -0
  269. data/spec/models/spree/stock/estimator_spec.rb +56 -8
  270. data/spec/models/spree/stock/quantifier_spec.rb +61 -32
  271. data/spec/models/spree/stock_item_spec.rb +19 -1
  272. data/spec/models/spree/store_credit_event_spec.rb +101 -0
  273. data/spec/models/spree/store_credit_spec.rb +786 -0
  274. data/spec/models/spree/store_spec.rb +39 -11
  275. data/spec/models/spree/tax_category_spec.rb +6 -1
  276. data/spec/models/spree/tax_rate_spec.rb +204 -44
  277. data/spec/models/spree/user_spec.rb +105 -38
  278. data/spec/models/spree/variant_spec.rb +281 -9
  279. data/spec/models/spree/zone_member_spec.rb +38 -0
  280. data/spec/models/spree/zone_spec.rb +32 -8
  281. data/spec/spec_helper.rb +3 -0
  282. data/spec/support/concerns/{adjustment_source_spec.rb → adjustment_source.rb} +0 -0
  283. data/spec/support/concerns/{default_price_spec.rb → default_price.rb} +9 -0
  284. data/spec/validators/db_maximum_length_validator_spec.rb +22 -0
  285. data/spree_core.gemspec +5 -6
  286. metadata +99 -36
  287. data/CHANGELOG.md +0 -4
  288. data/app/models/concerns/spree/number_generator.rb +0 -39
  289. data/spec/models/spree/validations/db_maximum_length_validator_spec.rb +0 -24
@@ -1,11 +1,15 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe Spree::OrderInventory, :type => :model do
3
+ describe Spree::OrderInventory, type: :model do
4
4
  let(:order) { create :completed_order_with_totals }
5
5
  let(:line_item) { order.line_items.first }
6
6
 
7
7
  subject { described_class.new(order, line_item) }
8
8
 
9
+ describe 'delegate' do
10
+ it { is_expected.to delegate_method(:inventory_units).to(:line_item) }
11
+ end
12
+
9
13
  context "when order is missing inventory units" do
10
14
  before { line_item.update_column(:quantity, 2) }
11
15
 
@@ -91,9 +95,9 @@ describe Spree::OrderInventory, :type => :model do
91
95
  before do
92
96
  subject.verify
93
97
 
94
- order.shipments.create(:stock_location_id => stock_location.id, :cost => 5)
98
+ order.shipments.create(stock_location_id: stock_location.id, cost: 5)
95
99
 
96
- shipped = order.shipments.create(:stock_location_id => order.shipments.first.stock_location.id, :cost => 10)
100
+ shipped = order.shipments.create(stock_location_id: order.shipments.first.stock_location.id, cost: 10)
97
101
  shipped.update_column(:state, 'shipped')
98
102
  end
99
103
 
@@ -163,11 +167,13 @@ describe Spree::OrderInventory, :type => :model do
163
167
  end
164
168
 
165
169
  it 'should destroy backordered units first' do
166
- allow(shipment).to receive_messages(inventory_units_for_item: [
167
- mock_model(Spree::InventoryUnit, :variant_id => variant.id, :state => 'backordered'),
168
- mock_model(Spree::InventoryUnit, :variant_id => variant.id, :state => 'on_hand'),
169
- mock_model(Spree::InventoryUnit, :variant_id => variant.id, :state => 'backordered')
170
- ])
170
+ allow(shipment).to receive_messages(
171
+ inventory_units_for_item: [
172
+ mock_model(Spree::InventoryUnit, variant_id: variant.id, state: 'backordered', shipped?: false),
173
+ mock_model(Spree::InventoryUnit, variant_id: variant.id, state: 'on_hand', shipped?: false),
174
+ mock_model(Spree::InventoryUnit, variant_id: variant.id, state: 'backordered', shipped?: false)
175
+ ]
176
+ )
171
177
 
172
178
  expect(shipment.inventory_units_for_item[0]).to receive(:destroy)
173
179
  expect(shipment.inventory_units_for_item[1]).not_to receive(:destroy)
@@ -177,10 +183,12 @@ describe Spree::OrderInventory, :type => :model do
177
183
  end
178
184
 
179
185
  it 'should destroy unshipped units first' do
180
- allow(shipment).to receive_messages(inventory_units_for_item: [
181
- mock_model(Spree::InventoryUnit, :variant_id => variant.id, :state => 'shipped'),
182
- mock_model(Spree::InventoryUnit, :variant_id => variant.id, :state => 'on_hand')
183
- ])
186
+ allow(shipment).to receive_messages(
187
+ inventory_units_for_item: [
188
+ mock_model(Spree::InventoryUnit, variant_id: variant.id, state: 'shipped', shipped?: true),
189
+ mock_model(Spree::InventoryUnit, variant_id: variant.id, state: 'on_hand', shipped?: false)
190
+ ]
191
+ )
184
192
 
185
193
  expect(shipment.inventory_units_for_item[0]).not_to receive(:destroy)
186
194
  expect(shipment.inventory_units_for_item[1]).to receive(:destroy)
@@ -189,10 +197,12 @@ describe Spree::OrderInventory, :type => :model do
189
197
  end
190
198
 
191
199
  it 'only attempts to destroy as many units as are eligible, and return amount destroyed' do
192
- allow(shipment).to receive_messages(inventory_units_for_item: [
193
- mock_model(Spree::InventoryUnit, :variant_id => variant.id, :state => 'shipped'),
194
- mock_model(Spree::InventoryUnit, :variant_id => variant.id, :state => 'on_hand')
195
- ])
200
+ allow(shipment).to receive_messages(
201
+ inventory_units_for_item: [
202
+ mock_model(Spree::InventoryUnit, variant_id: variant.id, state: 'shipped', shipped?: true),
203
+ mock_model(Spree::InventoryUnit, variant_id: variant.id, state: 'on_hand', shipped?: false)
204
+ ]
205
+ )
196
206
 
197
207
  expect(shipment.inventory_units_for_item[0]).not_to receive(:destroy)
198
208
  expect(shipment.inventory_units_for_item[1]).to receive(:destroy)
@@ -201,7 +211,7 @@ describe Spree::OrderInventory, :type => :model do
201
211
  end
202
212
 
203
213
  it 'should destroy self if not inventory units remain' do
204
- allow(shipment.inventory_units).to receive_messages(:count => 0)
214
+ allow(shipment.inventory_units).to receive_messages(count: 0)
205
215
  expect(shipment).to receive(:destroy)
206
216
 
207
217
  expect(subject.send(:remove_from_shipment, shipment, 1)).to eq(1)
@@ -15,6 +15,37 @@ describe Spree::Order, :type => :model do
15
15
  allow(Spree::LegacyUser).to receive_messages(:current => mock_model(Spree::LegacyUser, :id => 123))
16
16
  end
17
17
 
18
+ describe '.scopes' do
19
+ let!(:user) { FactoryGirl.create(:user) }
20
+ let!(:completed_order) { FactoryGirl.create(:order, user: user, completed_at: Time.current) }
21
+ let!(:incompleted_order) { FactoryGirl.create(:order, user: user, completed_at: nil) }
22
+
23
+ describe '.complete' do
24
+ it { expect(Spree::Order.complete).to include completed_order }
25
+ it { expect(Spree::Order.complete).not_to include incompleted_order }
26
+ end
27
+
28
+ describe '.incomplete' do
29
+ it { expect(Spree::Order.incomplete).to include incompleted_order }
30
+ it { expect(Spree::Order.incomplete).not_to include completed_order }
31
+ end
32
+ end
33
+
34
+ describe '#update_with_updater!' do
35
+ let(:updater) { Spree::OrderUpdater.new(order) }
36
+
37
+ before do
38
+ allow(order).to receive(:updater).and_return(updater)
39
+ allow(updater).to receive(:update).and_return(true)
40
+ end
41
+
42
+ after { order.update_with_updater! }
43
+
44
+ it 'expects to update order with order updater' do
45
+ expect(updater).to receive(:update).and_return(true)
46
+ end
47
+ end
48
+
18
49
  context "#cancel" do
19
50
  let(:order) { create(:completed_order_with_totals) }
20
51
  let!(:payment) do
@@ -157,9 +188,6 @@ describe Spree::Order, :type => :model do
157
188
  end
158
189
 
159
190
  it "should freeze all adjustments" do
160
- # Stub this method as it's called due to a callback
161
- # and it's irrelevant to this test
162
- allow(order).to receive :has_available_shipment
163
191
  allow(Spree::OrderMailer).to receive_message_chain :confirm_email, :deliver_later
164
192
  adjustments = [double]
165
193
  expect(order).to receive(:all_adjustments).and_return(adjustments)
@@ -203,15 +231,15 @@ describe Spree::Order, :type => :model do
203
231
  end
204
232
  end
205
233
 
206
- describe '#ensure_line_item_variants_are_not_deleted' do
207
- subject { order.ensure_line_item_variants_are_not_deleted }
234
+ describe "#ensure_line_item_variants_are_not_discontinued" do
235
+ subject { order.ensure_line_item_variants_are_not_discontinued }
208
236
 
209
237
  let(:order) { create :order_with_line_items }
210
238
 
211
239
  context 'when variant is destroyed' do
212
240
  before do
213
241
  allow(order).to receive(:restart_checkout_flow)
214
- order.line_items.first.variant.destroy
242
+ order.line_items.first.variant.discontinue!
215
243
  end
216
244
 
217
245
  it 'should restart checkout flow' do
@@ -221,7 +249,7 @@ describe Spree::Order, :type => :model do
221
249
 
222
250
  it 'should have error message' do
223
251
  subject
224
- expect(order.errors[:base]).to include(Spree.t(:deleted_variants_present))
252
+ expect(order.errors[:base]).to include(Spree.t(:discontinued_variants_present))
225
253
  end
226
254
 
227
255
  it 'should be false' do
@@ -267,23 +295,37 @@ describe Spree::Order, :type => :model do
267
295
  end
268
296
 
269
297
  context "empty!" do
270
- let(:order) { stub_model(Spree::Order, item_count: 2) }
298
+ let(:order) { Spree::Order.create(email: 'test@example.com') }
299
+ let(:promotion) { create :promotion, code: '10off' }
271
300
 
272
301
  before do
273
- allow(order).to receive_messages(line_items: [1, 2])
274
- allow(order).to receive_messages(adjustments: [])
275
- allow(order).to receive_message_chain(:line_items, sum: 0)
302
+ promotion.orders << order
276
303
  end
277
304
 
278
- it "clears out line items, adjustments and update totals" do
279
- expect(order.line_items).to receive(:destroy_all)
280
- expect(order.adjustments).to receive(:destroy_all)
281
- expect(order.shipments).to receive(:destroy_all)
282
- expect(order.updater).to receive(:update_totals)
283
- expect(order.updater).to receive(:persist_totals)
305
+ context 'completed order' do
306
+ before do
307
+ order.update_columns(state: 'complete', completed_at: Time.current)
308
+ end
284
309
 
285
- order.empty!
286
- expect(order.item_total).to eq 0
310
+ it "raises an exception" do
311
+ expect { order.empty! }.to raise_error(RuntimeError, Spree.t(:cannot_empty_completed_order))
312
+ end
313
+ end
314
+
315
+ context 'incomplete order' do
316
+ before do
317
+ order.empty!
318
+ end
319
+
320
+ it "clears out line items, adjustments and update totals" do
321
+ expect(order.line_items.count).to be_zero
322
+ expect(order.adjustments.count).to be_zero
323
+ expect(order.shipments.count).to be_zero
324
+ expect(order.order_promotions.count).to be_zero
325
+ expect(order.promo_total).to be_zero
326
+ expect(order.item_total).to be_zero
327
+ expect(order.empty!).to eq(order)
328
+ end
287
329
  end
288
330
  end
289
331
 
@@ -392,7 +434,7 @@ describe Spree::Order, :type => :model do
392
434
  it "calls hook during update" do
393
435
  order = create(:order)
394
436
  expect(order).to receive(:add_awesome_sauce)
395
- order.update!
437
+ order.update_with_updater!
396
438
  end
397
439
 
398
440
  it "calls hook during finalize" do
@@ -550,35 +592,6 @@ describe Spree::Order, :type => :model do
550
592
  end
551
593
  end
552
594
 
553
- context "#generate_order_number" do
554
- context "when no configure" do
555
- let(:default_length) { 9 + 'R'.length }
556
- subject(:order_number) { order.generate_number }
557
- its(:class) { should eq String }
558
- its(:length) { should eq default_length }
559
- it { should match /^R/ }
560
- end
561
-
562
- context "when length option is 5" do
563
- let(:option_length) { 5 + 'R'.length }
564
- it "should be option length for order number" do
565
- expect(order.generate_number(length: 5).length).to eq option_length
566
- end
567
- end
568
-
569
- context "when letters option is true" do
570
- it "generates order number include letter" do
571
- expect(order.generate_number(length: 100, letters: true)).to match /[A-Z]/
572
- end
573
- end
574
-
575
- context "when prefix option is 'P'" do
576
- it "generates order number and it prefix is 'P'" do
577
- expect(order.generate_number(prefix: 'P')).to match /^P/
578
- end
579
- end
580
- end
581
-
582
595
  describe "#associate_user!" do
583
596
  let(:user) { FactoryGirl.create(:user_with_addreses) }
584
597
  let(:email) { user.email }
@@ -746,7 +759,7 @@ describe Spree::Order, :type => :model do
746
759
  order.completed_at = nil
747
760
  expect(order.completed?).to be false
748
761
 
749
- order.completed_at = Time.now
762
+ order.completed_at = Time.current
750
763
  expect(order.completed?).to be true
751
764
  end
752
765
  end
@@ -785,14 +798,14 @@ describe Spree::Order, :type => :model do
785
798
  it "should be false for completed order in the canceled state" do
786
799
  order.state = 'canceled'
787
800
  order.shipment_state = 'ready'
788
- order.completed_at = Time.now
801
+ order.completed_at = Time.current
789
802
  expect(order.can_cancel?).to be false
790
803
  end
791
804
 
792
805
  it "should be true for completed order with no shipment" do
793
806
  order.state = 'complete'
794
807
  order.shipment_state = nil
795
- order.completed_at = Time.now
808
+ order.completed_at = Time.current
796
809
  expect(order.can_cancel?).to be true
797
810
  end
798
811
  end
@@ -8,7 +8,15 @@ RSpec.describe Spree::Payment::GatewayOptions, type: :model do
8
8
  Spree::Payment,
9
9
  order: order,
10
10
  number: "P1566",
11
- currency: "EUR"
11
+ currency: "EUR",
12
+ payment_method: payment_method
13
+ )
14
+ end
15
+
16
+ let(:payment_method) do
17
+ double(
18
+ Spree::Gateway::Bogus,
19
+ exchange_multiplier: Spree::Gateway::FROM_DOLLAR_TO_CENT_RATE
12
20
  )
13
21
  end
14
22
 
@@ -31,6 +39,7 @@ RSpec.describe Spree::Payment::GatewayOptions, type: :model do
31
39
  let(:bill_address) do
32
40
  double Spree::Address, active_merchant_hash: { bill: :address }
33
41
  end
42
+
34
43
  let(:ship_address) do
35
44
  double Spree::Address, active_merchant_hash: { ship: :address }
36
45
  end
@@ -115,5 +124,4 @@ RSpec.describe Spree::Payment::GatewayOptions, type: :model do
115
124
  end
116
125
  it { should == expected }
117
126
  end
118
-
119
127
  end
@@ -0,0 +1,60 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'Payment' do
4
+ context '#cancel!' do
5
+ subject { payment.cancel! }
6
+
7
+ context 'a store credit' do
8
+ let(:store_credit) { create(:store_credit, amount_used: captured_amount) }
9
+ let(:auth_code) { '1-SC-20141111111111' }
10
+ let(:captured_amount) { 10.0 }
11
+ let(:payment) { create(:store_credit_payment, response_code: auth_code) }
12
+
13
+ let!(:capture_event) do
14
+ create(:store_credit_auth_event,
15
+ action: Spree::StoreCredit::CAPTURE_ACTION,
16
+ authorization_code: auth_code,
17
+ amount: captured_amount,
18
+ store_credit: store_credit)
19
+ end
20
+
21
+ let(:successful_response) do
22
+ ActiveMerchant::Billing::Response.new(
23
+ true,
24
+ Spree.t('store_credit_payment_method.successful_action', action: :cancel),
25
+ {},
26
+ authorization: payment.response_code
27
+ )
28
+ end
29
+
30
+ let(:failed_response) do
31
+ ActiveMerchant::Billing::Response.new(
32
+ false,
33
+ Spree.t('store_credit_payment_method.unable_to_find_for_action', action: :cancel,
34
+ auth_code: payment.response_code),
35
+ {},
36
+ {}
37
+ )
38
+ end
39
+
40
+ it 'attemps to cancels the payment' do
41
+ expect(payment.payment_method).to receive(:cancel).with(payment.response_code) { successful_response }
42
+ subject
43
+ end
44
+
45
+ context 'cancels successfully' do
46
+ it 'voids the payment' do
47
+ expect { subject }.to change { payment.state }.to('void')
48
+ end
49
+ end
50
+
51
+ context 'does not cancel successfully' do
52
+ it 'does not change the payment state' do
53
+ expect(payment.payment_method).to receive(:cancel).with(payment.response_code) { failed_response }
54
+ expect { subject }.to raise_error(Spree::Core::GatewayError)
55
+ expect(payment.reload.state).not_to eq 'void'
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,291 @@
1
+ require 'spec_helper'
2
+
3
+ describe Spree::PaymentMethod::StoreCredit do
4
+ let(:order) { create(:order) }
5
+ let(:payment) { create(:payment, order: order) }
6
+ let(:gateway_options) { payment.gateway_options }
7
+
8
+ context '#authorize' do
9
+ subject do
10
+ Spree::PaymentMethod::StoreCredit.new.authorize(auth_amount, store_credit, gateway_options)
11
+ end
12
+
13
+ let(:auth_amount) { store_credit.amount_remaining * 100 }
14
+ let(:store_credit) { create(:store_credit) }
15
+ let(:gateway_options) { super().merge(originator: originator) }
16
+ let(:originator) { nil }
17
+
18
+ context 'without an invalid store credit' do
19
+ let(:store_credit) { nil }
20
+ let(:auth_amount) { 10 }
21
+
22
+ it 'declines an unknown store credit' do
23
+ expect(subject.success?).to be false
24
+ expect(subject.message).to include Spree.t('store_credit_payment_method.unable_to_find')
25
+ end
26
+ end
27
+
28
+ context 'with insuffient funds' do
29
+ let(:auth_amount) { (store_credit.amount_remaining * 100) + 1 }
30
+
31
+ it 'declines a store credit' do
32
+ expect(subject.success?).to be false
33
+ expect(subject.message).to include Spree.t('store_credit_payment_method.insufficient_funds')
34
+ end
35
+ end
36
+
37
+ context 'when the currency does not match the order currency' do
38
+ let(:store_credit) { create(:store_credit, currency: 'AUD') }
39
+
40
+ it 'declines the credit' do
41
+ expect(subject.success?).to be false
42
+ expect(subject.message).to include Spree.t('store_credit_payment_method.currency_mismatch')
43
+ end
44
+ end
45
+
46
+ context 'with a valid request' do
47
+ it 'authorizes a valid store credit' do
48
+ expect(subject.success?).to be true
49
+ expect(subject.authorization).to_not be_nil
50
+ end
51
+
52
+ context 'with an originator' do
53
+ let(:originator) { double('originator') }
54
+
55
+ it 'passes the originator' do
56
+ expect_any_instance_of(Spree::StoreCredit).to receive(:authorize).
57
+ with(anything, anything, action_originator: originator)
58
+ subject
59
+ end
60
+ end
61
+ end
62
+ end
63
+
64
+ context '#capture' do
65
+ subject do
66
+ Spree::PaymentMethod::StoreCredit.new.capture(capture_amount, auth_code, gateway_options)
67
+ end
68
+
69
+ let(:capture_amount) { 10_00 }
70
+ let(:auth_code) { auth_event.authorization_code }
71
+ let(:gateway_options) { super().merge(originator: originator) }
72
+
73
+ let(:authorized_amount) { capture_amount / 100.0 }
74
+ let(:auth_event) { create(:store_credit_auth_event, store_credit: store_credit, amount: authorized_amount) }
75
+ let(:store_credit) { create(:store_credit, amount_authorized: authorized_amount) }
76
+ let(:originator) { nil }
77
+
78
+ context 'with an invalid auth code' do
79
+ let(:auth_code) { -1 }
80
+
81
+ it 'declines an unknown store credit' do
82
+ expect(subject.success?).to be false
83
+ expect(subject.message).to include Spree.t('store_credit_payment_method.unable_to_find')
84
+ end
85
+ end
86
+
87
+ context 'when unable to authorize the amount' do
88
+ let(:authorized_amount) { (capture_amount - 1) / 100 }
89
+
90
+ before do
91
+ allow_any_instance_of(Spree::StoreCredit).to receive_messages(authorize: true)
92
+ end
93
+
94
+ it 'declines a store credit' do
95
+ expect(subject.success?).to be false
96
+ expect(subject.message).to include Spree.t('store_credit_payment_method.insufficient_authorized_amount')
97
+ end
98
+ end
99
+
100
+ context 'when the currency does not match the order currency' do
101
+ let(:store_credit) { create(:store_credit, currency: 'AUD', amount_authorized: authorized_amount) }
102
+
103
+ it 'declines the credit' do
104
+ expect(subject.success?).to be false
105
+ expect(subject.message).to include Spree.t('store_credit_payment_method.currency_mismatch')
106
+ end
107
+ end
108
+
109
+ context 'with a valid request' do
110
+ it 'captures the store credit' do
111
+ expect(subject.message).to include Spree.t('store_credit_payment_method.successful_action',
112
+ action: Spree::StoreCredit::CAPTURE_ACTION)
113
+ expect(subject.success?).to be true
114
+ end
115
+
116
+ context 'with an originator' do
117
+ let(:originator) { double('originator') }
118
+
119
+ it 'passes the originator' do
120
+ expect_any_instance_of(Spree::StoreCredit).to receive(:capture).
121
+ with(anything, anything, anything, action_originator: originator)
122
+ subject
123
+ end
124
+ end
125
+ end
126
+ end
127
+
128
+ context '#void' do
129
+ subject do
130
+ Spree::PaymentMethod::StoreCredit.new.void(auth_code, gateway_options)
131
+ end
132
+
133
+ let(:auth_code) { auth_event.authorization_code }
134
+ let(:gateway_options) { super().merge(originator: originator) }
135
+ let(:auth_event) { create(:store_credit_auth_event) }
136
+ let(:originator) { nil }
137
+
138
+ context 'with an invalid auth code' do
139
+ let(:auth_code) { 1 }
140
+
141
+ it 'declines an unknown store credit' do
142
+ expect(subject.success?).to be false
143
+ expect(subject.message).to include Spree.t('store_credit_payment_method.unable_to_find')
144
+ end
145
+ end
146
+
147
+ context 'when the store credit is not voided successfully' do
148
+ before { allow_any_instance_of(Spree::StoreCredit).to receive(:void).and_return false }
149
+
150
+ it 'returns an error response' do
151
+ expect(subject.success?).to be false
152
+ end
153
+ end
154
+
155
+ it 'voids a valid store credit void request' do
156
+ expect(subject.success?).to be true
157
+ expect(subject.message).to include Spree.t('store_credit_payment_method.successful_action',
158
+ action: Spree::StoreCredit::VOID_ACTION)
159
+ end
160
+
161
+ context 'with an originator' do
162
+ let(:originator) { double('originator') }
163
+
164
+ it 'passes the originator' do
165
+ expect_any_instance_of(Spree::StoreCredit).to receive(:void).with(anything, action_originator: originator)
166
+ subject
167
+ end
168
+ end
169
+ end
170
+
171
+ context '#purchase' do
172
+ it "declines a purchase if it can't find a pending credit for the correct amount" do
173
+ amount = 100.0
174
+ store_credit = create(:store_credit)
175
+ auth_code = store_credit.generate_authorization_code
176
+ store_credit.store_credit_events.create!(action: Spree::StoreCredit::ELIGIBLE_ACTION,
177
+ amount: amount,
178
+ authorization_code: auth_code)
179
+ store_credit.store_credit_events.create!(action: Spree::StoreCredit::CAPTURE_ACTION,
180
+ amount: amount, authorization_code: auth_code)
181
+
182
+ response = subject.purchase(amount * 100.0, store_credit, gateway_options)
183
+ expect(response.success?).to be false
184
+ expect(response.message).to include Spree.t('store_credit_payment_method.unable_to_find')
185
+ end
186
+
187
+ it 'captures a purchase if it can find a pending credit for the correct amount' do
188
+ amount = 100.0
189
+ store_credit = create(:store_credit)
190
+ auth_code = store_credit.generate_authorization_code
191
+ store_credit.store_credit_events.create!(action: Spree::StoreCredit::ELIGIBLE_ACTION,
192
+ amount: amount, authorization_code: auth_code)
193
+
194
+ response = subject.purchase(amount * 100.0, store_credit, gateway_options)
195
+ expect(response.success?).to be true
196
+ expect(response.message).to include Spree.t('store_credit_payment_method.successful_action',
197
+ action: Spree::StoreCredit::CAPTURE_ACTION)
198
+ end
199
+ end
200
+
201
+ context '#credit' do
202
+ subject do
203
+ Spree::PaymentMethod::StoreCredit.new.credit(credit_amount, auth_code, gateway_options)
204
+ end
205
+
206
+ let(:credit_amount) { 100.0 }
207
+ let(:auth_code) { auth_event.authorization_code }
208
+ let(:gateway_options) { super().merge(originator: originator) }
209
+ let(:auth_event) { create(:store_credit_auth_event) }
210
+ let(:originator) { nil }
211
+
212
+ context 'with an invalid auth code' do
213
+ let(:auth_code) { 1 }
214
+
215
+ it 'declines an unknown store credit' do
216
+ expect(subject.success?).to be false
217
+ expect(subject.message).to include Spree.t('store_credit_payment_method.unable_to_find')
218
+ end
219
+ end
220
+
221
+ context "when the store credit isn't credited successfully" do
222
+ before { allow(Spree::StoreCredit).to receive_messages(credit: false) }
223
+
224
+ it 'returns an error response' do
225
+ expect(subject.success?).to be false
226
+ end
227
+ end
228
+
229
+ context 'with a valid credit request' do
230
+ before { allow_any_instance_of(Spree::StoreCredit).to receive_messages(credit: true) }
231
+
232
+ it 'credits a valid store credit credit request' do
233
+ expect(subject.success?).to be true
234
+ expect(subject.message).to include Spree.t('store_credit_payment_method.successful_action',
235
+ action: Spree::StoreCredit::CREDIT_ACTION)
236
+ end
237
+ end
238
+
239
+ context 'with an originator' do
240
+ let(:originator) { double('originator') }
241
+
242
+ it 'passes the originator' do
243
+ allow_any_instance_of(Spree::StoreCredit).to receive(:credit).
244
+ with(anything, anything, anything, action_originator: originator)
245
+ subject
246
+ end
247
+ end
248
+ end
249
+
250
+ context '#cancel' do
251
+ subject do
252
+ Spree::PaymentMethod::StoreCredit.new.cancel(auth_code)
253
+ end
254
+
255
+ let(:store_credit) { create(:store_credit, amount_used: captured_amount) }
256
+ let(:auth_code) { '1-SC-20141111111111' }
257
+ let(:captured_amount) { 10.0 }
258
+
259
+ let!(:capture_event) do
260
+ create(:store_credit_auth_event,
261
+ action: Spree::StoreCredit::CAPTURE_ACTION,
262
+ authorization_code: auth_code,
263
+ amount: captured_amount,
264
+ store_credit: store_credit)
265
+ end
266
+
267
+ context 'store credit event found' do
268
+ it 'creates a store credit for the same amount that was captured' do
269
+ allow_any_instance_of(Spree::StoreCredit).to receive(:credit).
270
+ with(captured_amount, auth_code, store_credit.currency)
271
+ subject
272
+ end
273
+
274
+ it 'returns a valid store credit cancel request' do
275
+ expect(subject.success?).to be true
276
+ expect(subject.message).to include Spree.t('store_credit_payment_method.successful_action',
277
+ action: Spree::StoreCredit::CANCEL_ACTION)
278
+ end
279
+ end
280
+
281
+ context 'store credit event not found' do
282
+ subject do
283
+ Spree::PaymentMethod::StoreCredit.new.cancel('INVALID')
284
+ end
285
+
286
+ it 'returns an error response' do
287
+ expect(subject.success?).to be false
288
+ end
289
+ end
290
+ end
291
+ end