spree_core 2.0.4 → 2.0.5

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 (51) hide show
  1. checksums.yaml +4 -4
  2. data/app/mailers/spree/test_mailer.rb +2 -1
  3. data/app/models/spree/adjustment.rb +18 -7
  4. data/app/models/spree/alert.rb +1 -1
  5. data/app/models/spree/credit_card.rb +2 -2
  6. data/app/models/spree/inventory_unit.rb +5 -0
  7. data/app/models/spree/line_item.rb +18 -4
  8. data/app/models/spree/order/checkout.rb +10 -14
  9. data/app/models/spree/order.rb +39 -27
  10. data/app/models/spree/order_contents.rb +2 -2
  11. data/app/models/spree/order_inventory.rb +2 -9
  12. data/app/models/spree/order_updater.rb +18 -7
  13. data/app/models/spree/payment/processing.rb +102 -102
  14. data/app/models/spree/payment.rb +10 -9
  15. data/app/models/spree/preferences/store.rb +1 -1
  16. data/app/models/spree/product.rb +11 -2
  17. data/app/models/spree/promotion/rules/user.rb +7 -2
  18. data/app/models/spree/property.rb +1 -1
  19. data/app/models/spree/shipment.rb +12 -7
  20. data/app/models/spree/shipping_method.rb +1 -1
  21. data/app/models/spree/stock/availability_validator.rb +9 -1
  22. data/app/models/spree/stock/coordinator.rb +1 -3
  23. data/app/models/spree/stock/estimator.rb +1 -1
  24. data/app/models/spree/stock/packer.rb +13 -5
  25. data/app/models/spree/stock_item.rb +10 -1
  26. data/app/models/spree/stock_location.rb +1 -1
  27. data/app/models/spree/tax_rate.rb +3 -1
  28. data/app/models/spree/zone.rb +37 -1
  29. data/app/views/spree/test_mailer/test_email.text.erb +4 -0
  30. data/config/locales/en.yml +24 -1
  31. data/db/default/spree/roles.rb +2 -2
  32. data/db/migrate/20130213191427_create_default_stock.rb +2 -1
  33. data/db/migrate/20130802022321_migrate_tax_categories_to_line_items.rb +1 -1
  34. data/db/migrate/20130806022521_drop_spree_mail_methods.rb +12 -0
  35. data/db/migrate/20130806145853_set_default_stock_location_on_shipments.rb +8 -0
  36. data/db/migrate/20130809164245_add_admin_name_column_to_spree_shipping_methods.rb +5 -0
  37. data/db/migrate/20130809164330_add_admin_name_column_to_spree_stock_locations.rb +5 -0
  38. data/db/migrate/20130813140619_expand_order_number_size.rb +9 -0
  39. data/db/migrate/20130826062534_add_depth_to_spree_taxons.rb +16 -0
  40. data/db/migrate/20130915032339_add_deleted_at_to_spree_stock_items.rb +5 -0
  41. data/lib/generators/spree/dummy/templates/rails/database.yml +0 -3
  42. data/lib/spree/core/engine.rb +1 -5
  43. data/lib/spree/core/permalinks.rb +4 -2
  44. data/lib/spree/core/version.rb +1 -1
  45. data/lib/spree/promo/coupon_applicator.rb +2 -2
  46. data/lib/spree/testing_support/capybara_ext.rb +2 -2
  47. data/lib/spree/testing_support/factories/order_factory.rb +8 -4
  48. metadata +17 -12
  49. data/app/models/spree/new_adjustment.rb +0 -4
  50. data/app/models/spree/shipping_adjustment.rb +0 -4
  51. data/db/migrate/20130805043440_create_spree_new_adjustments.rb +0 -8
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b435838b2a77628006e2e2885f5dbe2039958630
4
- data.tar.gz: 1df2bcec2ac50c9d4716017752eb8c56ab2f9960
3
+ metadata.gz: 4eb6afc84186dd0b46d37daebea561e582412dfb
4
+ data.tar.gz: 96ad34a945d823c7f0ce6d17797c183eee5f4261
5
5
  SHA512:
