spree_core 2.2.14 → 2.3.0

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 (172) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/{spree.js.coffee → spree.js.coffee.erb} +11 -2
  3. data/app/controllers/spree/base_controller.rb +1 -0
  4. data/app/helpers/spree/base_helper.rb +5 -6
  5. data/app/helpers/spree/orders_helper.rb +4 -0
  6. data/app/helpers/spree/products_helper.rb +8 -7
  7. data/app/mailers/spree/base_mailer.rb +2 -2
  8. data/app/mailers/spree/order_mailer.rb +2 -2
  9. data/app/mailers/spree/shipment_mailer.rb +1 -1
  10. data/app/mailers/spree/test_mailer.rb +1 -1
  11. data/app/models/spree/ability.rb +15 -16
  12. data/app/models/spree/address.rb +3 -6
  13. data/app/models/spree/adjustment.rb +2 -2
  14. data/app/models/spree/alert.rb +1 -1
  15. data/app/models/spree/app_configuration.rb +17 -20
  16. data/app/models/spree/asset.rb +2 -2
  17. data/app/models/spree/base.rb +9 -0
  18. data/app/models/spree/calculator.rb +1 -1
  19. data/app/models/spree/calculator/flat_rate.rb +1 -1
  20. data/app/models/spree/calculator/flexi_rate.rb +1 -1
  21. data/app/models/spree/calculator/price_sack.rb +1 -3
  22. data/app/models/spree/calculator/shipping/flat_rate.rb +1 -1
  23. data/app/models/spree/calculator/shipping/flexi_rate.rb +1 -1
  24. data/app/models/spree/calculator/shipping/per_item.rb +1 -1
  25. data/app/models/spree/calculator/shipping/price_sack.rb +1 -3
  26. data/app/models/spree/classification.rb +1 -1
  27. data/app/models/spree/configuration.rb +1 -1
  28. data/app/models/spree/country.rb +1 -1
  29. data/app/models/spree/credit_card.rb +8 -12
  30. data/app/models/spree/gateway.rb +0 -3
  31. data/app/models/spree/gateway/bogus.rb +2 -3
  32. data/app/models/spree/image.rb +3 -1
  33. data/app/models/spree/inventory_unit.rb +5 -6
  34. data/app/models/spree/item_adjustments.rb +3 -4
  35. data/app/models/spree/legacy_user.rb +1 -1
  36. data/app/models/spree/line_item.rb +6 -13
  37. data/app/models/spree/log_entry.rb +1 -1
  38. data/app/models/spree/option_type.rb +1 -1
  39. data/app/models/spree/option_value.rb +1 -3
  40. data/app/models/spree/order.rb +52 -70
  41. data/app/models/spree/order/checkout.rb +17 -10
  42. data/app/models/spree/order/currency_updater.rb +1 -1
  43. data/app/models/spree/order_contents.rb +7 -4
  44. data/app/models/spree/order_populator.rb +1 -1
  45. data/app/models/spree/order_updater.rb +8 -21
  46. data/app/models/spree/payment.rb +26 -12
  47. data/app/models/spree/payment/processing.rb +5 -16
  48. data/app/models/spree/payment_capture_event.rb +1 -1
  49. data/app/models/spree/payment_method.rb +2 -2
  50. data/app/models/spree/payment_method/check.rb +0 -2
  51. data/app/models/spree/preference.rb +1 -31
  52. data/app/models/spree/preferences/configuration.rb +2 -6
  53. data/app/models/spree/preferences/preferable.rb +46 -74
  54. data/app/models/spree/preferences/preferable_class_methods.rb +11 -46
  55. data/app/models/spree/preferences/scoped_store.rb +33 -0
  56. data/app/models/spree/preferences/store.rb +8 -7
  57. data/app/models/spree/price.rb +1 -3
  58. data/app/models/spree/product.rb +59 -87
  59. data/app/models/spree/product/scopes.rb +22 -13
  60. data/app/models/spree/product_option_type.rb +1 -1
  61. data/app/models/spree/product_property.rb +1 -3
  62. data/app/models/spree/product_scope/scopes.rb +1 -1
  63. data/app/models/spree/promotion.rb +4 -5
  64. data/app/models/spree/promotion/actions/create_adjustment.rb +11 -2
  65. data/app/models/spree/promotion/actions/create_item_adjustments.rb +19 -2
  66. data/app/models/spree/promotion/actions/create_line_items.rb +2 -12
  67. data/app/models/spree/promotion/rules/user.rb +5 -1
  68. data/app/models/spree/promotion_action.rb +1 -1
  69. data/app/models/spree/promotion_action_line_item.rb +1 -1
  70. data/app/models/spree/promotion_handler/cart.rb +2 -14
  71. data/app/models/spree/promotion_handler/coupon.rb +3 -13
  72. data/app/models/spree/promotion_rule.rb +1 -1
  73. data/app/models/spree/property.rb +1 -3
  74. data/app/models/spree/prototype.rb +1 -1
  75. data/app/models/spree/return_authorization.rb +4 -10
  76. data/app/models/spree/role.rb +1 -1
  77. data/app/models/spree/shipment.rb +1 -9
  78. data/app/models/spree/shipping_category.rb +3 -3
  79. data/app/models/spree/shipping_method.rb +1 -1
  80. data/app/models/spree/shipping_method_category.rb +2 -2
  81. data/app/models/spree/shipping_rate.rb +3 -3
  82. data/app/models/spree/state.rb +1 -1
  83. data/app/models/spree/state_change.rb +1 -1
  84. data/app/models/spree/stock/availability_validator.rb +7 -3
  85. data/app/models/spree/stock/package.rb +0 -23
  86. data/app/models/spree/stock/splitter/backordered.rb +1 -1
  87. data/app/models/spree/stock/splitter/shipping_category.rb +1 -1
  88. data/app/models/spree/stock/splitter/weight.rb +1 -1
  89. data/app/models/spree/stock_item.rb +7 -10
  90. data/app/models/spree/stock_location.rb +2 -6
  91. data/app/models/spree/stock_movement.rb +1 -3
  92. data/app/models/spree/stock_transfer.rb +1 -3
  93. data/app/models/spree/store.rb +33 -0
  94. data/app/models/spree/tax_category.rb +2 -2
  95. data/app/models/spree/tax_rate.rb +21 -52
  96. data/app/models/spree/taxon.rb +9 -8
  97. data/app/models/spree/taxonomy.rb +1 -1
  98. data/app/models/spree/tracker.rb +1 -1
  99. data/app/models/spree/variant.rb +13 -15
  100. data/app/models/spree/variant/scopes.rb +1 -1
  101. data/app/models/spree/zone.rb +22 -22
  102. data/app/models/spree/zone_member.rb +2 -2
  103. data/config/initializers/user_class_extensions.rb +0 -8
  104. data/config/locales/en.yml +7 -42
  105. data/db/default/spree/countries.rb +2 -3
  106. data/db/default/spree/stores.rb +9 -0
  107. data/db/migrate/20130611054351_rename_shipping_methods_zones_to_spree_shipping_methods_zones.rb +0 -5
  108. data/db/migrate/20130807024301_upgrade_adjustments.rb +4 -5
  109. data/db/migrate/20130807024302_rename_adjustment_fields.rb +5 -2
  110. data/db/migrate/20131118183431_add_line_item_id_to_spree_inventory_units.rb +1 -1
  111. data/db/migrate/20140106065820_remove_value_type_from_spree_preferences.rb +8 -0
  112. data/db/migrate/20140227112348_add_preference_store_to_everything.rb +8 -0
  113. data/db/migrate/20140309023735_migrate_old_preferences.rb +23 -0
  114. data/db/migrate/20140309024355_create_spree_stores.rb +25 -0
  115. data/db/migrate/20140309033438_create_store_from_preferences.rb +30 -0
  116. data/db/migrate/20140315053743_add_timestamps_to_spree_assets.rb +6 -0
  117. data/db/migrate/20140331100557_add_additional_store_fields.rb +8 -0
  118. data/db/migrate/20140410141842_add_many_missing_indexes.rb +18 -0
  119. data/db/migrate/20140410150358_correct_some_polymorphic_index_and_add_more_missing.rb +66 -0
  120. data/db/migrate/20140508151342_change_spree_price_amount_precision.rb +1 -1
  121. data/db/migrate/20140518174634_add_token_to_spree_orders.rb +5 -0
  122. data/db/migrate/20140530024945_move_order_token_from_tokenized_permission.rb +29 -0
  123. data/db/migrate/20140601011216_set_shipment_total_for_users_upgrading.rb +5 -3
  124. data/db/migrate/20140604135309_drop_credit_card_first_name_and_last_name.rb +6 -0
  125. data/lib/generators/spree/dummy/dummy_generator.rb +1 -0
  126. data/lib/generators/spree/dummy/templates/initializers/devise.rb +3 -0
  127. data/lib/generators/spree/dummy/templates/rails/routes.rb +0 -1
  128. data/lib/generators/spree/install/install_generator.rb +8 -17
  129. data/lib/generators/spree/install/templates/config/initializers/spree.rb +2 -2
  130. data/lib/spree/core.rb +13 -9
  131. data/lib/spree/core/calculated_adjustments.rb +1 -1
  132. data/lib/spree/core/controller_helpers/auth.rb +27 -18
  133. data/lib/spree/core/controller_helpers/common.rb +2 -2
  134. data/lib/spree/core/controller_helpers/order.rb +15 -24
  135. data/lib/spree/core/controller_helpers/store.rb +19 -0
  136. data/lib/spree/core/delegate_belongs_to.rb +2 -2
  137. data/lib/spree/core/engine.rb +0 -10
  138. data/lib/spree/core/importer.rb +1 -0
  139. data/lib/spree/core/importer/order.rb +16 -44
  140. data/lib/spree/core/importer/product.rb +62 -0
  141. data/lib/spree/core/product_filters.rb +0 -4
  142. data/lib/spree/core/routes.rb +4 -6
  143. data/lib/spree/core/validators/email.rb +23 -1
  144. data/lib/spree/core/version.rb +1 -1
  145. data/lib/spree/money.rb +1 -169
  146. data/lib/spree/permitted_attributes.rb +6 -4
  147. data/lib/spree/testing_support/authorization_helpers.rb +23 -21
  148. data/lib/spree/testing_support/capybara_ext.rb +11 -21
  149. data/lib/spree/testing_support/common_rake.rb +3 -1
  150. data/lib/spree/testing_support/controller_requests.rb +0 -2
  151. data/lib/spree/testing_support/factories/credit_card_factory.rb +1 -1
  152. data/lib/spree/testing_support/factories/line_item_factory.rb +4 -1
  153. data/lib/spree/testing_support/factories/order_factory.rb +5 -4
  154. data/lib/spree/testing_support/factories/product_factory.rb +0 -4
  155. data/lib/spree/testing_support/factories/promotion_factory.rb +5 -7
  156. data/lib/spree/testing_support/factories/shipment_factory.rb +0 -1
  157. data/lib/spree/testing_support/factories/stock_factory.rb +2 -2
  158. data/lib/spree/testing_support/factories/store_factory.rb +8 -0
  159. data/lib/spree/testing_support/preferences.rb +3 -3
  160. data/lib/tasks/core.rake +2 -2
  161. metadata +48 -39
  162. data/app/models/spree/stock/order_counter.rb +0 -55
  163. data/app/models/spree/tokenized_permission.rb +0 -6
  164. data/app/views/spree/shared/_routes.html.erb +0 -13
  165. data/db/migrate/20140804185157_add_default_to_shipment_cost.rb +0 -10
  166. data/db/migrate/20141021194502_add_state_lock_version_to_order.rb +0 -5
  167. data/lib/spree/core/adjustment_source.rb +0 -26
  168. data/lib/spree/core/mail_interceptor.rb +0 -22
  169. data/lib/spree/core/mail_method.rb +0 -27
  170. data/lib/spree/core/mail_settings.rb +0 -55
  171. data/lib/spree/core/ransackable_attributes.rb +0 -15
  172. data/lib/spree/core/token_resource.rb +0 -27
