spree_core 1.2.0 → 1.2.2

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 (98) hide show
  1. data/app/assets/javascripts/admin/admin.js.erb +10 -9
  2. data/app/assets/javascripts/admin/checkouts/edit.js +4 -4
  3. data/app/assets/javascripts/admin/product_autocomplete.js.erb +5 -5
  4. data/app/assets/javascripts/admin/taxon_autocomplete.js.erb +34 -0
  5. data/app/assets/javascripts/admin/taxonomy.js +11 -11
  6. data/app/assets/javascripts/store/cart.js.coffee +5 -2
  7. data/app/assets/javascripts/store/checkout.js.coffee +8 -4
  8. data/app/assets/stylesheets/admin/admin-form.css.erb +4 -0
  9. data/app/assets/stylesheets/store/screen.css.scss +1 -1
  10. data/app/controllers/spree/admin/banners_controller.rb +2 -2
  11. data/app/controllers/spree/admin/mail_methods_controller.rb +7 -0
  12. data/app/controllers/spree/admin/orders_controller.rb +3 -1
  13. data/app/controllers/spree/admin/payment_methods_controller.rb +7 -1
  14. data/app/controllers/spree/admin/products_controller.rb +11 -6
  15. data/app/controllers/spree/admin/prototypes_controller.rb +1 -1
  16. data/app/controllers/spree/admin/search_controller.rb +11 -31
  17. data/app/controllers/spree/admin/taxons_controller.rb +8 -0
  18. data/app/controllers/spree/checkout_controller.rb +7 -1
  19. data/app/controllers/spree/home_controller.rb +1 -0
  20. data/app/controllers/spree/orders_controller.rb +18 -5
  21. data/app/controllers/spree/products_controller.rb +1 -0
  22. data/app/controllers/spree/taxons_controller.rb +1 -0
  23. data/app/helpers/spree/admin/general_settings_helper.rb +1 -1
  24. data/app/helpers/spree/base_helper.rb +1 -1
  25. data/app/models/spree/ability.rb +5 -0
  26. data/app/models/spree/app_configuration.rb +1 -0
  27. data/app/models/spree/calculator/price_sack.rb +5 -3
  28. data/app/models/spree/credit_card.rb +2 -2
  29. data/app/models/spree/image.rb +2 -1
  30. data/app/models/spree/inventory_unit.rb +11 -3
  31. data/app/models/spree/line_item.rb +3 -2
  32. data/app/models/spree/order.rb +52 -9
  33. data/app/models/spree/order/checkout.rb +5 -8
  34. data/app/models/spree/payment.rb +1 -1
  35. data/app/models/spree/payment/processing.rb +21 -16
  36. data/app/models/spree/payment_method.rb +1 -1
  37. data/app/models/spree/preference.rb +1 -1
  38. data/app/models/spree/preferences/preferable_class_methods.rb +2 -0
  39. data/app/models/spree/preferences/store.rb +20 -2
  40. data/app/models/spree/product.rb +16 -0
  41. data/app/models/spree/product/scopes.rb +19 -8
  42. data/app/models/spree/return_authorization.rb +1 -0
  43. data/app/models/spree/shipment.rb +6 -4
  44. data/app/models/spree/shipping_method.rb +5 -6
  45. data/app/models/spree/tax_rate.rb +4 -2
  46. data/app/models/spree/taxon.rb +7 -0
  47. data/app/models/spree/variant.rb +26 -15
  48. data/app/views/spree/admin/banners/_gateway.html.erb +14 -0
  49. data/app/views/spree/admin/general_settings/edit.html.erb +13 -4
  50. data/app/views/spree/admin/orders/_form.html.erb +1 -1
  51. data/app/views/spree/admin/orders/customer_details/_form.html.erb +1 -1
  52. data/app/views/spree/admin/product_properties/index.html.erb +1 -1
  53. data/app/views/spree/admin/products/_form.html.erb +7 -8
  54. data/app/views/spree/admin/products/new.html.erb +1 -1
  55. data/app/views/spree/admin/return_authorizations/_form.html.erb +17 -33
  56. data/app/views/spree/admin/search/users.rabl +32 -0
  57. data/app/views/spree/admin/shared/_head.html.erb +3 -13
  58. data/app/views/spree/admin/shared/_routes.html.erb +8 -0
  59. data/app/views/spree/admin/shared/_translations.html.erb +26 -0
  60. data/app/views/spree/admin/tax_rates/_form.html.erb +8 -0
  61. data/app/views/spree/admin/tax_rates/index.html.erb +5 -1
  62. data/app/views/spree/admin/taxonomies/edit.erb +2 -2
  63. data/app/views/spree/admin/taxonomies/get_children.json.erb +1 -1
  64. data/app/views/spree/admin/taxons/search.rabl +5 -0
  65. data/app/views/spree/checkout/_confirm.html.erb +1 -0
  66. data/app/views/spree/checkout/payment/_gateway.html.erb +1 -1
  67. data/app/views/spree/orders/_adjustments.html.erb +1 -1
  68. data/app/views/spree/orders/edit.html.erb +3 -1
  69. data/app/views/spree/products/_cart_form.html.erb +3 -3
  70. data/app/views/spree/products/_thumbnails.html.erb +1 -1
  71. data/app/views/spree/shared/_head.html.erb +0 -2
  72. data/app/views/spree/shared/_order_details.html.erb +2 -2
  73. data/app/views/spree/shared/_products.html.erb +1 -1
  74. data/app/views/spree/shared/_taxonomies.html.erb +1 -1
  75. data/app/views/spree/shipment_mailer/shipped_email.text.erb +1 -1
  76. data/config/initializers/check_for_orphaned_preferences.rb +1 -1
  77. data/config/initializers/rails_5868.rb +8 -0
  78. data/config/locales/en.yml +4 -0
  79. data/config/routes.rb +13 -0
  80. data/db/default/spree/countries.yml +6 -0
  81. data/db/migrate/20120905145253_add_tax_rate_label.rb +5 -0
  82. data/db/migrate/20120905151823_add_toggle_tax_rate_display.rb +5 -0
  83. data/db/migrate/20121009142519_add_lock_version_to_variant.rb +5 -0
  84. data/db/migrate/20121017010007_remove_not_null_constraint_from_products_on_hand.rb +11 -0
  85. data/lib/generators/spree/custom_user/custom_user_generator.rb +4 -1
  86. data/lib/spree/core.rb +3 -2
  87. data/lib/spree/core/mail_settings.rb +2 -1
  88. data/lib/spree/core/permalinks.rb +1 -2
  89. data/lib/spree/core/search/base.rb +1 -0
  90. data/lib/spree/core/testing_support/authorization_helpers.rb +30 -0
  91. data/lib/spree/core/testing_support/factories/product_factory.rb +1 -1
  92. data/lib/spree/core/testing_support/flash.rb +17 -0
  93. data/lib/spree/core/testing_support/preferences.rb +26 -0
  94. data/lib/spree/core/version.rb +1 -1
  95. data/lib/spree/money.rb +4 -1
  96. metadata +69 -46
  97. data/config/initializers/workarounds_for_ruby19.rb +0 -72
  98. data/lib/spree/core/testing_support/env.rb +0 -2
