spree_core 1.3.2 → 1.3.3
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.
- checksums.yaml +7 -0
- data/app/assets/images/credit_cards/icons/diners_club.png +0 -0
- data/app/assets/javascripts/admin/address_states.js +1 -1
- data/app/assets/javascripts/admin/admin.js.erb +18 -13
- data/app/assets/javascripts/admin/calculator.js +2 -2
- data/app/assets/javascripts/admin/checkouts/edit.js +3 -1
- data/app/assets/javascripts/admin/image_settings.js.erb +5 -5
- data/app/assets/javascripts/admin/orders/edit.js +1 -1
- data/app/assets/javascripts/admin/payments/new.js +9 -2
- data/app/assets/javascripts/admin/spree_core.js +13 -1
- data/app/assets/javascripts/admin/taxon_autocomplete.js.erb +2 -1
- data/app/assets/javascripts/admin/variant_autocomplete.js.erb +23 -19
- data/app/assets/javascripts/spree.js.coffee +37 -0
- data/app/assets/javascripts/store/checkout.js.coffee +8 -0
- data/app/assets/javascripts/store/product.js.coffee +1 -1
- data/app/assets/javascripts/store/spree_core.js +1 -0
- data/app/assets/stylesheets/admin/components/_sidebar.scss +7 -6
- data/app/assets/stylesheets/admin/components/_states.scss +16 -12
- data/app/assets/stylesheets/admin/globals/_variables.scss +102 -96
- data/app/assets/stylesheets/admin/shared/_forms.scss +2 -1
- data/app/assets/stylesheets/admin/shared/_icons.scss +2 -1
- data/app/assets/stylesheets/admin/shared/_layout.scss +4 -1
- data/app/assets/stylesheets/admin/shared/_tables.scss +8 -0
- data/app/assets/stylesheets/store/screen.css.scss +28 -16
- data/app/assets/stylesheets/store/variables.css.scss +4 -2
- data/app/controllers/spree/admin/adjustments_controller.rb +7 -3
- data/app/controllers/spree/admin/base_controller.rb +10 -5
- data/app/controllers/spree/admin/line_items_controller.rb +3 -2
- data/app/controllers/spree/admin/orders/customer_details_controller.rb +3 -2
- data/app/controllers/spree/admin/orders_controller.rb +2 -2
- data/app/controllers/spree/admin/payments_controller.rb +1 -1
- data/app/controllers/spree/admin/resource_controller.rb +5 -5
- data/app/controllers/spree/admin/shipments_controller.rb +1 -1
- data/app/controllers/spree/admin/taxons_controller.rb +1 -1
- data/app/controllers/spree/admin/users_controller.rb +96 -0
- data/app/controllers/spree/checkout_controller.rb +18 -7
- data/app/controllers/spree/locale_controller.rb +1 -1
- data/app/controllers/spree/orders_controller.rb +20 -2
- data/app/controllers/spree/taxons_controller.rb +8 -2
- data/app/helpers/spree/admin/images_helper.rb +6 -2
- data/app/helpers/spree/admin/navigation_helper.rb +23 -3
- data/app/helpers/spree/base_helper.rb +9 -5
- data/app/helpers/spree/orders_helper.rb +13 -0
- data/app/helpers/spree/products_helper.rb +9 -4
- data/app/mailers/spree/base_mailer.rb +16 -0
- data/app/mailers/spree/order_mailer.rb +12 -11
- data/app/mailers/spree/shipment_mailer.rb +4 -7
- data/app/mailers/spree/test_mailer.rb +2 -3
- data/app/models/spree/adjustment.rb +1 -1
- data/app/models/spree/app_configuration.rb +9 -3
- data/app/models/spree/calculator/default_tax.rb +5 -1
- data/app/models/spree/calculator/per_item.rb +1 -1
- data/app/models/spree/classification.rb +7 -0
- data/app/models/spree/credit_card.rb +1 -5
- data/app/models/spree/gateway.rb +10 -2
- data/app/models/spree/gateway/bogus.rb +5 -5
- data/app/models/spree/inventory_unit.rb +4 -4
- data/app/models/spree/line_item.rb +1 -1
- data/app/models/spree/order.rb +15 -35
- data/app/models/spree/order/checkout.rb +52 -0
- data/app/models/spree/order_populator.rb +11 -3
- data/app/models/spree/order_updater.rb +3 -4
- data/app/models/spree/payment.rb +23 -1
- data/app/models/spree/payment/processing.rb +18 -5
- data/app/models/spree/payment_method.rb +4 -0
- data/app/models/spree/price.rb +2 -3
- data/app/models/spree/product.rb +12 -4
- data/app/models/spree/product/scopes.rb +29 -16
- data/app/models/spree/return_authorization.rb +1 -1
- data/app/models/spree/shipment.rb +1 -1
- data/app/models/spree/taxon.rb +21 -6
- data/app/models/spree/variant.rb +7 -2
- data/app/views/spree/admin/adjustments/_adjustments_table.html.erb +2 -2
- data/app/views/spree/admin/countries/index.html.erb +1 -0
- data/app/views/spree/admin/general_settings/edit.html.erb +10 -2
- data/app/views/spree/admin/images/index.html.erb +7 -3
- data/app/views/spree/admin/mail_methods/index.html.erb +2 -2
- data/app/views/spree/admin/orders/_form.html.erb +3 -3
- data/app/views/spree/admin/orders/_line_item.html.erb +1 -1
- data/app/views/spree/admin/orders/customer_details/_form.html.erb +4 -4
- data/app/views/spree/admin/orders/index.html.erb +60 -52
- data/app/views/spree/admin/payment_methods/_form.html.erb +2 -2
- data/app/views/spree/admin/payment_methods/index.html.erb +39 -35
- data/app/views/spree/admin/payments/_list.html.erb +1 -1
- data/app/views/spree/admin/payments/source_forms/_gateway.html.erb +10 -10
- data/app/views/spree/admin/products/_form.html.erb +7 -12
- data/app/views/spree/admin/products/index.html.erb +13 -15
- data/app/views/spree/admin/products/new.html.erb +3 -1
- data/app/views/spree/admin/return_authorizations/_form.html.erb +7 -7
- data/app/views/spree/admin/return_authorizations/edit.html.erb +17 -11
- data/app/views/spree/admin/return_authorizations/index.html.erb +4 -4
- data/app/views/spree/admin/return_authorizations/new.html.erb +13 -6
- data/app/views/spree/admin/shared/_alert.html.erb +1 -1
- data/app/views/spree/admin/shared/_configuration_menu.html.erb +6 -2
- data/app/views/spree/admin/shared/_order_details.html.erb +6 -6
- data/app/views/spree/admin/shared/_order_tabs.html.erb +20 -37
- data/app/views/spree/admin/shared/_routes.html.erb +1 -1
- data/app/views/spree/admin/shared/_tabs.html.erb +1 -2
- data/app/views/spree/admin/shared/_update_order_state.js +1 -1
- data/app/views/spree/admin/shipments/_form.html.erb +24 -24
- data/app/views/spree/admin/shipments/edit.html.erb +13 -13
- data/app/views/spree/admin/shipments/index.html.erb +35 -31
- data/app/views/spree/admin/shipping_methods/index.html.erb +35 -32
- data/app/views/spree/admin/tax_rates/_form.html.erb +2 -1
- data/app/views/spree/admin/taxons/_form.html.erb +17 -0
- data/app/views/spree/admin/taxons/edit.html.erb +3 -1
- data/app/views/spree/admin/trackers/_form.html.erb +2 -2
- data/app/views/spree/admin/trackers/index.html.erb +2 -2
- data/app/views/spree/admin/users/_form.html.erb +37 -0
- data/app/views/spree/admin/users/edit.html.erb +28 -0
- data/app/views/spree/admin/users/index.html.erb +53 -0
- data/app/views/spree/admin/users/new.html.erb +23 -0
- data/app/views/spree/admin/users/show.html.erb +21 -0
- data/app/views/spree/admin/variants/edit.html.erb +6 -4
- data/app/views/spree/admin/variants/index.html.erb +1 -1
- data/app/views/spree/admin/zones/_form.html.erb +4 -4
- data/app/views/spree/admin/zones/index.html.erb +3 -1
- data/app/views/spree/checkout/_delivery.html.erb +1 -1
- data/app/views/spree/checkout/_payment.html.erb +1 -1
- data/app/views/spree/checkout/_summary.html.erb +2 -2
- data/app/views/spree/checkout/payment/_gateway.html.erb +6 -6
- data/app/views/spree/layouts/spree_application.html.erb +0 -1
- data/app/views/spree/order_mailer/cancel_email.text.erb +1 -1
- data/app/views/spree/order_mailer/confirm_email.text.erb +1 -1
- data/app/views/spree/orders/_adjustments.html.erb +1 -1
- data/app/views/spree/orders/_line_item.html.erb +2 -2
- data/app/views/spree/orders/edit.html.erb +1 -1
- data/app/views/spree/payments/_payment.html.erb +16 -0
- data/app/views/spree/products/_cart_form.html.erb +2 -2
- data/app/views/spree/products/_thumbnails.html.erb +3 -3
- data/app/views/spree/products/index.html.erb +1 -1
- data/app/views/spree/shared/_google_analytics.html.erb +1 -1
- data/app/views/spree/shared/_main_nav_bar.html.erb +1 -1
- data/app/views/spree/shared/_order_details.html.erb +10 -24
- data/app/views/spree/shared/_products.html.erb +1 -1
- data/app/views/spree/shared/_search.html.erb +1 -1
- data/app/views/spree/taxons/show.html.erb +1 -1
- data/config/initializers/check_for_orphaned_preferences.rb +5 -2
- data/config/locales/en.yml +24 -5
- data/config/routes.rb +4 -3
- data/db/default/spree/countries.rb +229 -0
- data/db/default/spree/roles.rb +2 -0
- data/db/default/spree/states.rb +57 -0
- data/db/default/spree/zones.rb +17 -0
- data/db/migrate/20130207155350_add_order_id_index_to_payments.rb +9 -0
- data/db/migrate/20130208032954_add_primary_to_spree_products_taxons.rb +5 -0
- data/db/migrate/20130222032153_add_order_id_index_to_shipments.rb +5 -0
- data/db/migrate/20130226032817_change_meta_description_on_spree_products_to_text.rb +5 -0
- data/db/migrate/20130226054936_add_variant_id_index_to_spree_prices.rb +5 -0
- data/db/migrate/20130319062004_change_orders_total_precision.rb +8 -0
- data/db/migrate/20130319063911_change_spree_payments_amount_precision.rb +7 -0
- data/db/migrate/20130319064308_change_spree_return_authorization_amount_precision.rb +7 -0
- data/db/migrate/20130319082943_change_adjustments_amount_precision.rb +7 -0
- data/db/migrate/20130328195253_add_seo_metas_to_taxons.rb +9 -0
- data/lib/generators/spree/dummy/templates/rails/database.yml +9 -6
- data/lib/spree/core/calculated_adjustments.rb +1 -1
- data/lib/spree/core/controller_helpers/auth.rb +3 -3
- data/lib/spree/core/controller_helpers/common.rb +1 -11
- data/lib/spree/core/controller_helpers/order.rb +15 -12
- data/lib/spree/core/engine.rb +5 -1
- data/lib/spree/core/mail_interceptor.rb +4 -6
- data/lib/spree/core/mail_settings.rb +52 -23
- data/lib/spree/core/permalinks.rb +1 -3
- data/lib/spree/core/testing_support/authorization_helpers.rb +1 -1
- data/lib/spree/core/testing_support/capybara_ext.rb +30 -0
- data/lib/spree/core/testing_support/common_rake.rb +8 -0
- data/lib/spree/core/testing_support/factories/payment_factory.rb +1 -1
- data/lib/spree/core/testing_support/factories/product_factory.rb +7 -2
- data/lib/spree/core/testing_support/factories/variant_factory.rb +4 -2
- data/lib/spree/core/validators/email.rb +1 -1
- data/lib/spree/core/version.rb +1 -1
- data/lib/spree/money.rb +14 -3
- data/lib/spree/product_filters.rb +1 -1
- data/vendor/assets/javascripts/jquery.jstree/jquery.jstree.js +3 -2
- data/vendor/assets/javascripts/jsuri.js +2 -0
- data/vendor/assets/javascripts/modernizr.js +3 -3
- metadata +78 -69
- data/db/default/spree/countries.yml +0 -1589
- data/db/default/spree/roles.yml +0 -5
- data/db/default/spree/states.yml +0 -256
- data/db/default/spree/zone_members.yml +0 -169
- data/db/default/spree/zones.yml +0 -13
|
@@ -33,7 +33,11 @@ module Spree
|
|
|
33
33
|
|
|
34
34
|
def compute_line_item(line_item)
|
|
35
35
|
if line_item.product.tax_category == rate.tax_category
|
|
36
|
-
|
|
36
|
+
if rate.included_in_price
|
|
37
|
+
deduced_total_by_rate(line_item.total, rate)
|
|
38
|
+
else
|
|
39
|
+
round_to_two_places(line_item.total * rate.amount)
|
|
40
|
+
end
|
|
37
41
|
else
|
|
38
42
|
0
|
|
39
43
|
end
|
|
@@ -14,7 +14,7 @@ module Spree
|
|
|
14
14
|
def compute(object=nil)
|
|
15
15
|
return 0 if object.nil?
|
|
16
16
|
self.preferred_amount * object.line_items.reduce(0) do |sum, value|
|
|
17
|
-
if
|
|
17
|
+
if matching_products.blank? || matching_products.include?(value.product)
|
|
18
18
|
value_to_add = value.quantity
|
|
19
19
|
else
|
|
20
20
|
value_to_add = 0
|
|
@@ -14,10 +14,6 @@ module Spree
|
|
|
14
14
|
attr_accessible :first_name, :last_name, :number, :verification_value, :year,
|
|
15
15
|
:month, :gateway_customer_profile_id, :gateway_payment_profile_id
|
|
16
16
|
|
|
17
|
-
def number=(num)
|
|
18
|
-
@number = num.gsub(/[^0-9]/, '') rescue nil
|
|
19
|
-
end
|
|
20
|
-
|
|
21
17
|
def set_last_digits
|
|
22
18
|
number.to_s.gsub!(/\s/,'')
|
|
23
19
|
verification_value.to_s.gsub!(/\s/,'')
|
|
@@ -64,7 +60,7 @@ module Spree
|
|
|
64
60
|
|
|
65
61
|
# needed for some of the ActiveMerchant gateways (eg. SagePay)
|
|
66
62
|
def brand
|
|
67
|
-
|
|
63
|
+
spree_cc_type
|
|
68
64
|
end
|
|
69
65
|
|
|
70
66
|
scope :with_payment_profile, lambda { where('gateway_customer_profile_id IS NOT NULL') }
|
data/app/models/spree/gateway.rb
CHANGED
|
@@ -21,7 +21,9 @@ module Spree
|
|
|
21
21
|
def provider
|
|
22
22
|
gateway_options = options
|
|
23
23
|
gateway_options.delete :login if gateway_options.has_key?(:login) and gateway_options[:login].nil?
|
|
24
|
-
|
|
24
|
+
if gateway_options[:server]
|
|
25
|
+
ActiveMerchant::Billing::Base.gateway_mode = gateway_options[:server].to_sym
|
|
26
|
+
end
|
|
25
27
|
@provider ||= provider_class.new(gateway_options)
|
|
26
28
|
end
|
|
27
29
|
|
|
@@ -33,7 +35,7 @@ module Spree
|
|
|
33
35
|
if @provider.nil? || !@provider.respond_to?(method)
|
|
34
36
|
super
|
|
35
37
|
else
|
|
36
|
-
provider.send(method)
|
|
38
|
+
provider.send(method, *args)
|
|
37
39
|
end
|
|
38
40
|
end
|
|
39
41
|
|
|
@@ -44,5 +46,11 @@ module Spree
|
|
|
44
46
|
def method_type
|
|
45
47
|
'gateway'
|
|
46
48
|
end
|
|
49
|
+
|
|
50
|
+
def supports?(source)
|
|
51
|
+
return true unless provider_class.respond_to? :supports?
|
|
52
|
+
return false unless source.brand
|
|
53
|
+
provider_class.supports?(source.brand)
|
|
54
|
+
end
|
|
47
55
|
end
|
|
48
56
|
end
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
module Spree
|
|
2
2
|
class Gateway::Bogus < Gateway
|
|
3
|
-
TEST_VISA = '4111111111111111'
|
|
4
|
-
TEST_MC = '5500000000000004'
|
|
5
|
-
TEST_AMEX = '340000000000009'
|
|
6
|
-
TEST_DISC = '6011000000000004'
|
|
3
|
+
TEST_VISA = ['4111111111111111','4012888888881881','4222222222222']
|
|
4
|
+
TEST_MC = ['5500000000000004','5555555555554444','5105105105105100']
|
|
5
|
+
TEST_AMEX = ['378282246310005','371449635398431','378734493671000','340000000000009']
|
|
6
|
+
TEST_DISC = ['6011000000000004','6011111111111117','6011000990139424']
|
|
7
7
|
|
|
8
|
-
VALID_CCS = ['1', TEST_VISA, TEST_MC, TEST_AMEX, TEST_DISC]
|
|
8
|
+
VALID_CCS = ['1', TEST_VISA, TEST_MC, TEST_AMEX, TEST_DISC].flatten
|
|
9
9
|
|
|
10
10
|
attr_accessor :test
|
|
11
11
|
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
module Spree
|
|
2
2
|
class InventoryUnit < ActiveRecord::Base
|
|
3
|
-
belongs_to :variant
|
|
4
|
-
belongs_to :order
|
|
5
|
-
belongs_to :shipment
|
|
6
|
-
belongs_to :return_authorization
|
|
3
|
+
belongs_to :variant, :class_name => "Spree::Variant"
|
|
4
|
+
belongs_to :order, :class_name => "Spree::Order"
|
|
5
|
+
belongs_to :shipment, :class_name => "Spree::Shipment"
|
|
6
|
+
belongs_to :return_authorization, :class_name => "Spree::ReturnAuthorization"
|
|
7
7
|
|
|
8
8
|
scope :backordered, lambda { where(:state => 'backordered') }
|
|
9
9
|
scope :shipped, lambda { where(:state => 'shipped') }
|
data/app/models/spree/order.rb
CHANGED
|
@@ -24,7 +24,7 @@ module Spree
|
|
|
24
24
|
order.payment_required?
|
|
25
25
|
}
|
|
26
26
|
go_to_state :confirm, :if => lambda { |order| order.confirmation_required? }
|
|
27
|
-
go_to_state :complete, :if => lambda { |order| (order.payment_required? && order.
|
|
27
|
+
go_to_state :complete, :if => lambda { |order| (order.payment_required? && order.has_unprocessed_payments?) || !order.payment_required? }
|
|
28
28
|
remove_transition :from => :delivery, :to => :confirm
|
|
29
29
|
end
|
|
30
30
|
|
|
@@ -164,7 +164,14 @@ module Spree
|
|
|
164
164
|
|
|
165
165
|
# If true, causes the confirmation step to happen during the checkout process
|
|
166
166
|
def confirmation_required?
|
|
167
|
-
payment_method
|
|
167
|
+
payments.map(&:payment_method).any?(&:payment_profiles_supported?)
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
# Used by the checkout state machine to check for unprocessed payments
|
|
171
|
+
# The Order should be unable to proceed to complete if there are unprocessed
|
|
172
|
+
# payments and there is payment required.
|
|
173
|
+
def has_unprocessed_payments?
|
|
174
|
+
payments.with_state('checkout').reload.exists?
|
|
168
175
|
end
|
|
169
176
|
|
|
170
177
|
# Indicates the number of items in the order
|
|
@@ -214,7 +221,7 @@ module Spree
|
|
|
214
221
|
end
|
|
215
222
|
|
|
216
223
|
def updater
|
|
217
|
-
OrderUpdater.new(self)
|
|
224
|
+
@updater ||= OrderUpdater.new(self)
|
|
218
225
|
end
|
|
219
226
|
|
|
220
227
|
def update!
|
|
@@ -375,11 +382,11 @@ module Spree
|
|
|
375
382
|
adjustments.each { |adjustment| adjustment.update_column('locked', true) }
|
|
376
383
|
|
|
377
384
|
# update payment and shipment(s) states, and save
|
|
378
|
-
updater = OrderUpdater.new(self)
|
|
379
385
|
updater.update_payment_state
|
|
380
386
|
shipments.each { |shipment| shipment.update!(self) }
|
|
381
387
|
updater.update_shipment_state
|
|
382
388
|
save
|
|
389
|
+
updater.run_hooks
|
|
383
390
|
|
|
384
391
|
deliver_order_confirmation_email
|
|
385
392
|
|
|
@@ -393,7 +400,7 @@ module Spree
|
|
|
393
400
|
|
|
394
401
|
def deliver_order_confirmation_email
|
|
395
402
|
begin
|
|
396
|
-
OrderMailer.confirm_email(self).deliver
|
|
403
|
+
OrderMailer.confirm_email(self.id).deliver
|
|
397
404
|
rescue Exception => e
|
|
398
405
|
logger.error("#{e.class.name}: #{e.message}")
|
|
399
406
|
logger.error(e.backtrace * "\n")
|
|
@@ -408,23 +415,8 @@ module Spree
|
|
|
408
415
|
end
|
|
409
416
|
|
|
410
417
|
def rate_hash
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
# reserve one slot for each shipping method computation
|
|
414
|
-
computed_costs = Array.new(available_shipping_methods(:front_end).size)
|
|
415
|
-
|
|
416
|
-
# create all the threads and kick off their execution
|
|
417
|
-
threads = available_shipping_methods(:front_end).each_with_index.map do |ship_method, index|
|
|
418
|
-
Thread.new { computed_costs[index] = [ship_method, ship_method.calculator.compute(self)] }
|
|
419
|
-
end
|
|
420
|
-
|
|
421
|
-
# wait for all threads to finish
|
|
422
|
-
threads.map(&:join)
|
|
423
|
-
|
|
424
|
-
# now consolidate and memoize the threaded results
|
|
425
|
-
@rate_hash ||= computed_costs.map do |pair|
|
|
426
|
-
ship_method,cost = *pair
|
|
427
|
-
next unless cost
|
|
418
|
+
@rate_hash ||= available_shipping_methods.collect do |ship_method|
|
|
419
|
+
next unless cost = ship_method.calculator.compute(self)
|
|
428
420
|
ShippingRate.new( :id => ship_method.id,
|
|
429
421
|
:shipping_method => ship_method,
|
|
430
422
|
:name => ship_method.name,
|
|
@@ -437,22 +429,10 @@ module Spree
|
|
|
437
429
|
payment_state == 'paid'
|
|
438
430
|
end
|
|
439
431
|
|
|
440
|
-
def payment
|
|
441
|
-
payments.first
|
|
442
|
-
end
|
|
443
|
-
|
|
444
432
|
def available_payment_methods
|
|
445
433
|
@available_payment_methods ||= PaymentMethod.available(:front_end)
|
|
446
434
|
end
|
|
447
435
|
|
|
448
|
-
def payment_method
|
|
449
|
-
if payment and payment.payment_method
|
|
450
|
-
payment.payment_method
|
|
451
|
-
else
|
|
452
|
-
available_payment_methods.first
|
|
453
|
-
end
|
|
454
|
-
end
|
|
455
|
-
|
|
456
436
|
def pending_payments
|
|
457
437
|
payments.select {|p| p.state == "checkout"}
|
|
458
438
|
end
|
|
@@ -565,7 +545,7 @@ module Spree
|
|
|
565
545
|
restock_items!
|
|
566
546
|
|
|
567
547
|
#TODO: make_shipments_pending
|
|
568
|
-
OrderMailer.cancel_email(self).deliver
|
|
548
|
+
OrderMailer.cancel_email(self.id).deliver
|
|
569
549
|
unless %w(partial shipped).include?(shipment_state)
|
|
570
550
|
self.payment_state = 'credit_owed'
|
|
571
551
|
end
|
|
@@ -7,6 +7,7 @@ module Spree
|
|
|
7
7
|
class_attribute :previous_states
|
|
8
8
|
class_attribute :checkout_flow
|
|
9
9
|
class_attribute :checkout_steps
|
|
10
|
+
class_attribute :removed_transitions
|
|
10
11
|
|
|
11
12
|
def self.checkout_flow(&block)
|
|
12
13
|
if block_given?
|
|
@@ -22,6 +23,7 @@ module Spree
|
|
|
22
23
|
self.checkout_steps = ActiveSupport::OrderedHash.new
|
|
23
24
|
self.next_event_transitions = []
|
|
24
25
|
self.previous_states = [:cart]
|
|
26
|
+
self.removed_transitions = []
|
|
25
27
|
|
|
26
28
|
# Build the checkout flow using the checkout_flow defined either
|
|
27
29
|
# within the Order class, or a decorator for that class.
|
|
@@ -93,7 +95,40 @@ module Spree
|
|
|
93
95
|
end
|
|
94
96
|
end
|
|
95
97
|
|
|
98
|
+
def self.insert_checkout_step(name, options = {})
|
|
99
|
+
before = options.delete(:before)
|
|
100
|
+
after = options.delete(:after) unless before
|
|
101
|
+
after = self.checkout_steps.keys.last unless before || after
|
|
102
|
+
|
|
103
|
+
cloned_steps = self.checkout_steps.clone
|
|
104
|
+
cloned_removed_transitions = self.removed_transitions.clone
|
|
105
|
+
self.checkout_flow do
|
|
106
|
+
cloned_steps.each_pair do |key, value|
|
|
107
|
+
self.go_to_state(name, options) if key == before
|
|
108
|
+
self.go_to_state(key, value)
|
|
109
|
+
self.go_to_state(name, options) if key == after
|
|
110
|
+
end
|
|
111
|
+
cloned_removed_transitions.each do |transition|
|
|
112
|
+
self.remove_transition(transition)
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def self.remove_checkout_step(name)
|
|
118
|
+
cloned_steps = self.checkout_steps.clone
|
|
119
|
+
cloned_removed_transitions = self.removed_transitions.clone
|
|
120
|
+
self.checkout_flow do
|
|
121
|
+
cloned_steps.each_pair do |key, value|
|
|
122
|
+
self.go_to_state(key, value) unless key == name
|
|
123
|
+
end
|
|
124
|
+
cloned_removed_transitions.each do |transition|
|
|
125
|
+
self.remove_transition(transition)
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
|
|
96
130
|
def self.remove_transition(options={})
|
|
131
|
+
self.removed_transitions << options
|
|
97
132
|
if transition = find_transition(options)
|
|
98
133
|
self.next_event_transitions.delete(transition)
|
|
99
134
|
end
|
|
@@ -131,6 +166,23 @@ module Spree
|
|
|
131
166
|
steps << "complete" unless steps.include?("complete")
|
|
132
167
|
steps
|
|
133
168
|
end
|
|
169
|
+
|
|
170
|
+
def has_checkout_step?(step)
|
|
171
|
+
step.present? ? self.checkout_steps.include?(step) : false
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
def checkout_step_index(step)
|
|
175
|
+
self.checkout_steps.index(step)
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
def self.removed_transitions
|
|
179
|
+
@removed_transitions ||= []
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
def can_go_to_state?(state)
|
|
183
|
+
return false unless self.state.present? && has_checkout_step?(state) && has_checkout_step?(self.state)
|
|
184
|
+
checkout_step_index(state) > checkout_step_index(self.state)
|
|
185
|
+
end
|
|
134
186
|
end
|
|
135
187
|
end
|
|
136
188
|
end
|
|
@@ -38,6 +38,11 @@ module Spree
|
|
|
38
38
|
|
|
39
39
|
def attempt_cart_add(variant_id, quantity)
|
|
40
40
|
quantity = quantity.to_i
|
|
41
|
+
if quantity > Spree::Config[:max_quantity]
|
|
42
|
+
errors.add(:base, I18n.t(:please_enter_reasonable_quantity, :scope => :order_populator))
|
|
43
|
+
return false
|
|
44
|
+
end
|
|
45
|
+
|
|
41
46
|
variant = Spree::Variant.find(variant_id)
|
|
42
47
|
if quantity > 0
|
|
43
48
|
if check_stock_levels(variant, quantity)
|
|
@@ -55,12 +60,15 @@ module Spree
|
|
|
55
60
|
if on_hand >= quantity || Spree::Config[:allow_backorders]
|
|
56
61
|
return true
|
|
57
62
|
else
|
|
58
|
-
|
|
59
|
-
|
|
63
|
+
remainder_message = I18n.t(:remainder_message,
|
|
64
|
+
:item => display_name.inspect,
|
|
65
|
+
:on_hand => on_hand,
|
|
66
|
+
:scope => :order_populator)
|
|
67
|
+
errors.add(:base, remainder_message)
|
|
60
68
|
return false
|
|
61
69
|
end
|
|
62
70
|
else
|
|
63
|
-
errors.add(:base,
|
|
71
|
+
errors.add(:base, I18n.t(:out_of_stock, :item => display_name.inspect, :scope => :order_populator))
|
|
64
72
|
return false
|
|
65
73
|
end
|
|
66
74
|
end
|
|
@@ -34,11 +34,10 @@ module Spree
|
|
|
34
34
|
:total => order.total
|
|
35
35
|
})
|
|
36
36
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
order.payment.update_attributes_without_callbacks(:amount => order.total)
|
|
40
|
-
end
|
|
37
|
+
run_hooks
|
|
38
|
+
end
|
|
41
39
|
|
|
40
|
+
def run_hooks
|
|
42
41
|
update_hooks.each { |hook| order.send hook }
|
|
43
42
|
end
|
|
44
43
|
|
data/app/models/spree/payment.rb
CHANGED
|
@@ -14,6 +14,8 @@ module Spree
|
|
|
14
14
|
|
|
15
15
|
# update the order totals, etc.
|
|
16
16
|
after_save :update_order
|
|
17
|
+
# invalidate previously entered payments
|
|
18
|
+
after_create :invalidate_old_payments
|
|
17
19
|
|
|
18
20
|
attr_accessor :source_attributes
|
|
19
21
|
after_initialize :build_source
|
|
@@ -25,6 +27,15 @@ module Spree
|
|
|
25
27
|
scope :completed, with_state('completed')
|
|
26
28
|
scope :pending, with_state('pending')
|
|
27
29
|
scope :failed, with_state('failed')
|
|
30
|
+
scope :valid, where("state NOT IN (?)", %w(failed invalid))
|
|
31
|
+
|
|
32
|
+
after_rollback :persist_invalid
|
|
33
|
+
|
|
34
|
+
def persist_invalid
|
|
35
|
+
return unless ['failed', 'invalid'].include?(state)
|
|
36
|
+
state_will_change!
|
|
37
|
+
save
|
|
38
|
+
end
|
|
28
39
|
|
|
29
40
|
# order state machine (see http://github.com/pluginaweek/state_machine/tree/master for details)
|
|
30
41
|
state_machine :initial => 'checkout' do
|
|
@@ -47,15 +58,20 @@ module Spree
|
|
|
47
58
|
event :void do
|
|
48
59
|
transition :from => ['pending', 'completed', 'checkout'], :to => 'void'
|
|
49
60
|
end
|
|
61
|
+
# when the card brand isnt supported
|
|
62
|
+
event :invalidate do
|
|
63
|
+
transition :from => ['checkout'], :to => 'invalid'
|
|
64
|
+
end
|
|
50
65
|
end
|
|
51
66
|
|
|
52
67
|
def currency
|
|
53
68
|
order.currency
|
|
54
69
|
end
|
|
55
70
|
|
|
56
|
-
def
|
|
71
|
+
def money
|
|
57
72
|
Spree::Money.new(amount, { :currency => currency })
|
|
58
73
|
end
|
|
74
|
+
alias display_amount money
|
|
59
75
|
|
|
60
76
|
def offsets_total
|
|
61
77
|
offsets.pluck(:amount).sum
|
|
@@ -106,6 +122,12 @@ module Spree
|
|
|
106
122
|
gateway_error e
|
|
107
123
|
end
|
|
108
124
|
|
|
125
|
+
def invalidate_old_payments
|
|
126
|
+
order.payments.with_state('checkout').where("id != ?", self.id).each do |payment|
|
|
127
|
+
payment.invalidate!
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
|
|
109
131
|
def update_order
|
|
110
132
|
order.payments.reload
|
|
111
133
|
order.update!
|
|
@@ -5,10 +5,15 @@ module Spree
|
|
|
5
5
|
if payment_method && payment_method.source_required?
|
|
6
6
|
if source
|
|
7
7
|
if !processing?
|
|
8
|
-
if payment_method.
|
|
9
|
-
|
|
8
|
+
if payment_method.supports?(source)
|
|
9
|
+
if payment_method.auto_capture?
|
|
10
|
+
purchase!
|
|
11
|
+
else
|
|
12
|
+
authorize!
|
|
13
|
+
end
|
|
10
14
|
else
|
|
11
|
-
|
|
15
|
+
invalidate!
|
|
16
|
+
raise Core::GatewayError.new(I18n.t(:payment_method_not_supported))
|
|
12
17
|
end
|
|
13
18
|
end
|
|
14
19
|
else
|
|
@@ -39,7 +44,7 @@ module Spree
|
|
|
39
44
|
response = payment_method.capture(self, source, gateway_options)
|
|
40
45
|
else
|
|
41
46
|
# Standard ActiveMerchant capture usage
|
|
42
|
-
response = payment_method.capture(
|
|
47
|
+
response = payment_method.capture(money.money.cents,
|
|
43
48
|
response_code,
|
|
44
49
|
gateway_options)
|
|
45
50
|
end
|
|
@@ -111,7 +116,11 @@ module Spree
|
|
|
111
116
|
options = { :email => order.email,
|
|
112
117
|
:customer => order.email,
|
|
113
118
|
:ip => order.last_ip_address,
|
|
114
|
-
|
|
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 }
|
|
115
124
|
|
|
116
125
|
options.merge!({ :shipping => order.ship_total * 100,
|
|
117
126
|
:tax => order.tax_total * 100,
|
|
@@ -187,5 +196,9 @@ module Spree
|
|
|
187
196
|
raise Core::GatewayError.new(message)
|
|
188
197
|
end
|
|
189
198
|
|
|
199
|
+
# The unique identifier to be passed in to the payment gateway
|
|
200
|
+
def gateway_order_id
|
|
201
|
+
"#{order.number}-#{self.identifier}"
|
|
202
|
+
end
|
|
190
203
|
end
|
|
191
204
|
end
|