@@ -1,5 +1,5 @@
1
1
  module Spree
2
- class Order < ActiveRecord::Base
2
+ class Order < Spree::Base
3
3
  module Checkout
4
4
  def self.included(klass)
5
5
  klass.class_eval do
@@ -71,7 +71,12 @@ module Spree
71
71
 
72
72
  if states[:payment]
73
73
  before_transition :to => :complete do |order|
74
- order.process_payments! if order.payment_required?
74
+ if order.payment_required? && order.payments.empty?
75
+ order.errors.add(:base, Spree.t(:no_payment_found))
76
+ false
77
+ elsif order.payment_required?
78
+ order.process_payments!
79
+ end
75
80
  end
76
81
  end
77
82
 
@@ -92,11 +97,9 @@ module Spree
92
97
  before_transition :from => :delivery, :do => :apply_free_shipping_promotions
93
98
  end
94
99
 
95
- before_transition to: :resumed, do: :ensure_line_items_are_in_stock
96
-
97
- after_transition to: :complete, do: :finalize!
98
- after_transition to: :resumed, do: :after_resume
99
- after_transition to: :canceled, do: :after_cancel
100
+ after_transition :to => :complete, :do => :finalize!
101
+ after_transition :to => :resumed, :do => :after_resume
102
+ after_transition :to => :canceled, :do => :after_cancel
100
103
 