@@ -5,6 +5,7 @@ module Spree
5
5
 
6
6
  def index
7
7
  @searcher = Spree::Config.searcher_class.new(params)
8
+ @searcher.current_user = try_spree_current_user
8
9
  @products = @searcher.retrieve_products
9
10
  respond_with(@products)
10
11
  end
@@ -1,5 +1,7 @@
1
1
  module Spree
2
2
  class OrdersController < BaseController
3
+ ssl_required :show
4
+
3
5
  rescue_from ActiveRecord::RecordNotFound, :with => :render_404
4
6
  helper 'spree/products'
5
7
 
@@ -13,9 +15,18 @@ module Spree
13
15
  def update
14
16
  @order = current_order
15
17
  if @order.update_attributes(params[:order])
16
- @order.line_items = @order.line_items.select {|li| li.quantity > 0 }
18
+ @order.line_items = @order.line_items.select { |li| li.quantity > 0 }
17
19
  fire_event('spree.order.contents_changed')
18
- respond_with(@order) { |format| format.html { redirect_to cart_path } }
20
+ respond_with(@order) do |format|
21
+ format.html do
22
+ if params.has_key?(:checkout)
23
+ @order.next_transition.run_callbacks
24
+ redirect_to checkout_state_path(@order.checkout_steps.first)
25
+ else
26
+ redirect_to cart_path
27
+ end
28
+ end
29
+ end
19
30
  else
20
31
  respond_with(@order)