6
- metadata.gz: 1154f9c96163b14b0f85379e73718b6e5a95a6b60688399df8b724e109880d1e21deb4dbd77d44ae8dd29fe1cd98bd563d74c6ce191ac89eff57424dba437602
7
- data.tar.gz: 5d008b1beae9dc20bf209bcc59063debee39ae36c6426569f970af0aad14b64287b61f9bed6454190e694ce96cb9b145be04b15066bc8abc80da9fb3c91c21fe
6
+ metadata.gz: 2a990089d87e7ed851394892fe747d8146fdd7992a1f1d70f1cb7447a6471c937dd1faf5380cbec891844f048049b5f8b65312bae912ae69cf46690f235e2dab
7
+ data.tar.gz: c13e7f2071ddac220493da65f4407b25e00cf0704a7d205637c67513487f7646e60ab209d43ed3a2365d81d473420c6fb56760331a7598dc2e66c7966837e9e6
@@ -1,8 +1,9 @@
1
1
  module Spree
2
2
  class TestMailer < BaseMailer
3
3
  def test_email(user)
4
+ recipient = user.respond_to?(:id) ? user : Spree.user_class.find(user)
4
5
  subject = "#{Spree::Config[:site_name]} #{Spree.t('test_mailer.test_email.subject')}"
5
- mail(to: user.email, from: from_address, subject: subject)
6
+ mail(to: recipient.email, from: from_address, subject: subject)
6
7
  end
7
8
  end
8
9
  end
@@ -60,10 +60,14 @@ module Spree
60
60
  scope :promotion, -> { where(originator_type: 'Spree::PromotionAction') }
61
61
  scope :return_authorization, -> { where(source_type: "Spree::ReturnAuthorization") }
62
62
 
63
+ def promotion?
64
+ originator_type == 'Spree::PromotionAction'
65
+ end
66
+
63
67
  # Update the boolean _eligible_ attribute which determines which adjustments
64
68
  # count towards the order's adjustment_total.
65
69
  def set_eligibility
66
- result = self.mandatory || (self.amount != 0 && self.eligible_for_originator?)
70
+ result = mandatory || ((amount != 0 || promotion?) && eligible_for_originator?)
67
71
  update_attribute_without_callbacks(:eligible, result)
68
72
  end
69
73
 
@@ -74,20 +78,27 @@ module Spree
74
78
  !originator.respond_to?(:eligible?) || originator.eligible?(source)
75
79
  end
76
80
 
77
- # Update both the eligibility and amount of the adjustment. Adjustments
81
+ # Update both the eligibility and amount of the adjustment. Adjustments
78
82
  # delegate updating of amount to their Originator when present, but only if
79
83
  # +locked+ is false. Adjustments that are +locked+ will never change their amount.
80
84
  #
81
- # order#update_adjustments passes self as the src, this is so calculations can
82
- # be performed on the # current values. If we used source it would load the old
83
- # record from db for the association
84
- def update!
85
+ # Adjustments delegate updating of amount to their Originator when present,
86
+ # but only if when they're in "open" state, closed or finalized adjustments
87
+ # are not recalculated.
88
+ #
89
+ # It receives +calculable+ as the updated source here so calculations can be
90
+ # performed on the current values of that source. If we used +source+ it
91
+ # could load the old record from db for the association. e.g. when updating
92
+ # more than on line items at once via accepted_nested_attributes the order
93
+ # object on the association would be in a old state and therefore the
94
+ # adjustment calculations would not performed on proper values
95
+ def update!(calculable = nil)
85
96
  return if immutable?
86
97
  # Fix for #3381
87
98
  # If we attempt to call 'source' before the reload, then source is currently