101
104
  after_transition :from => any - :cart, :to => any - [:confirm, :complete] do |order|
102
105
  order.update_totals
@@ -206,11 +209,11 @@ module Spree
206
209
  checkout_step_index(state) > checkout_step_index(self.state)
207
210
  end
208
211
 
209
- define_callbacks :updating_from_params, terminator: 'result == false'
212
+ define_callbacks :updating_from_params, terminator: ->(target, result) { result == false }
210
213
 
211
214
  set_callback :updating_from_params, :before, :update_params_payment_source
212
215
 
213
- def update_from_params(params, permitted_params)
216
+ def update_from_params(params, permitted_params, request_env = {})
214
217
  success = false
215
218
  @updating_params = params
216
219
  run_callbacks :updating_from_params do
@@ -231,9 +234,13 @@ module Spree
231
234
  attributes[:payments_attributes].first.delete :source_attributes
232
235
  end
233
236
 
237
+ if attributes[:payments_attributes]
238
+ attributes[:payments_attributes].first[:request_env] = request_env
239
+ end
240
+
234
241
  success = self.update_attributes(attributes)
235
- set_shipments_cost if self.shipments.any?
236
242
  end
243
+
237
244
  @updating_params = nil
238
245
  success
239
246
  end
@@ -1,5 +1,5 @@
1
1
  module Spree