21
32
  end
@@ -64,8 +75,10 @@ module Spree
64
75
  redirect_to spree.cart_path
65
76
  end
66
77
 
67
- def accurate_titles
68
- @order && @order.completed? ? "#{Order.model_name.human} #{@order.number}" : t(:shopping_cart)
69
- end
78
+ private
79
+
80
+ def accurate_title
81
+ @order && @order.completed? ? "#{Order.model_name.human} #{@order.number}" : t(:shopping_cart)
82
+ end
70
83
  end
71
84
  end
@@ -8,6 +8,7 @@ module Spree
8
8
 
9
9
  def index
10
10
  @searcher = Config.searcher_class.new(params)
11
+ @searcher.current_user = try_spree_current_user
11
12
  @products = @searcher.retrieve_products
12
13
  respond_with(@products)
13
14
  end
@@ -10,6 +10,7 @@ module Spree
10
10
  return unless @taxon
11
11
 
12
12
  @searcher = Spree::Config.searcher_class.new(params.merge(:taxon => @taxon.id))
13
+ @searcher.current_user = try_spree_current_user
13
14
  @products = @searcher.retrieve_products
14
15
 
15
16
  respond_with(@taxon)
@@ -6,7 +6,7 @@ module Spree
6
6
  iso = details[:iso_code]
7
7
  [iso, "#{details[:name]} (#{iso})"]
8
8
  end
9
- options_from_collection_for_select(currencies, :first, :last)
9
+ options_from_collection_for_select(currencies, :first, :last, Spree::Config[:currency])
10
10
  end
11
11
  end
12
12
  end
@@ -87,7 +87,7 @@ module Spree
87
87
  end
88
88
 
89
89
  def flash_messages(opts = {})
90
- opts[:ignore_types] = [:commerce_tracking].concat(opts[:ignore_types] || [])
90
+ opts[:ignore_types] = [:commerce_tracking].concat(Array(opts[:ignore_types]) || [])
91
91
 
92
92
  flash.each do |msg_type, text|
93
93
  unless opts[:ignore_types].include?(msg_type)
@@ -51,6 +51,11 @@ module Spree
51
51
  order.user == user || order.token && token == order.token
52
52
  end
53
53
  can :create, Order
54
+
55
+ can :read, Address do |address|
56
+ address.user == user
57
+ end
58
+
54
59
  #############################
55
60
  can :read, Product
56
61
  can :index, Product
@@ -42,6 +42,7 @@ module Spree
42
42
  preference :company, :boolean, :default => false # Request company field for billing and shipping addr
43
43
  preference :create_inventory_units, :boolean, :default => true # should only be false when track_inventory_levels is false, also disables RMA's
44
44
  preference :currency, :string, :default => "USD"
45
+ preference :currency_symbol_position, :string, :default => "before"
45
46
  preference :display_currency, :boolean, :default => false
46
47
  preference :default_country_id, :integer, :default => 214
47
48
  preference :default_locale, :string, :default => Rails.application.config.i18n.default_locale || :en
@@ -1,4 +1,6 @@
1
1
  require_dependency 'spree/calculator'
2
+ # For #to_d method on Ruby 1.8
3
+ require 'bigdecimal/util'
2
4
 
3
5
  module Spree
4
6
  class Calculator::PriceSack < Calculator
@@ -17,12 +19,12 @@ module Spree
17
19
  # as object we always get line items, as calculable we have Coupon, ShippingMethod
18
20
  def compute(object)
19
21
  if object.is_a?(Array)
20
- base = object.map { |o| o.respond_to?(:amount) ? o.amount : o.to_d }.sum
22
+ base = object.map { |o| o.respond_to?(:amount) ? o.amount : BigDecimal(o.to_s) }.sum
21
23
  else
22
- base = object.respond_to?(:amount) ? object.amount : object.to_d
24
+ base = object.respond_to?(:amount) ? object.amount : BigDecimal(object.to_s)
23
25
  end
24
26
 
25
- if base >= self.preferred_minimal_amount
27
+ if base < self.preferred_minimal_amount
26
28
  self.preferred_normal_amount
27
29
  else
28
30
  self.preferred_discount_amount
@@ -1,6 +1,6 @@
1
1
  module Spree
2
2
  class CreditCard < ActiveRecord::Base
3
- has_many :payments
3
+ has_many :payments, :as => :source
4
4
 