88
99
  # the order object. After calling a reload, the source is the Shipment.
89
100
  reload
90
- originator.update_adjustment(self, source) if originator.present?
101
+ originator.update_adjustment(self, calculable || source) if originator.present?
91
102
  set_eligibility
92
103
  end
93
104
 
@@ -11,7 +11,7 @@ module Spree
11
11
  rails_version: Rails.version
12
12
  }
13
13
 
14
- HTTParty.get('http://alerts.spreecommerce.com/alerts.json', body: params).parsed_response
14
+ HTTParty.get('http://alerts.spreecommerce.com/alerts.json', query: params).parsed_response
15
15
  end
16
16
  end
17
17
  end
@@ -105,9 +105,9 @@ module Spree
105
105
  private
106
106
 
107
107
  def expiry_not_in_the_past
108
- if year && month
108
+ if year.present? && month.present?
109
109
  time = "#{year}-#{month}-1".to_time
110
- if time < Time.zone.now.beginning_of_month
110
+ if time < Time.zone.now.to_time.beginning_of_month
111
111
  errors.add(:base, :card_expired)
112
112
  end
113
113
  end
@@ -53,6 +53,11 @@ module Spree
53
53
  variant_id: variant_id).first
54
54
  end
55
55
 
56
+ # Remove variant default_scope `deleted_at: nil`
57
+ def variant
58
+ Spree::Variant.unscoped { super }
59
+ end
60
+
56
61
  private
57
62
 
58
63
  def allow_ship?
@@ -85,15 +85,29 @@ module Spree
85
85
  @preferred_shipment = shipment
86
86
  end
87
87
 
88
+ # Remove product default_scope `deleted_at: nil`
89
+ def product
90
+ variant.product
91
+ end
92
+
93
+ # Remove variant default_scope `deleted_at: nil`
94
+ def variant
95
+ Spree::Variant.unscoped { super }
96
+ end
97
+
88
98
  private
89
99
  def update_inventory
90
- Spree::OrderInventory.new(self.order).verify(self, target_shipment)
100
+ if changed?
101
+ Spree::OrderInventory.new(self.order).verify(self, target_shipment)
102
+ end
91
103
  end
92
104
 
93
105
  def update_order
94
- # update the order totals, etc.
95
- order.create_tax_charge!
96
- order.update!
106
+ if changed? || destroyed?
107
+ # update the order totals, etc.
108
+ order.create_tax_charge!
109
+ order.update!
110
+ end
97
111
  end
98
112
  end
99
113
  end
@@ -63,10 +63,12 @@ module Spree
63
63
  transition :to => :awaiting_return
64
64
  end
65
65
 
66
-
67
- before_transition :to => :complete do |order|
68
- order.process_payments! if order.payment_required?
66
+ if states[:payment]
67
+ before_transition :to => :complete do |order|
68
+ order.process_payments! if order.payment_required?
69
+ end
69
70
  end
71
+
70
72
  before_transition :from => :cart, :do => :ensure_line_items_present
71
73
 
72
74
  before_transition :to => :delivery, :do => :create_proposed_shipments
@@ -125,12 +127,11 @@ module Spree
125
127
 
126
128
  def self.remove_transition(options={})
127
129
  self.removed_transitions << options
128
- if transition = find_transition(options)
129
- self.next_event_transitions.delete(transition)
130
- end
130
+ self.next_event_transitions.delete(find_transition(options))
131
131
  end
132
132
 
133
133
  def self.find_transition(options={})
134
+ return nil if options.nil? || !options.include?(:from) || !options.include?(:to)
134
135
  self.next_event_transitions.detect do |transition|
135
136
  transition[options[:from].to_sym] == options[:to].to_sym
136
137
  end
@@ -149,15 +150,10 @@ module Spree
149
150
  end
150
151
 
151
152
  def checkout_steps