2
- class Order < ActiveRecord::Base
2
+ class Order < Spree::Base
3
3
  module CurrencyUpdater
4
4
  extend ActiveSupport::Concern
5
5
 
@@ -9,7 +9,6 @@ module Spree
9
9
  def add(variant, quantity = 1, currency = nil, shipment = nil)
10
10
  line_item = add_to_line_item(variant, quantity, currency, shipment)
11
11
  reload_totals
12
- shipment.present? ? shipment.update_amounts : order.ensure_updated_shipments
13
12
  PromotionHandler::Cart.new(order, line_item).activate
14
13
  ItemAdjustments.new(line_item).update
15
14
  reload_totals
@@ -19,7 +18,6 @@ module Spree
19
18
  def remove(variant, quantity = 1, shipment = nil)
20
19
  line_item = remove_from_line_item(variant, quantity, shipment)
21
20
  reload_totals
22
- shipment.present? ? shipment.update_amounts : order.ensure_updated_shipments
23
21
  PromotionHandler::Cart.new(order, line_item).activate
24
22
  ItemAdjustments.new(line_item).update
25
23
  reload_totals
@@ -49,7 +47,12 @@ module Spree
49
47
 
50
48
  def reload_totals
51
49
  order_updater.update_item_count
52
- order_updater.update
50
+ order_updater.update_item_total
51
+ order_updater.update_adjustment_total
52
+
53
+ order_updater.update_payment_state if order.completed?
54
+ order_updater.persist_totals
55
+
53
56
  order.reload
54
57
  end
55
58
 
@@ -77,7 +80,7 @@ module Spree
77
80
 
78
81
  def remove_from_line_item(variant, quantity, shipment=nil)
79
82
  line_item = grab_line_item_by_variant(variant, true)
80
- line_item.quantity += -quantity
83
+ line_item.quantity -= quantity
81
84
  line_item.target_shipment= shipment
82
85
 
83
86
  if line_item.quantity == 0
@@ -9,9 +9,9 @@ module Spree
9
9
  @errors = ActiveModel::Errors.new(self)
10
10
  end
11
11
 
12
+
12
13
  def populate(variant_id, quantity)
13
14
  attempt_cart_add(variant_id, quantity)
14
- order.ensure_updated_shipments
15
15
  valid?
16
16
  end
17
17
 
@@ -38,10 +38,9 @@ module Spree
38
38
  # +payment_total+ The total value of all finalized Payments (NOTE: non-finalized Payments are excluded)
39
39
  # +item_total+ The total value of all LineItems
40
40
  # +adjustment_total+ The total value of all adjustments (promotions, credits, etc.)
41
- # +promo_total+ The total value of all promotion adjustments
42
41
  # +total+ The so-called "order total." This is equivalent to +item_total+ plus +adjustment_total+.
43
42
  def update_totals
44
- order.payment_total = payments.completed.sum(:amount)
43
+ update_payment_total
45
44
  update_item_total
46
45
  update_shipment_total
47
46
  update_adjustment_total
@@ -50,12 +49,11 @@ module Spree
50
49
 
51
50
  # give each of the shipments a chance to update themselves
52
51
  def update_shipments
53
- shipments.each do |shipment|
54
- next unless shipment.persisted?
55
- shipment.update!(order)
56
- shipment.refresh_rates
57
- shipment.update_amounts
58
- end
52
+ shipments.each { |shipment| shipment.update!(order) }
53
+ end
54
+
55
+ def update_payment_total
56
+ order.payment_total = payments.completed.sum(:amount)
59
57
  end