5
5
  before_save :set_last_digits
6
6
  after_validation :set_card_type
@@ -63,7 +63,7 @@ module Spree
63
63
  cc_type
64
64
  end
65
65
 
66
- scope :with_payment_profile, where('gateway_customer_profile_id IS NOT NULL')
66
+ scope :with_payment_profile, lambda { where('gateway_customer_profile_id IS NOT NULL') }
67
67
 
68
68
  def actions
69
69
  %w{capture void credit}
@@ -9,7 +9,8 @@ module Spree
9
9
  :styles => { :mini => '48x48>', :small => '100x100>', :product => '240x240>', :large => '600x600>' },
10
10
  :default_style => :product,
11
11
  :url => '/spree/products/:id/:style/:basename.:extension',
12
- :path => ':rails_root/public/spree/products/:id/:style/:basename.:extension'
12
+ :path => ':rails_root/public/spree/products/:id/:style/:basename.:extension',
13
+ :convert_options => { :all => '-strip' }
13
14
  # save the w,h of the original image (from which others can be calculated)
14
15
  # we need to look at the write-queue for images which have not been saved yet
15
16
  after_post_process :find_dimensions
@@ -5,7 +5,13 @@ module Spree
5
5
  belongs_to :shipment
6
6
  belongs_to :return_authorization
7
7
 
8
- scope :backorder, where(:state => 'backordered')
8
+ scope :backordered, lambda { where(:state => 'backordered') }
9
+ scope :shipped, lambda { where(:state => 'shipped') }
10
+
11
+ def self.backorder
12
+ warn "[SPREE] Spree::InventoryUnit.backorder will be deprecated in Spree 1.3. Please use Spree::Product.backordered instead."
13
+ backordered
14
+ end
9
15
 
10
16
  attr_accessible :shipment
11
17
 
@@ -107,8 +113,10 @@ module Spree
107
113
  end
108
114
 
109
115
  def restock_variant
110
- variant.on_hand += 1
111
- variant.save
116
+ if Spree::Config[:track_inventory_levels]
117
+ variant.on_hand += 1
118
+ variant.save
119
+ end
112
120
  end
113
121
  end
114
122
  end
@@ -10,7 +10,7 @@ module Spree
10
10
  before_validation :copy_price
11
11
 
12
12
  validates :variant, :presence => true
13
- validates :quantity, :numericality => { :only_integer => true, :message => I18n.t('validation.must_be_int') }
13
+ validates :quantity, :numericality => { :only_integer => true, :message => I18n.t('validation.must_be_int'), :greater_than => -1 }
14
14
  validates :price, :numericality => true
15
15
  validate :stock_availability
16
16
  validate :quantity_no_less_than_shipped
@@ -80,6 +80,7 @@ module Spree
80
80
 
81
81
  def update_order
82
82
  # update the order totals, etc.
83
+ order.create_tax_charge!
83
84
  order.update!
84
85
  end
85
86
 
@@ -97,7 +98,7 @@ module Spree
97
98
  end
98
99
 
99
100
  def quantity_no_less_than_shipped
100
- already_shipped = order.shipments.reduce(0) { |acc,s| acc + s.inventory_units.select { |i| i.variant == variant }.count }
101
+ already_shipped = order.shipments.reduce(0) { |acc, s| acc + s.inventory_units.shipped.where(:variant_id => variant_id).count }
101
102
  unless quantity >= already_shipped
102
103
  errors.add(:quantity, I18n.t('validation.cannot_be_less_than_shipped_units'))
103
104
  end
@@ -63,7 +63,6 @@ module Spree
63
63
  before_create :link_by_email
64
64
  after_create :create_tax_charge!
65
65
 
66
- # TODO: validate the format of the email as well (but we can't rely on authlogic anymore to help with validation)
67
66
  validates :email, :presence => true, :email => true, :if => :require_email
68
67
  validate :has_available_shipment
69
68
  validate :has_available_payment
@@ -128,6 +127,7 @@ module Spree
128
127
 
129
128
  # Is this a free order in which case the payment step should be skipped
130
129
  def payment_required?
130
+ update_totals
131
131
  total.to_f > 0.0
132
132
  end
133
133
 
@@ -144,7 +144,7 @@ module Spree
144
144
  # Indicates whether there are any backordered InventoryUnits associated with the Order.
145
145
  def backordered?
