spree_core 2.2.14 → 2.3.0

Sign up to get free protection for your applications and to get access to all the features.
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
-