60
58
 
61
59
  def update_shipment_total
@@ -75,10 +73,6 @@ module Spree
75
73
  order.included_tax_total = line_items.sum(:included_tax_total) + shipments.sum(:included_tax_total)
76
74
  order.additional_tax_total = line_items.sum(:additional_tax_total) + shipments.sum(:additional_tax_total)
77
75
 
78
- order.promo_total = line_items.sum(:promo_total) +
79
- shipments.sum(:promo_total) +
80
- adjustments.promotion.eligible.sum(:amount)
81
-
82
76
  update_order_total
83
77
  end
84
78
 
@@ -87,7 +81,7 @@ module Spree
87
81
  end
88
82
 
89
83
  def update_item_total
90
- order.item_total = line_items.map(&:amount).sum
84
+ order.item_total = line_items.sum('price * quantity')
91
85
  update_order_total
92
86
  end
93
87
 
@@ -102,7 +96,6 @@ module Spree
102
96
  additional_tax_total: order.additional_tax_total,
103
97
  payment_total: order.payment_total,
104
98
  shipment_total: order.shipment_total,
105
- promo_total: order.promo_total,
106
99
  total: order.total,
107
100
  updated_at: Time.now,
108
101
  )
@@ -152,23 +145,17 @@ module Spree
152
145
  # The +payment_state+ value helps with reporting, etc. since it provides a quick and easy way to locate Orders needing attention.
153
146
  def update_payment_state
154
147
  last_state = order.payment_state
155
- if payments.present? && payments.valid.size == 0
148
+ if payments.present? && payments.last.state == 'failed'
156
149
  order.payment_state = 'failed'
157
- elsif !payments.present? && order.state == 'canceled'
158
- order.payment_state = 'void'
159
- elsif order.state == 'canceled' && order.payment_total == 0 && payments.completed.size > 0
160
- order.payment_state = 'void'
161
150
  else
162
151
  order.payment_state = 'balance_due' if order.outstanding_balance > 0
163
152
  order.payment_state = 'credit_owed' if order.outstanding_balance < 0
164
153
  order.payment_state = 'paid' if !order.outstanding_balance?
165
154
  end
166
155
  order.state_changed('payment') if last_state != order.payment_state
167
- order.payment_state
168
156
  end
169
157
 
170
158
  private
171
-
172
159
  def round_money(n)
173
160
  (n * 100).round / 100.0
174
161
  end
@@ -1,5 +1,5 @@
1
1
  module Spree
2
- class Payment < ActiveRecord::Base
2
+ class Payment < Spree::Base
3
3
  include Spree::Payment::Processing
4
4
 
5
5
  IDENTIFIER_CHARS = (('A'..'Z').to_a + ('0'..'9').to_a - %w(0 1 I O)).freeze
@@ -8,7 +8,7 @@ module Spree
8
8
 
9
9
  belongs_to :order, class_name: 'Spree::Order', touch: true, inverse_of: :payments
10
10
  belongs_to :source, polymorphic: true
11
- belongs_to :payment_method, class_name: 'Spree::PaymentMethod', inverse_of: :payments
11
+ belongs_to :payment_method, class_name: 'Spree::PaymentMethod'
12
12
 
13
13
  has_many :offsets, -> { where("source_type = 'Spree::Payment' AND amount < 0 AND state = 'completed'") },
14
14
  class_name: "Spree::Payment", foreign_key: :source_id
@@ -26,13 +26,15 @@ module Spree
26
26
  # invalidate previously entered payments
27
27
  after_create :invalidate_old_payments
28
28
 
29
- attr_accessor :source_attributes
29
+ attr_accessor :source_attributes, :request_env
30
+
30
31
  after_initialize :build_source
31
32
 
32
33
  scope :from_credit_card, -> { where(source_type: 'Spree::CreditCard') }
33
34
  scope :with_state, ->(s) { where(state: s.to_s) }
34
35
  scope :completed, -> { with_state('completed') }
35
36
  scope :pending, -> { with_state('pending') }
37
+ scope :processing, -> { with_state('processing') }
36
38
  scope :failed, -> { with_state('failed') }
37
39
  scope :risky, -> { where("avs_response IN (?) OR (cvv_response_code IS NOT NULL and cvv_response_code != 'M') OR state = 'failed'", RISKY_AVS_CODES) }
38
40
  scope :valid, -> { where.not(state: %w(failed invalid)) }
@@ -50,6 +52,10 @@ module Spree
50
52
  # order state machine (see http://github.com/pluginaweek/state_machine/tree/master for details)