146
146
  return false unless Spree::Config[:track_inventory_levels]
147
- inventory_units.backorder.present?
147
+ inventory_units.backordered.present?
148
148
  end
149
149
 
150
150
  # Returns the relevant zone (if any) to be used for taxation purposes. Uses default tax zone
@@ -230,7 +230,7 @@ module Spree
230
230
 
231
231
  def allow_cancel?
232
232
  return false unless completed? and state != 'canceled'
233
- %w{ready backorder pending}.include? shipment_state
233
+ shipment_state.nil? || %w{ready backorder pending}.include?(shipment_state)
234
234
  end
235
235
 
236
236
  def allow_resume?
@@ -239,6 +239,10 @@ module Spree
239
239
  true
240
240
  end
241
241
 
242
+ def awaiting_returns?
243
+ return_authorizations.any? { |return_authorization| return_authorization.authorized? }
244
+ end
245
+
242
246
  def add_variant(variant, quantity = 1)
243
247
  current_item = find_line_item_by_variant(variant)
244
248
  if current_item
@@ -350,8 +354,16 @@ module Spree
350
354
  def finalize!
351
355
  touch :completed_at
352
356
  InventoryUnit.assign_opening_inventory(self)
353
- # lock any optional adjustments (coupon promotions, etc.)
354
- adjustments.optional.each { |adjustment| adjustment.update_column('locked', true) }
357
+
358
+ # lock all adjustments (coupon promotions, etc.)
359
+ adjustments.each { |adjustment| adjustment.update_column('locked', true) }
360
+
361
+ # update payment and shipment(s) states, and save
362
+ update_payment_state
363
+ shipments.each { |shipment| shipment.update!(self) }
364
+ update_shipment_state
365
+ save
366
+
355
367
  deliver_order_confirmation_email
356
368
 