152
- checkout_steps = []
153
- # TODO: replace this with each_with_object once Ruby 1.9 is standard
154
- self.class.checkout_steps.each do |step, options|
155
- if options[:if]
156
- next unless options[:if].call(self)
157
- end
153
+ steps = self.class.checkout_steps.each_with_object([]) { |(step, options), checkout_steps|
154
+ next if options.include?(:if) && !options[:if].call(self)
158
155
  checkout_steps << step
159
- end
160
- steps = checkout_steps.map(&:to_s)
156
+ }.map(&:to_s)
161
157
  # Ensure there is always a complete step
162
158
  steps << "complete" unless steps.include?("complete")
163
159
  steps
@@ -47,9 +47,12 @@ module Spree
47
47
  belongs_to :ship_address, foreign_key: :ship_address_id, class_name: 'Spree::Address'
48
48
  alias_attribute :shipping_address, :ship_address
49
49
 
50
+ has_many :adjustments, as: :adjustable, dependent: :destroy, order: 'created_at ASC'
51
+ has_many :line_item_adjustments, through: :line_items, source: :adjustments
52
+ has_many :line_items, dependent: :destroy, order: 'created_at ASC'
53
+ has_many :payments, dependent: :destroy
54
+ has_many :return_authorizations, dependent: :destroy
50
55
  has_many :state_changes, as: :stateful
51
- has_many :line_items, dependent: :destroy, order: "#{Spree::LineItem.table_name}.created_at ASC"
52
- has_many :payments, dependent: :destroy, :class_name => "Spree::Payment"
53
56
 
54
57
  has_many :shipments, dependent: :destroy, :class_name => "Shipment" do
55
58
  def states
@@ -57,13 +60,6 @@ module Spree
57
60
  end
58
61
  end
59
62
 
60
- has_many :return_authorizations, dependent: :destroy
61
- has_many :adjustments,
62
- as: :adjustable,
63
- dependent: :destroy,
64
- order: "#{Spree::Adjustment.table_name}.created_at ASC",
65
- inverse_of: :source
66
-
67
63
  accepts_nested_attributes_for :line_items
68
64
  accepts_nested_attributes_for :bill_address
69
65
  accepts_nested_attributes_for :ship_address
@@ -202,26 +198,26 @@ module Spree
202
198
  return tax_zone != Zone.default_tax
203
199
  end
204
200
 
205
- # Array of adjustments that are inclusive in the variant price. Useful for when
206
- # prices include tax (ex. VAT) and you need to record the tax amount separately.
207
201
  def price_adjustments
208
- adjustments = []
209
-
210
- line_items.each { |line_item| adjustments.concat line_item.adjustments }
211
-
212
- adjustments
202
+ ActiveSupport::Deprecation.warn("Order#price_adjustments will be deprecated in Spree 2.1, please use Order#line_item_adjustments instead.")
203
+ self.line_item_adjustments
213
204
  end
214
205
 
215
- # Array of totals grouped by Adjustment#label. Useful for displaying price
206
+ # Array of totals grouped by Adjustment#label. Useful for displaying line item
216
207
  # adjustments on an invoice. For example, you can display tax breakout for
217
208
  # cases where tax is included in price.