51
53
  state_machine initial: :checkout do
52
54
  # With card payments, happens before purchase or authorization happens
55
+ #
56
+ # Setting it after creating a profile and authorizing a full amount will
57
+ # prevent the payment from being authorized again once Order transitions
58
+ # to complete
53
59
  event :started_processing do
54
60
  transition from: [:checkout, :pending, :completed, :processing], to: :processing
55
61
  end
@@ -66,7 +72,7 @@ module Spree
66
72
  transition from: [:processing, :pending, :checkout], to: :completed
67
73
  end
68
74
  event :void do
69
- transition from: [:pending, :completed, :checkout], to: :void
75
+ transition from: [:pending, :processing, :completed, :checkout], to: :void
70
76
  end
71
77
  # when the card brand isnt supported
72
78
  event :invalidate do
@@ -166,8 +172,7 @@ module Spree
166
172
  end
167
173
 
168
174
  def create_payment_profile
169
- return unless source.respond_to?(:has_payment_profile?) && !source.has_payment_profile? &&
170
- state != 'invalid' && state != 'failed'
175
+ return unless source.respond_to?(:has_payment_profile?) && !source.has_payment_profile?
171
176
 
172
177
  payment_method.create_profile(self)
173
178
  rescue ActiveMerchant::ConnectionError => e
@@ -175,16 +180,25 @@ module Spree
175
180
  end
176
181
 
177
182
  def invalidate_old_payments
178
- if state != 'invalid' and state != 'failed'
179
- order.payments.with_state('checkout').where("id != ?", self.id).each do |payment|
180
- payment.invalidate!
181
- end
183
+ order.payments.with_state('checkout').where("id != ?", self.id).each do |payment|
184
+ payment.invalidate!
182
185
  end
183
186
  end
184
187
 
185
188
  def update_order
186
- order.payments.reload
187
- order.update!
189
+ if self.completed?
190
+ order.updater.update_payment_total
191
+ end
192
+
193
+ if order.completed?
194
+ order.updater.update_payment_state
195
+ order.updater.update_shipments
196
+ order.updater.update_shipment_state
197
+ end
198
+
199
+ if self.completed? || order.completed?
200
+ order.persist_totals
201
+ end
188
202
  end
189
203
 
190
204
  # Necessary because some payment gateways will refuse payments with
@@ -1,11 +1,11 @@
1
1
  module Spree
2
- class Payment < ActiveRecord::Base
2
+ class Payment < Spree::Base
3
3
  module Processing
4
4
  def process!
5
5
  if payment_method && payment_method.source_required?
6
6
  if source
7
7
  if !processing?
8
- if payment_method.supports?(source) || token_based?
8
+ if payment_method.supports?(source)
9
9
  if payment_method.auto_capture?
10
10
  purchase!
11
11
  else
@@ -81,17 +81,11 @@ module Spree
81
81
  end
82
82
 
83
83
  def credit!(credit_amount=nil)
84
- raise Core::GatewayError.new(Spree.t(:payment_processing_failed)) if processing?
85
-
86
- # Calculate credit amount before marking as processing since it messes up the order totals not having payment in completed state.
87
- credit_amount ||= credit_allowed >= order.outstanding_balance.abs ? order.outstanding_balance.abs : credit_allowed.abs
88
- credit_amount = credit_amount.to_f
89
-
90
- # Mark as processing to avoid race condition that could send multiple credits to the gateway.
91
- started_processing!
92
84
  protect_from_connection_error do
93
85
  check_environment
94
86
 
87
+ credit_amount ||= credit_allowed >= order.outstanding_balance.abs ? order.outstanding_balance.abs : credit_allowed.abs
88
+ credit_amount = credit_amount.to_f
95
89
  credit_cents = Spree::Money.new(credit_amount, currency: currency).money.cents
96
90
 
97
91
  if payment_method.payment_profiles_supported?
@@ -101,8 +95,6 @@ module Spree
101
95
  end
102
96
 
103
97
  record_response(response)
104
- # Always set back to 'completed' as initial payment record was successful.
105
- self.update_column(:state, 'completed')
106
98
 
107
99
  if response.success?