357
369
  self.state_changes.create({
@@ -379,8 +391,23 @@ module Spree
379
391
  end
380
392
 
381
393
  def rate_hash
382
- @rate_hash ||= available_shipping_methods(:front_end).collect do |ship_method|
383
- next unless cost = ship_method.calculator.compute(self)
394
+ return @rate_hash if @rate_hash.present?
395
+
396
+ # reserve one slot for each shipping method computation
397
+ computed_costs = Array.new(available_shipping_methods(:front_end).size)
398
+
399
+ # create all the threads and kick off their execution
400
+ threads = available_shipping_methods(:front_end).each_with_index.map do |ship_method, index|
401
+ Thread.new { computed_costs[index] = [ship_method, ship_method.calculator.compute(self)] }
402
+ end
403
+
404
+ # wait for all threads to finish
405
+ threads.map(&:join)
406
+
407
+ # now consolidate and memoize the threaded results
408
+ @rate_hash ||= computed_costs.map do |pair|
409
+ ship_method,cost = *pair
410
+ next unless cost
384
411
  ShippingRate.new( :id => ship_method.id,
385
412
  :shipping_method => ship_method,
386
413
  :name => ship_method.name,
@@ -408,9 +435,21 @@ module Spree
408
435
  end
409
436
  end
410
437
 
438
+ def pending_payments
439
+ payments.select {|p| p.state == "checkout"}
440
+ end
441
+
411
442
  def process_payments!
412
443
  begin
413
- payments.each(&:process!)
444
+ pending_payments.each do |payment|
445
+ break if payment_total >= total
446
+
447
+ payment.process!
448
+
449
+ if payment.completed?
450
+ self.payment_total += payment.amount
451
+ end
452
+ end
414
453
  rescue Core::GatewayError
415
454
  !!Spree::Config[:allow_checkout_on_gateway_error]
416
455
  end
@@ -428,6 +467,10 @@ module Spree
428
467
  line_items.map { |li| li.variant.product }
429
468
  end
430
469
 
470
+ def variants
471
+ line_items.map(&:variant)
472
+ end
473
+
431
474
  def insufficient_stock_lines
432
475
  line_items.select &:insufficient_stock?
433
476
  end
@@ -505,7 +548,7 @@ module Spree
505
548
  #
506
549
  # The +payment_state+ value helps with reporting, etc. since it provides a quick and easy way to locate Orders needing attention.
507
550
  def update_payment_state
508
-
551
+
509
552
  #line_item are empty when user empties cart
510
553
  if self.line_items.empty? || round_money(payment_total) < round_money(total)
511
554
  self.payment_state = 'balance_due'
@@ -51,7 +51,7 @@ module Spree
51
51
  end
52
52
 
53
53
  event :return do
54
- transition :to => :returned, :from => :awaiting_return
54
+ transition :to => :returned, :from => :awaiting_return, :unless => :awaiting_returns?
55
55
  end
56
56
 
57
57
  event :resume do
@@ -64,7 +64,7 @@ module Spree
64
64
 
65
65
  before_transition :to => :complete do |order|
66
66
  begin
67
- order.process_payments!
67
+ order.process_payments! if order.payment_required?
68
68
  rescue Spree::Core::GatewayError
69
69
  !!Spree::Config[:allow_checkout_on_gateway_error]
70
70
  end
@@ -83,15 +83,12 @@ module Spree
83
83
 
84
84
  def self.go_to_state(name, options={})
85
85
  self.checkout_steps[name] = options
86
+ previous_states.each do |state|
87
+ add_transition({:from => state, :to => name}.merge(options))
88
+ end
86
89
  if options[:if]
87
- previous_states.each do |state|
88
- add_transition({:from => state, :to => name}.merge(options))
89
- end
90
90
  self.previous_states << name
91
91
  else
92
- previous_states.each do |state|
93
- add_transition({:from => state, :to => name}.merge(options))
94
- end
95
92
  self.previous_states = [name]
96
93
  end
97
94
  end
@@ -18,7 +18,7 @@ module Spree
18
18
 
19
19
  attr_accessible :amount, :payment_method_id, :source_attributes
20
20
 
21
- scope :from_credit_card, where(:source_type => 'Spree::CreditCard')
21
+ scope :from_credit_card, lambda { where(:source_type => 'Spree::CreditCard') }
22
22
  scope :with_state, lambda { |s| where(:state => s) }
23
23
  scope :completed, with_state('completed')
24
24
  scope :pending, with_state('pending')
@@ -28,6 +28,7 @@ module Spree
28
28
  end
29
29
 
30
30
  def capture!
31
+ return true if completed?
31
32
  protect_from_connection_error do
32
33
  check_environment
33
34
 
@@ -47,6 +48,7 @@ module Spree
47
48
  end
48
49
 
49
50
  def void_transaction!
51
+ return true if void?
50
52
  protect_from_connection_error do
51
53
  check_environment
52
54
 
@@ -104,6 +106,25 @@ module Spree
104
106
  credit!(amount)
105
107
  end
106
108
 
109
+ def gateway_options
110
+ options = { :email => order.email,
111
+ :customer => order.email,
112
+ :ip => '192.168.1.100', # TODO: Use an actual IP
113
+ :order_id => order.number }
114
+
115
+ options.merge!({ :shipping => order.ship_total * 100,
116
+ :tax => order.tax_total * 100,
117
+ :subtotal => order.item_total * 100 })
118
+
119
+ options.merge!({ :currency => payment_method.preferences[:currency_code] }) if payment_method && payment_method.preferences[:currency_code]
120
+
121
+ options.merge!({ :billing_address => order.bill_address.try(:active_merchant_hash),
122
+ :shipping_address => order.ship_address.try(:active_merchant_hash) })
123
+
124
+ options.merge!(:discount => promo_total) if respond_to?(:promo_total)
125
+ options
126
+ end
127
+
107
128
  private
108
129
 
109
130
  def gateway_action(source, action, success_state)
@@ -136,22 +157,6 @@ module Spree
136
157
  log_entries.create({:details => response.to_yaml}, :without_protection => true)
137
158
  end
138
159
 
139
- def gateway_options
140
- options = { :email => order.email,
141
- :customer => order.email,
142
- :ip => '192.168.1.100', # TODO: Use an actual IP
143
- :order_id => order.number }
144
-
145
- options.merge!({ :shipping => order.ship_total * 100,
146
- :tax => order.tax_total * 100,
147
- :subtotal => order.item_total * 100 })
148
-
149
- options.merge!({ :currency => payment_method.preferences[:currency_code] }) if payment_method && payment_method.preferences[:currency_code]
150
-
151
- options.merge({ :billing_address => order.bill_address.try(:active_merchant_hash),
152
- :shipping_address => order.ship_address.try(:active_merchant_hash) })
153
- end
154
-
155
160
  def protect_from_connection_error
156
161
  begin
157
162
  yield