218
- def price_adjustment_totals
219
- Hash[price_adjustments.group_by(&:label).map do |label, adjustments|
209
+ def line_item_adjustment_totals
210
+ Hash[self.line_item_adjustments.eligible.group_by(&:label).map do |label, adjustments|
220
211
  total = adjustments.sum(&:amount)
221
212
  [label, Spree::Money.new(total, { currency: currency })]
222
213
  end]
223
214
  end
224
215
 
216
+ def price_adjustment_totals
217
+ ActiveSupport::Deprecation.warn("Order#price_adjustment_totals will be deprecated in Spree 2.1, please use Order#line_item_adjustment_totals instead.")
218
+ self.line_item_adjustment_totals
219
+ end
220
+
225
221
  def updater
226
222
  @updater ||= OrderUpdater.new(self)
227
223
  end
@@ -279,10 +275,11 @@ module Spree
279
275
  def associate_user!(user)
280
276
  self.user = user
281
277
  self.email = user.email
278
+ self.created_by = user if self.created_by.blank?
282
279
 
283
280
  if persisted?
284
281
  # immediately persist the changes we just made, but don't use save since we might have an invalid address associated
285
- self.class.unscoped.where(id: id).update_all(email: user.email, user_id: user.id)
282
+ self.class.unscoped.where(id: id).update_all(email: user.email, user_id: user.id, created_by_id: self.created_by_id)
286
283
  end
287
284
  end
288
285
 
@@ -368,7 +365,7 @@ module Spree
368
365
  touch :completed_at
369
366
 
370
367
  # lock all adjustments (coupon promotions, etc.)
371
- adjustments.each { |adjustment| adjustment.update_column('state', "closed") }
368
+ adjustments.update_all state: 'closed'
372
369
 
373
370
  # update payment and shipment(s) states, and save
374
371
  updater.update_payment_state
@@ -462,7 +459,7 @@ module Spree
462
459
  end
463
460
 
464
461
  def insufficient_stock_lines
465
- line_items.select &:insufficient_stock?
462
+ @insufficient_stock_lines ||= line_items.select(&:insufficient_stock?)
466
463
  end
467
464
 
468
465
  def merge!(order)
@@ -487,11 +484,9 @@ module Spree
487
484
  adjustments.destroy_all
488
485
  end
489
486
 
490
- # destroy any previous adjustments.
491
- # Adjustments will be recalculated during order update.
492
487
  def clear_adjustments!
493
- adjustments.tax.each(&:destroy)
494
- price_adjustments.each(&:destroy)
488
+ self.adjustments.destroy_all
489
+ self.line_item_adjustments.destroy_all
495
490
  end
496
491
 
497
492
  def has_step?(step)
@@ -522,7 +517,7 @@ module Spree
522
517
  # Receives an adjustment +originator+ (here a PromotionAction object) and tells
523
518
  # if the order has adjustments from that already
524
519
  def promotion_credit_exists?(originator)
525
- !! adjustments.promotion.reload.detect { |credit| credit.originator.id == originator.id }
520
+ !! adjustments.includes(:originator).promotion.reload.detect { |credit| credit.originator.id == originator.id }
526
521
  end
527
522
 
528
523
  def promo_total
@@ -534,6 +529,7 @@ module Spree
534
529
  end
535
530
 
536
531
  def create_proposed_shipments
532
+ adjustments.shipping.delete_all
537
533
  shipments.destroy_all
538
534
 
539
535
  packages = Spree::Stock::Coordinator.new(self).packages
@@ -544,6 +540,22 @@ module Spree
544
540
  shipments
545
541
  end
546
542
 
543
+ # Clean shipments and make order back to address state
544
+ #
545
+ # At some point the might need to force the order to transition from address
546
+ # to delivery again so that proper updated shipments are created.
547
+ # e.g. customer goes back from payment step and changes order items
548
+ def ensure_updated_shipments
549
+ if shipments.any?
550
+ self.shipments.destroy_all
551
+ self.update_column(:state, "address")
552
+ end
553
+ end
554
+
555
+ def refresh_shipment_rates
556
+ shipments.map &:refresh_rates
557
+ end
558
+
547
559
  private
548
560
 
549
561
  def link_by_email
@@ -8,14 +8,14 @@ module Spree
8
8
 
9
9
  # Get current line item for variant if exists
10
10
  # Add variant qty to line_item
11
- def add(variant, quantity, currency=nil, shipment=nil)
11
+ def add(variant, quantity=1, currency=nil, shipment=nil)
12
12
  line_item = order.find_line_item_by_variant(variant)
13
13
  add_to_line_item(line_item, variant, quantity, currency, shipment)
14
14
  end
15
15
 
16
16
  # Get current line item for variant
17
17
  # Remove variant qty from line_item
18
- def remove(variant, quantity, shipment=nil)
18
+ def remove(variant, quantity=1, shipment=nil)
19
19
  line_item = order.find_line_item_by_variant(variant)
20
20
 
21
21
  unless line_item
@@ -67,15 +67,8 @@ module Spree
67
67
  def add_to_shipment(shipment, variant, quantity)
68
68
  on_hand, back_order = shipment.stock_location.fill_status(variant, quantity)
69
69
 
70
- on_hand.times do
71
- shipment.inventory_units.create({variant_id: variant.id,
72
- state: 'on_hand'}, without_protection: true)
73
- end
74
-
75
- back_order.times do
76
- shipment.inventory_units.create({variant_id: variant.id,
77
- state: 'backordered'}, without_protection: true)
78
- end
70
+ on_hand.times { shipment.set_up_inventory('on_hand', variant, order) }
71
+ back_order.times { shipment.set_up_inventory('backordered', variant, order) }
79
72
 
80
73
  # adding to this shipment, and removing from stock_location
81
74
  if order.completed?
@@ -16,12 +16,17 @@ module Spree
16
16
  # associations try to save and then in turn try to call +update!+ again.)
17
17
  def update
18
18
  update_totals
19
- update_payment_state
20
19
 
21
- # give each of the shipments a chance to update themselves
22
- shipments.each { |shipment| shipment.update!(order) }#(&:update!)
23
- update_shipment_state
24
- update_adjustments
20
+ if order.completed?
21
+ update_payment_state
22
+
23
+ # give each of the shipments a chance to update themselves
24
+ shipments.each { |shipment| shipment.update!(order) }
25
+ update_shipment_state
26
+ end
27
+
28
+ update_promotion_adjustments
29
+ update_shipping_adjustments
25
30
  # update totals a second time in case updated adjustments have an effect on the total
26
31
  update_totals
27
32
 
@@ -120,11 +125,17 @@ module Spree
120
125
  #
121
126
  # Adjustments will check if they are still eligible. Ineligible adjustments
122
127
  # are preserved but not counted towards adjustment_total.
123
- def update_adjustments
124
- order.adjustments.reload.each { |adjustment| adjustment.update! }
128
+ def update_promotion_adjustments
129
+ order.adjustments.reload.promotion.each { |adjustment| adjustment.update!(order) }
125
130
  choose_best_promotion_adjustment
126
131
  end
127
132
 
133
+ # Shipping adjustments don't receive order on update! because they calculated
134
+ # over a shipping / package object rather than an order object
135
+ def update_shipping_adjustments
136
+ order.adjustments.reload.shipping.each { |adjustment| adjustment.update! }
137
+ end
138
+
128
139
  private
129
140
 
130
141
  # Picks one (and only one) promotion to be eligible for this order
@@ -76,133 +76,133 @@ module Spree
76
76
  end
77
77
  end
78
78
  end
79
- end
80
79
 
81
- def credit!(credit_amount=nil)
82
- protect_from_connection_error do
83
- check_environment
80
+ def credit!(credit_amount=nil)
81
+ protect_from_connection_error do
82
+ check_environment
84
83
 
85
- credit_amount ||= credit_allowed >= order.outstanding_balance.abs ? order.outstanding_balance.abs : credit_allowed.abs
86
- credit_amount = credit_amount.to_f
84
+ credit_amount ||= credit_allowed >= order.outstanding_balance.abs ? order.outstanding_balance.abs : credit_allowed.abs
85
+ credit_amount = credit_amount.to_f
87
86
 
88
- if payment_method.payment_profiles_supported?
89
- response = payment_method.credit((credit_amount * 100).round, source, response_code, gateway_options)
90
- else
91
- response = payment_method.credit((credit_amount * 100).round, response_code, gateway_options)
92
- end
87
+ if payment_method.payment_profiles_supported?
88
+ response = payment_method.credit((credit_amount * 100).round, source, response_code, gateway_options)
89
+ else
90
+ response = payment_method.credit((credit_amount * 100).round, response_code, gateway_options)
91
+ end
93
92
 
94
- record_response(response)
93
+ record_response(response)
95
94
 
96
- if response.success?
97
- self.class.create({ :order => order,
98
- :source => self,
99
- :payment_method => payment_method,
100
- :amount => credit_amount.abs * -1,
101
- :response_code => response.authorization,
102
- :state => 'completed' }, :without_protection => true)
103
- else
104
- gateway_error(response)
95
+ if response.success?
96
+ self.class.create({ :order => order,
97
+ :source => self,
98
+ :payment_method => payment_method,
99
+ :amount => credit_amount.abs * -1,
100
+ :response_code => response.authorization,
101
+ :state => 'completed' }, :without_protection => true)
102
+ else
103
+ gateway_error(response)
104
+ end
105
105
  end
106
106
  end
107
- end
108
107
 
109
- def partial_credit(amount)
110
- return if amount > credit_allowed
111
- started_processing!
112
- credit!(amount)
113
- end
108
+ def partial_credit(amount)
109
+ return if amount > credit_allowed
110
+ started_processing!
111
+ credit!(amount)
112
+ end
114
113
 
115
- def gateway_options
116
- options = { :email => order.email,
117
- :customer => order.email,
118
- :ip => order.last_ip_address,
119
- # Need to pass in a unique identifier here to make some
120
- # payment gateways happy.
121
- #
122
- # For more information, please see Spree::Payment#set_unique_identifier
123
- :order_id => gateway_order_id }
124
-
125
- options.merge!({ :shipping => order.ship_total * 100,
126
- :tax => order.tax_total * 100,
127
- :subtotal => order.item_total * 100,
128
- :discount => order.promo_total * 100,
129
- :currency => currency })
130
-
131
- options.merge!({ :billing_address => order.bill_address.try(:active_merchant_hash),
132
- :shipping_address => order.ship_address.try(:active_merchant_hash) })
133
-
134
- options
135
- end
114
+ def gateway_options
115
+ options = { :email => order.email,
116
+ :customer => order.email,
117
+ :ip => order.last_ip_address,
118
+ # Need to pass in a unique identifier here to make some
119
+ # payment gateways happy.
120
+ #
121
+ # For more information, please see Spree::Payment#set_unique_identifier
122
+ :order_id => gateway_order_id }
123
+
124
+ options.merge!({ :shipping => order.ship_total * 100,
125
+ :tax => order.tax_total * 100,
126
+ :subtotal => order.item_total * 100,
127
+ :discount => order.promo_total * 100,
128
+ :currency => currency })
129
+
130
+ options.merge!({ :billing_address => order.bill_address.try(:active_merchant_hash),
131
+ :shipping_address => order.ship_address.try(:active_merchant_hash) })
132
+
133
+ options
134
+ end
136
135
 
137
- private
136
+ private
138
137
 
139
- def gateway_action(source, action, success_state)
140
- protect_from_connection_error do
141
- check_environment
138
+ def gateway_action(source, action, success_state)
139
+ protect_from_connection_error do
140
+ check_environment
142
141
 
143
- response = payment_method.send(action, (amount * 100).round,
144
- source,
145
- gateway_options)
146
- handle_response(response, success_state, :failure)
142
+ response = payment_method.send(action, (amount * 100).round,
143
+ source,
144
+ gateway_options)
145
+ handle_response(response, success_state, :failure)
146
+ end
147
147
  end
148
- end
149
148
 
150
- def handle_response(response, success_state, failure_state)
151
- record_response(response)
149
+ def handle_response(response, success_state, failure_state)
150
+ record_response(response)
152
151
 
153
- if response.success?
154
- unless response.authorization.nil?
155
- self.response_code = response.authorization
156
- self.avs_response = response.avs_result['code']
152
+ if response.success?
153
+ unless response.authorization.nil?
154
+ self.response_code = response.authorization
155
+ self.avs_response = response.avs_result['code']
157
156
 
158
- if response.cvv_result
159
- self.cvv_response_code = response.cvv_result['code']
160
- self.cvv_response_message = response.cvv_result['message']
157
+ if response.cvv_result
158
+ self.cvv_response_code = response.cvv_result['code']
159
+ self.cvv_response_message = response.cvv_result['message']
160
+ end
161
161
  end
162
+ self.send("#{success_state}!")
163
+ else
164
+ self.send(failure_state)
165
+ gateway_error(response)
162
166
  end
163
- self.send("#{success_state}!")
164
- else
165
- self.send(failure_state)
166
- gateway_error(response)
167
167
  end
168
- end
169
168
 
170
- def record_response(response)
171
- log_entries.create({:details => response.to_yaml}, :without_protection => true)
172
- end
169
+ def record_response(response)
170
+ log_entries.create({:details => response.to_yaml}, :without_protection => true)
171
+ end
173
172
 
174
- def protect_from_connection_error
175
- begin
176
- yield
177
- rescue ActiveMerchant::ConnectionError => e
178
- gateway_error(e)
173
+ def protect_from_connection_error
174
+ begin
175
+ yield
176
+ rescue ActiveMerchant::ConnectionError => e
177
+ gateway_error(e)
178
+ end
179
179
  end
180
- end
181
180
 
182
- def gateway_error(error)
183
- if error.is_a? ActiveMerchant::Billing::Response
184
- text = error.params['message'] || error.params['response_reason_text'] || error.message
185
- elsif error.is_a? ActiveMerchant::ConnectionError
186
- text = Spree.t(:unable_to_connect_to_gateway)
187
- else
188
- text = error.to_s
181
+ def gateway_error(error)
182
+ if error.is_a? ActiveMerchant::Billing::Response
183
+ text = error.params['message'] || error.params['response_reason_text'] || error.message
184
+ elsif error.is_a? ActiveMerchant::ConnectionError
185
+ text = Spree.t(:unable_to_connect_to_gateway)
186
+ else
187
+ text = error.to_s
188
+ end
189
+ logger.error(Spree.t(:gateway_error))
190
+ logger.error(" #{error.to_yaml}")
191
+ raise Core::GatewayError.new(text)
189
192
  end
190
- logger.error(Spree.t(:gateway_error))
191
- logger.error(" #{error.to_yaml}")
192
- raise Core::GatewayError.new(text)
193
- end
194
193
 
195
- # Saftey check to make sure we're not accidentally performing operations on a live gateway.
196
- # Ex. When testing in staging environment with a copy of production data.
197
- def check_environment
198
- return if payment_method.environment == Rails.env
199
- message = Spree.t(:gateway_config_unavailable) + " - #{Rails.env}"
200
- raise Core::GatewayError.new(message)
201
- end
194
+ # Saftey check to make sure we're not accidentally performing operations on a live gateway.
195
+ # Ex. When testing in staging environment with a copy of production data.
196
+ def check_environment
197
+ return if payment_method.environment == Rails.env
198
+ message = Spree.t(:gateway_config_unavailable) + " - #{Rails.env}"
199
+ raise Core::GatewayError.new(message)
200
+ end
202
201
 
203
- # The unique identifier to be passed in to the payment gateway
204
- def gateway_order_id
205
- "#{order.number}-#{self.identifier}"
202
+ # The unique identifier to be passed in to the payment gateway
203
+ def gateway_order_id
204
+ "#{order.number}-#{self.identifier}"
205
+ end
206
206
  end
207
207
  end
208
- end
208
+ end