108
100
  self.class.create!(
@@ -129,6 +121,7 @@ module Spree
129
121
 
130
122
  def partial_credit(amount)
131
123
  return if amount > credit_allowed
124
+ started_processing!
132
125
  credit!(amount)
133
126
  end
134
127
 
@@ -226,10 +219,6 @@ module Spree
226
219
  def gateway_order_id
227
220
  "#{order.number}-#{self.identifier}"
228
221
  end
229
-
230
- def token_based?
231
- source.gateway_customer_profile_id.present? || source.gateway_payment_profile_id.present?
232
- end
233
222
  end
234
223
  end
235
224
  end
@@ -1,5 +1,5 @@
1
1
  module Spree
2
- class PaymentCaptureEvent < ActiveRecord::Base
2
+ class PaymentCaptureEvent < Spree::Base
3
3
  belongs_to :payment, class_name: 'Spree::Payment'
4
4
 
5
5
  def display_amount
@@ -1,5 +1,5 @@
1
1
  module Spree
2
- class PaymentMethod < ActiveRecord::Base
2
+ class PaymentMethod < Spree::Base
3
3
  acts_as_paranoid
4
4
  DISPLAY = [:both, :front_end, :back_end]
5
5
  default_scope -> { where(deleted_at: nil) }
@@ -8,7 +8,7 @@ module Spree
8
8
 
9
9
  validates :name, presence: true
10
10
 
11
- has_many :payments, class_name: "Spree::Payment", inverse_of: :payment_method
11
+ has_many :payments, class_name: "Spree::Payment"
12
12
  has_many :credit_cards, class_name: "Spree::CreditCard"
13
13
 
14
14
  def self.providers
@@ -18,8 +18,6 @@ module Spree
18
18
  ActiveMerchant::Billing::Response.new(true, "", {}, {})
19
19
  end
20
20
 
21
- def cancel(response); end
22
-
23
21
  def void(*args)
24
22
  ActiveMerchant::Billing::Response.new(true, "", {}, {})
25
23
  end
@@ -1,35 +1,5 @@
1
- class Spree::Preference < ActiveRecord::Base
1
+ class Spree::Preference < Spree::Base
2
2
  serialize :value
3
3
 
4
4
  validates :key, presence: true
5
- validates :value_type, presence: true
6
-
7
- scope :valid, -> { where(Spree::Preference.arel_table[:key].not_eq(nil)).where(Spree::Preference.arel_table[:value_type].not_eq(nil)) }
8
-
9
- # The type conversions here should match
10
- # the ones in spree::preferences::preferrable#convert_preference_value
11
- def value
12
- if self[:value_type].present?
13
- case self[:value_type].to_sym
14
- when :string, :text
15
- self[:value].to_s
16
- when :password
17
- self[:value].to_s
18
- when :decimal
19
- BigDecimal.new(self[:value].to_s).round(2, BigDecimal::ROUND_HALF_UP)
20
- when :integer
21
- self[:value].to_i
22
- when :boolean
23
- (self[:value].to_s =~ /^[t|1]/i) != nil
24
- else
25
- self[:value].is_a?(String) ? YAML.load(self[:value]) : self[:value]
26
- end
27
- else
28
- self[:value]
29
- end
30
- end
31
-
32
- def raw_value
33
- self[:value]
34
- end
35
5
  end
@@ -28,12 +28,8 @@ module Spree::Preferences
28
28
  yield(self) if block_given?
29
29
  end
30
30
 
31
- def preference_cache_key(name)
32
- [rails_cache_id, self.class.name, name].compact.join('::').underscore
33
- end
34
-
35
- def rails_cache_id
36
- ENV['RAILS_CACHE_ID']
31
+ def preferences
32
+ ScopedStore.new(self.class.name.underscore)
37
33
  end
38
34
 
39
35
  def reset
@@ -1,40 +1,47 @@
1
- # The preference_cache_key is used to determine if the preference
2
- # can be set. The default behavior is to return nil if there is no
3
- # id value. On ActiveRecords, new objects will have their preferences
4
- # saved to a pending hash until it is persisted.
1
+ # Preferable allows defining preference accessor methods.
5
2
  #
6
- # class_attributes are inheritied unless you reassign them in
7
- # the subclass, so when you inherit a Preferable class, the
8
- # inherited hook will assign a new hash for the subclass definitions
9
- # and copy all the definitions allowing the subclass to add
10
- # additional defintions without affecting the base
3
+ # A class including Preferable must implement #preferences which should return
4
+ # an object responding to .fetch(key), []=(key, val), and .delete(key).
5
+ #
6
+ # The generated writer method performs typecasting before assignment into the
7
+ # preferences object.
8
+ #
9
+ # Examples:
10
+ #
11
+ # # Spree::Base includes Preferable and defines preferences as a serialized
12
+ # # column.
13
+ # class Settings < Spree::Base
14
+ # preference :color, :string, default: 'red'
15
+ # preference :temperature, :integer, default: 21
16
+ # end
17
+ #
18
+ # s = Settings.new
19
+ # s.preferred_color # => 'red'
20
+ # s.preferred_temperature # => 21
21
+ #
22
+ # s.preferred_color = 'blue'
23
+ # s.preferred_color # => 'blue'
24
+ #
25
+ # # Typecasting is performed on assignment
26
+ # s.preferred_temperature = '24'
27
+ # s.preferred_color # => 24
28
+ #
29
+ # # Modifications have been made to the .preferences hash
30
+ # s.preferences #=> {color: 'blue', temperature: 24}
31
+ #
32
+ # # Save the changes. All handled by activerecord
33
+ # s.save!
11
34
  module Spree::Preferences::Preferable
35
+ extend ActiveSupport::Concern
12
36
 
13
- def self.included(base)
14
- base.class_eval do
15
- extend Spree::Preferences::PreferableClassMethods
16
-
17
- if respond_to?(:after_create)
18
- after_create do |obj|
19
- obj.save_pending_preferences
20
- end
21
- end
22
-
23
- if respond_to?(:after_destroy)
24
- after_destroy do |obj|
25
- obj.clear_preferences
26
- end
27
- end
28
-
29
- end
37
+ included do
38
+ extend Spree::Preferences::PreferableClassMethods
30
39
  end
31
40
 
32
41
  def get_preference(name)
33
42
  has_preference! name
34
43
  send self.class.preference_getter_method(name)
35
44
  end
36
- alias :preferred :get_preference
37
- alias :prefers? :get_preference
38
45
 
39
46
  def set_preference(name, value)
40
47
  has_preference! name
@@ -51,11 +58,6 @@ module Spree::Preferences::Preferable
51
58
  send self.class.preference_default_getter_method(name)
52
59
  end
53
60
 
54
- def preference_description(name)
55
- has_preference! name
56
- send self.class.preference_description_getter_method(name)
57
- end
58
-
59
61
  def has_preference!(name)
60
62
  raise NoMethodError.new "#{name} preference not defined" unless has_preference? name
61
63
  end
@@ -64,50 +66,26 @@ module Spree::Preferences::Preferable
64
66
  respond_to? self.class.preference_getter_method(name)
65
67
  end
66
68
 
67
- def preferences
68
- prefs = {}
69
- methods.grep(/^prefers_.*\?$/).each do |pref_method|
70
- prefs[pref_method.to_s.gsub(/prefers_|\?/, '').to_sym] = send(pref_method)
69
+ def defined_preferences
70
+ methods.grep(/\Apreferred_.*=\Z/).map do |pref_method|
71
+ pref_method.to_s.gsub(/\Apreferred_|=\Z/, '').to_sym
71
72
  end
72
- prefs
73
73
  end
74
74
 
75
- def prefers?(name)
76
- get_preference(name)
77
- end
78
-
79
- def preference_cache_key(name)
80
- return unless id
81
- [rails_cache_id, self.class.name, name, id].compact.join('::').underscore
82
- end
83
-
84
- def rails_cache_id
85
- ENV['RAILS_CACHE_ID']
86
- end
87
-
88
- def save_pending_preferences
89
- return unless @pending_preferences
90
- @pending_preferences.each do |name, value|
91
- set_preference(name, value)
92
- end
75
+ def default_preferences
76
+ Hash[
77
+ defined_preferences.map do |preference|
78
+ [preference, preference_default(preference)]
79
+ end
80
+ ]
93
81
  end
94
82
 
95
83
  def clear_preferences
96
- preferences.keys.each {|pref| preference_store.delete preference_cache_key(pref)}
84
+ preferences.keys.each {|pref| preferences.delete pref}
97
85
  end
98
86
 
99
87
  private
100
88
 
101
- def add_pending_preference(name, value)
102
- @pending_preferences ||= {}
103
- @pending_preferences[name] = value
104
- end
105
-
106
- def get_pending_preference(name)
107
- return unless @pending_preferences
108
- @pending_preferences[name]
109
- end
110
-
111
89
  def convert_preference_value(value, type)
112
90
  case type
113
91
  when :string, :text
@@ -115,7 +93,7 @@ module Spree::Preferences::Preferable
115
93
  when :password
116
94
  value.to_s
117
95
  when :decimal
118
- BigDecimal.new(value.to_s).round(2, BigDecimal::ROUND_HALF_UP)
96
+ BigDecimal.new(value.to_s)
119
97
  when :integer
120
98
  value.to_i
121
99
  when :boolean
@@ -132,10 +110,4 @@ module Spree::Preferences::Preferable
132
110
  value
133
111
  end
134
112
  end
135
-
136
- def preference_store
137
- Spree::Preferences::Store.instance
138
- end
139
-
140
113
  end
141
-