spree_core 2.0.3 → 2.0.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/assets/images/logo/spree_50.png +0 -0
- data/app/assets/images/noimage/large.png +0 -0
- data/app/assets/images/noimage/mini.png +0 -0
- data/app/assets/images/noimage/product.png +0 -0
- data/app/assets/images/noimage/small.png +0 -0
- data/app/controllers/spree/base_controller.rb +3 -0
- data/app/helpers/spree/base_helper.rb +15 -11
- data/app/models/spree/adjustment.rb +5 -0
- data/app/models/spree/app_configuration.rb +3 -3
- data/app/models/spree/calculator/default_tax.rb +2 -2
- data/app/models/spree/calculator/percent_per_item.rb +9 -5
- data/app/models/spree/calculator.rb +1 -1
- data/app/models/spree/credit_card.rb +25 -0
- data/app/models/spree/line_item.rb +9 -0
- data/app/models/spree/new_adjustment.rb +4 -0
- data/app/models/spree/order/checkout.rb +4 -5
- data/app/models/spree/order.rb +52 -25
- data/app/models/spree/order_contents.rb +8 -7
- data/app/models/spree/order_inventory.rb +13 -13
- data/app/models/spree/order_populator.rb +4 -14
- data/app/models/spree/order_updater.rb +1 -1
- data/app/models/spree/payment/processing.rb +5 -0
- data/app/models/spree/payment.rb +12 -1
- data/app/models/spree/payment_method.rb +1 -4
- data/app/models/spree/product.rb +44 -17
- data/app/models/spree/promotion/actions/create_adjustment.rb +1 -1
- data/app/models/spree/promotion/actions/create_line_items.rb +32 -2
- data/app/models/spree/promotion.rb +2 -1
- data/app/models/spree/shipment.rb +5 -5
- data/app/models/spree/shipping_adjustment.rb +4 -0
- data/app/models/spree/shipping_method.rb +6 -0
- data/app/models/spree/shipping_rate.rb +1 -0
- data/app/models/spree/stock/availability_validator.rb +5 -3
- data/app/models/spree/stock/coordinator.rb +16 -4
- data/app/models/spree/stock/estimator.rb +16 -6
- data/app/models/spree/stock/packer.rb +2 -1
- data/app/models/spree/stock_location.rb +16 -6
- data/app/models/spree/tax_category.rb +1 -7
- data/app/models/spree/tax_rate.rb +1 -0
- data/app/models/spree/variant.rb +16 -3
- data/app/models/spree/zone.rb +1 -1
- data/config/initializers/user_class_extensions.rb +1 -1
- data/config/locales/en.yml +15 -1
- data/db/migrate/20130228210442_create_shipping_method_zone.rb +6 -1
- data/db/migrate/20130306181701_add_address_fields_to_stock_location.rb +4 -1
- data/db/migrate/20130515180736_add_backorderable_default_to_spree_stock_location.rb +5 -0
- data/db/migrate/20130516151222_add_propage_all_variants_to_spree_stock_location.rb +5 -0
- data/db/migrate/20130626232741_add_cvv_result_code_and_cvv_result_message_to_spree_payments.rb +6 -0
- data/db/migrate/20130628021056_add_unique_index_to_permalink_on_spree_products.rb +5 -0
- data/db/migrate/20130628022817_add_unique_index_to_orders_shipments_and_stock_transfers.rb +7 -0
- data/db/migrate/20130708052307_add_deleted_at_to_spree_tax_rates.rb +5 -0
- data/db/migrate/20130711200933_remove_lock_version_from_inventory_units.rb +6 -0
- data/db/migrate/20130718042445_add_cost_price_to_line_item.rb +5 -0
- data/db/migrate/20130718233855_set_backorderable_to_default_to_false.rb +6 -0
- data/db/migrate/20130725031716_add_created_by_id_to_spree_orders.rb +5 -0
- data/db/migrate/20130729214043_index_completed_at_on_spree_orders.rb +5 -0
- data/db/migrate/20130802014537_add_tax_category_id_to_spree_line_items.rb +5 -0
- data/db/migrate/20130802022321_migrate_tax_categories_to_line_items.rb +9 -0
- data/db/migrate/20130805043440_create_spree_new_adjustments.rb +8 -0
- data/lib/generators/spree/dummy/templates/rails/database.yml +8 -7
- data/lib/generators/spree/install/install_generator.rb +1 -1
- data/lib/spree/core/calculated_adjustments.rb +12 -1
- data/lib/spree/core/controller_helpers/order.rb +5 -3
- data/lib/spree/core/controller_helpers/search.rb +14 -0
- data/lib/spree/core/permalinks.rb +13 -13
- data/lib/spree/core/s3_support.rb +1 -1
- data/lib/spree/core/version.rb +1 -1
- data/lib/spree/core.rb +7 -5
- data/lib/spree/i18n/base.rb +17 -0
- data/lib/spree/i18n/initializer.rb +1 -0
- data/lib/spree/i18n.rb +28 -7
- data/lib/spree/money.rb +2 -0
- data/lib/spree/testing_support/authorization_helpers.rb +6 -15
- data/lib/spree/testing_support/capybara_ext.rb +20 -11
- data/lib/spree/testing_support/common_rake.rb +13 -0
- data/lib/spree/testing_support/factories/country_factory.rb +1 -1
- data/lib/spree/testing_support/factories/order_factory.rb +0 -2
- data/lib/spree/testing_support/factories/payment_method_factory.rb +1 -1
- data/lib/spree/testing_support/factories/product_factory.rb +8 -18
- data/lib/spree/testing_support/factories/return_authorization_factory.rb +4 -0
- data/lib/spree/testing_support/factories/shipment_factory.rb +1 -1
- data/lib/spree/testing_support/factories/stock_item_factory.rb +2 -1
- data/lib/spree/testing_support/factories/stock_location_factory.rb +5 -2
- data/lib/spree/testing_support/factories/variant_factory.rb +1 -1
- data/lib/spree/testing_support/order_walkthrough.rb +14 -1
- data/vendor/assets/javascripts/jquery.validate/localization/messages_et.js +23 -0
- data/vendor/assets/javascripts/jquery.validate/localization/messages_eu.js +25 -0
- data/vendor/assets/javascripts/jquery.validate/localization/messages_hr.js +25 -0
- data/vendor/assets/javascripts/jquery.validate/localization/messages_ka.js +25 -0
- data/vendor/assets/javascripts/jquery.validate/localization/messages_ko.js +25 -0
- data/vendor/assets/javascripts/jquery.validate/localization/messages_my.js +25 -0
- data/vendor/assets/javascripts/jquery.validate/localization/messages_pt_BR.js +26 -0
- data/vendor/assets/javascripts/jquery.validate/localization/messages_pt_PT.js +26 -0
- data/vendor/assets/javascripts/jquery.validate/localization/messages_sl.js +25 -0
- data/vendor/assets/javascripts/jquery.validate/localization/messages_sv.js +23 -0
- data/vendor/assets/javascripts/jquery.validate/localization/messages_uk.js +25 -0
- data/vendor/assets/javascripts/jquery.validate/localization/messages_zh.js +25 -0
- data/vendor/assets/javascripts/jquery.validate/localization/messages_zh_TW.js +26 -0
- metadata +118 -67
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b435838b2a77628006e2e2885f5dbe2039958630
|
4
|
+
data.tar.gz: 1df2bcec2ac50c9d4716017752eb8c56ab2f9960
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1154f9c96163b14b0f85379e73718b6e5a95a6b60688399df8b724e109880d1e21deb4dbd77d44ae8dd29fe1cd98bd563d74c6ce191ac89eff57424dba437602
|
7
|
+
data.tar.gz: 5d008b1beae9dc20bf209bcc59063debee39ae36c6426569f970af0aad14b64287b61f9bed6454190e694ce96cb9b145be04b15066bc8abc80da9fb3c91c21fe
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
@@ -5,6 +5,9 @@ class Spree::BaseController < ApplicationController
|
|
5
5
|
include Spree::Core::ControllerHelpers::RespondWith
|
6
6
|
include Spree::Core::ControllerHelpers::SSL
|
7
7
|
include Spree::Core::ControllerHelpers::Common
|
8
|
+
include Spree::Core::ControllerHelpers::Search
|
8
9
|
|
9
10
|
respond_to :html
|
10
11
|
end
|
12
|
+
|
13
|
+
require 'spree/i18n/initializer'
|
@@ -165,13 +165,6 @@ module Spree
|
|
165
165
|
end
|
166
166
|
end
|
167
167
|
|
168
|
-
def t(*args)
|
169
|
-
puts "WARNING: Spree's translations are now scoped to a 'spree' namespace. Please use the Spree.t helper."
|
170
|
-
puts "Called from: #{caller[0]}"
|
171
|
-
I18n.t(*args)
|
172
|
-
end
|
173
|
-
|
174
|
-
|
175
168
|
private
|
176
169
|
|
177
170
|
# Returns style of image or nil
|
@@ -182,15 +175,26 @@ module Spree
|
|
182
175
|
end
|
183
176
|
end
|
184
177
|
|
178
|
+
def create_product_image_tag(image, product, options, style)
|
179
|
+
options.reverse_merge! alt: image.alt.blank? ? product.name : image.alt
|
180
|
+
image_tag image.attachment.url(style), options
|
181
|
+
end
|
182
|
+
|
185
183
|
def define_image_method(style)
|
186
184
|
self.class.send :define_method, "#{style}_image" do |product, *options|
|
187
185
|
options = options.first || {}
|
188
186
|
if product.images.empty?
|
189
|
-
|
187
|
+
if !product.is_a?(Spree::Variant) && !product.variant_images.empty?
|
188
|
+
create_product_image_tag(product.variant_images.first, product, options, style)
|
189
|
+
else
|
190
|
+
if product.is_a?(Variant) && !product.product.variant_images.empty?
|
191
|
+
create_product_image_tag(product.product.variant_images.first, product, options, style)
|
192
|
+
else
|
193
|
+
image_tag "noimage/#{style}.png", options
|
194
|
+
end
|
195
|
+
end
|
190
196
|
else
|
191
|
-
|
192
|
-
options.reverse_merge! alt: image.alt.blank? ? product.name : image.alt
|
193
|
-
image_tag image.attachment.url(style), options
|
197
|
+
create_product_image_tag(product.images.first, product, options, style)
|
194
198
|
end
|
195
199
|
end
|
196
200
|
end
|
@@ -58,6 +58,7 @@ module Spree
|
|
58
58
|
scope :charge, -> { where('amount >= 0') }
|
59
59
|
scope :credit, -> { where('amount < 0') }
|
60
60
|
scope :promotion, -> { where(originator_type: 'Spree::PromotionAction') }
|
61
|
+
scope :return_authorization, -> { where(source_type: "Spree::ReturnAuthorization") }
|
61
62
|
|
62
63
|
# Update the boolean _eligible_ attribute which determines which adjustments
|
63
64
|
# count towards the order's adjustment_total.
|
@@ -82,6 +83,10 @@ module Spree
|
|
82
83
|
# record from db for the association
|
83
84
|
def update!
|
84
85
|
return if immutable?
|
86
|
+
# Fix for #3381
|
87
|
+
# If we attempt to call 'source' before the reload, then source is currently
|
88
|
+
# the order object. After calling a reload, the source is the Shipment.
|
89
|
+
reload
|
85
90
|
originator.update_adjustment(self, source) if originator.present?
|
86
91
|
set_eligibility
|
87
92
|
end
|
@@ -22,7 +22,7 @@ module Spree
|
|
22
22
|
|
23
23
|
# Alphabetized to more easily lookup particular preferences
|
24
24
|
preference :address_requires_state, :boolean, default: true # should state/state_name be required
|
25
|
-
preference :admin_interface_logo, :string, default: '
|
25
|
+
preference :admin_interface_logo, :string, default: 'logo/spree_50.png'
|
26
26
|
preference :admin_products_per_page, :integer, default: 10
|
27
27
|
preference :allow_backorder_shipping, :boolean, default: false # should only be true if you don't need to track inventory
|
28
28
|
preference :allow_checkout_on_gateway_error, :boolean, default: false
|
@@ -51,7 +51,7 @@ module Spree
|
|
51
51
|
preference :hide_cents, :boolean, default: false
|
52
52
|
preference :last_check_for_spree_alerts, :string, default: nil
|
53
53
|
preference :layout, :string, default: 'spree/layouts/spree_application'
|
54
|
-
preference :logo, :string, default: '
|
54
|
+
preference :logo, :string, default: 'logo/spree_50.png'
|
55
55
|
preference :max_level_in_taxons_menu, :integer, default: 1 # maximum nesting level in taxons menu
|
56
56
|
preference :orders_per_page, :integer, default: 15
|
57
57
|
preference :prices_inc_tax, :boolean, default: false
|
@@ -68,7 +68,7 @@ module Spree
|
|
68
68
|
preference :site_name, :string, default: 'Spree Demo Site'
|
69
69
|
preference :site_url, :string, default: 'demo.spreecommerce.com'
|
70
70
|
preference :tax_using_ship_address, :boolean, default: true
|
71
|
-
preference :track_inventory_levels, :boolean, default: true #
|
71
|
+
preference :track_inventory_levels, :boolean, default: true # Determines whether to track on_hand values for variants / products.
|
72
72
|
|
73
73
|
# Preferences related to image settings
|
74
74
|
preference :attachment_default_url, :string, default: '/spree/products/:id/:style/:basename.:extension'
|
@@ -24,7 +24,7 @@ module Spree
|
|
24
24
|
|
25
25
|
def compute_order(order)
|
26
26
|
matched_line_items = order.line_items.select do |line_item|
|
27
|
-
line_item.
|
27
|
+
line_item.tax_category == rate.tax_category
|
28
28
|
end
|
29
29
|
|
30
30
|
line_items_total = matched_line_items.sum(&:total)
|
@@ -32,7 +32,7 @@ module Spree
|
|
32
32
|
end
|
33
33
|
|
34
34
|
def compute_line_item(line_item)
|
35
|
-
if line_item.
|
35
|
+
if line_item.tax_category == rate.tax_category
|
36
36
|
if rate.included_in_price
|
37
37
|
deduced_total_by_rate(line_item.total, rate)
|
38
38
|
else
|
@@ -1,10 +1,10 @@
|
|
1
1
|
module Spree
|
2
2
|
|
3
3
|
# A calculator for promotions that calculates a percent-off discount
|
4
|
-
# for all matching products in an order. This should not be used as a
|
4
|
+
# for all matching products in an order. This should not be used as a
|
5
5
|
# shipping calculator since it would be the same thing as a flat percent
|
6
6
|
# off the entire order.
|
7
|
-
|
7
|
+
|
8
8
|
class Calculator::PercentPerItem < Calculator
|
9
9
|
preference :percent, :decimal, :default => 0
|
10
10
|
|
@@ -23,10 +23,14 @@ module Spree
|
|
23
23
|
|
24
24
|
private
|
25
25
|
|
26
|
-
# Returns all products that match
|
26
|
+
# Returns all products that match this calculator, but only if the calculator
|
27
|
+
# is attached to a promotion. If attached to a ShippingMethod, nil is returned.
|
28
|
+
# Copied from per_item.rb
|
27
29
|
def matching_products
|
28
|
-
|
29
|
-
self.calculable.promotion.rules.map
|
30
|
+
if compute_on_promotion?
|
31
|
+
self.calculable.promotion.rules.map do |rule|
|
32
|
+
rule.respond_to?(:products) ? rule.products : []
|
33
|
+
end.flatten
|
30
34
|
end
|
31
35
|
end
|
32
36
|
|
@@ -10,6 +10,7 @@ module Spree
|
|
10
10
|
validates :month, :year, numericality: { only_integer: true }
|
11
11
|
validates :number, presence: true, unless: :has_payment_profile?, on: :create
|
12
12
|
validates :verification_value, presence: true, unless: :has_payment_profile?, on: :create
|
13
|
+
validate :expiry_not_in_the_past
|
13
14
|
|
14
15
|
attr_accessible :first_name, :last_name, :number, :verification_value, :year,
|
15
16
|
:month, :gateway_customer_profile_id, :gateway_payment_profile_id
|
@@ -30,6 +31,19 @@ module Spree
|
|
30
31
|
end
|
31
32
|
end
|
32
33
|
|
34
|
+
# Some payment gateways, such as USA EPay, only support an ActiveMerchant::Billing::CreditCard
|
35
|
+
# object, rather than an object *like* that. So we need to convert it.
|
36
|
+
def to_active_merchant
|
37
|
+
ActiveMerchant::Billing::CreditCard.new(
|
38
|
+
:number => number,
|
39
|
+
:month => month,
|
40
|
+
:year => year,
|
41
|
+
:verification_value => verification_value,
|
42
|
+
:first_name => first_name,
|
43
|
+
:last_name => last_name
|
44
|
+
)
|
45
|
+
end
|
46
|
+
|
33
47
|
# sets self.cc_type while we still have the card number
|
34
48
|
def set_card_type
|
35
49
|
self.cc_type ||= CardDetector.brand?(number)
|
@@ -87,5 +101,16 @@ module Spree
|
|
87
101
|
return 'visa' if Rails.env.development?
|
88
102
|
cc_type
|
89
103
|
end
|
104
|
+
|
105
|
+
private
|
106
|
+
|
107
|
+
def expiry_not_in_the_past
|
108
|
+
if year && month
|
109
|
+
time = "#{year}-#{month}-1".to_time
|
110
|
+
if time < Time.zone.now.beginning_of_month
|
111
|
+
errors.add(:base, :card_expired)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
90
115
|
end
|
91
116
|
end
|
@@ -3,11 +3,13 @@ module Spree
|
|
3
3
|
before_validation :adjust_quantity
|
4
4
|
belongs_to :order, class_name: "Spree::Order"
|
5
5
|
belongs_to :variant, class_name: "Spree::Variant"
|
6
|
+
belongs_to :tax_category, class_name: "Spree::TaxCategory"
|
6
7
|
|
7
8
|
has_one :product, through: :variant
|
8
9
|
has_many :adjustments, as: :adjustable, dependent: :destroy
|
9
10
|
|
10
11
|
before_validation :copy_price
|
12
|
+
before_validation :copy_tax_category
|
11
13
|
|
12
14
|
validates :variant, presence: true
|
13
15
|
validates :quantity, numericality: {
|
@@ -30,10 +32,17 @@ module Spree
|
|
30
32
|
def copy_price
|
31
33
|
if variant
|
32
34
|
self.price = variant.price if price.nil?
|
35
|
+
self.cost_price = variant.cost_price if cost_price.nil?
|
33
36
|
self.currency = variant.currency if currency.nil?
|
34
37
|
end
|
35
38
|
end
|
36
39
|
|
40
|
+
def copy_tax_category
|
41
|
+
if variant
|
42
|
+
self.tax_category = variant.product.tax_category
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
37
46
|
def increment_quantity
|
38
47
|
ActiveSupport::Deprecation.warn("[SPREE] Spree::LineItem#increment_quantity will be deprecated in Spree 2.1, please use quantity.increment! instead.")
|
39
48
|
self.quantity.increment!
|
@@ -63,15 +63,14 @@ module Spree
|
|
63
63
|
transition :to => :awaiting_return
|
64
64
|
end
|
65
65
|
|
66
|
+
|
66
67
|
before_transition :to => :complete do |order|
|
67
|
-
|
68
|
-
order.process_payments! if order.payment_required?
|
69
|
-
rescue Spree::Core::GatewayError
|
70
|
-
!!Spree::Config[:allow_checkout_on_gateway_error]
|
71
|
-
end
|
68
|
+
order.process_payments! if order.payment_required?
|
72
69
|
end
|
70
|
+
before_transition :from => :cart, :do => :ensure_line_items_present
|
73
71
|
|
74
72
|
before_transition :to => :delivery, :do => :create_proposed_shipments
|
73
|
+
before_transition :to => :delivery, :do => :ensure_available_shipping_rates
|
75
74
|
|
76
75
|
after_transition :to => :complete, :do => :finalize!
|
77
76
|
after_transition :to => :delivery, :do => :create_tax_charge!
|
data/app/models/spree/order.rb
CHANGED
@@ -20,9 +20,7 @@ module Spree
|
|
20
20
|
order.payment_required?
|
21
21
|
}
|
22
22
|
go_to_state :confirm, if: ->(order) { order.confirmation_required? }
|
23
|
-
go_to_state :complete
|
24
|
-
(order.payment_required? && order.has_unprocessed_payments?) || !order.payment_required?
|
25
|
-
}
|
23
|
+
go_to_state :complete
|
26
24
|
remove_transition from: :delivery, to: :confirm
|
27
25
|
end
|
28
26
|
|
@@ -30,16 +28,17 @@ module Spree
|
|
30
28
|
|
31
29
|
attr_accessible :line_items, :bill_address_attributes, :ship_address_attributes,
|
32
30
|
:payments_attributes, :ship_address, :bill_address, :currency,
|
33
|
-
:
|
34
|
-
:
|
35
|
-
:coupon_code
|
31
|
+
:line_items_attributes, :number, :email, :use_billing,
|
32
|
+
:special_instructions, :shipments_attributes, :coupon_code
|
36
33
|
|
37
34
|
attr_reader :coupon_code
|
38
35
|
|
39
36
|
if Spree.user_class
|
40
37
|
belongs_to :user, class_name: Spree.user_class.to_s
|
38
|
+
belongs_to :created_by, class_name: Spree.user_class.to_s
|
41
39
|
else
|
42
40
|
belongs_to :user
|
41
|
+
belongs_to :created_by
|
43
42
|
end
|
44
43
|
|
45
44
|
belongs_to :bill_address, foreign_key: :bill_address_id, class_name: 'Spree::Address'
|
@@ -49,17 +48,21 @@ module Spree
|
|
49
48
|
alias_attribute :shipping_address, :ship_address
|
50
49
|
|
51
50
|
has_many :state_changes, as: :stateful
|
52
|
-
has_many :line_items, dependent: :destroy, order:
|
53
|
-
has_many :payments, dependent: :destroy
|
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"
|
54
53
|
|
55
|
-
has_many :shipments, dependent: :destroy do
|
54
|
+
has_many :shipments, dependent: :destroy, :class_name => "Shipment" do
|
56
55
|
def states
|
57
56
|
pluck(:state).uniq
|
58
57
|
end
|
59
58
|
end
|
60
59
|
|
61
60
|
has_many :return_authorizations, dependent: :destroy
|
62
|
-
has_many :adjustments,
|
61
|
+
has_many :adjustments,
|
62
|
+
as: :adjustable,
|
63
|
+
dependent: :destroy,
|
64
|
+
order: "#{Spree::Adjustment.table_name}.created_at ASC",
|
65
|
+
inverse_of: :source
|
63
66
|
|
64
67
|
accepts_nested_attributes_for :line_items
|
65
68
|
accepts_nested_attributes_for :bill_address
|
@@ -175,13 +178,6 @@ module Spree
|
|
175
178
|
payments.map(&:payment_method).compact.any?(&:payment_profiles_supported?)
|
176
179
|
end
|
177
180
|
|
178
|
-
# Used by the checkout state machine to check for unprocessed payments
|
179
|
-
# The Order should be unable to proceed to complete if there are unprocessed
|
180
|
-
# payments and there is payment required.
|
181
|
-
def has_unprocessed_payments?
|
182
|
-
payments.with_state('checkout').reload.exists?
|
183
|
-
end
|
184
|
-
|
185
181
|
# Indicates the number of items in the order
|
186
182
|
def item_count
|
187
183
|
line_items.inject(0) { |sum, li| sum + li.quantity }
|
@@ -406,7 +402,7 @@ module Spree
|
|
406
402
|
|
407
403
|
# Helper methods for checkout steps
|
408
404
|
def paid?
|
409
|
-
payment_state == 'paid'
|
405
|
+
payment_state == 'paid' || payment_state == 'credit_owed'
|
410
406
|
end
|
411
407
|
|
412
408
|
def available_payment_methods
|
@@ -417,8 +413,23 @@ module Spree
|
|
417
413
|
payments.select(&:checkout?)
|
418
414
|
end
|
419
415
|
|
416
|
+
# processes any pending payments and must return a boolean as it's
|
417
|
+
# return value is used by the checkout state_machine to determine
|
418
|
+
# success or failure of the 'complete' event for the order
|
419
|
+
#
|
420
|
+
# Returns:
|
421
|
+
# - true if all pending_payments processed successfully
|
422
|
+
# - true if a payment failed, ie. raised a GatewayError
|
423
|
+
# which gets rescued and converted to TRUE when
|
424
|
+
# :allow_checkout_gateway_error is set to true
|
425
|
+
# - false if a payment failed, ie. raised a GatewayError
|
426
|
+
# which gets rescued and converted to FALSE when
|
427
|
+
# :allow_checkout_on_gateway_error is set to false
|
428
|
+
#
|
420
429
|
def process_payments!
|
421
|
-
|
430
|
+
if pending_payments.empty?
|
431
|
+
raise Core::GatewayError.new Spree.t(:no_pending_payments)
|
432
|
+
else
|
422
433
|
pending_payments.each do |payment|
|
423
434
|
break if payment_total >= total
|
424
435
|
|
@@ -428,9 +439,10 @@ module Spree
|
|
428
439
|
self.payment_total += payment.amount
|
429
440
|
end
|
430
441
|
end
|
431
|
-
rescue Core::GatewayError
|
432
|
-
!!Spree::Config[:allow_checkout_on_gateway_error]
|
433
442
|
end
|
443
|
+
rescue Core::GatewayError => e
|
444
|
+
result = !!Spree::Config[:allow_checkout_on_gateway_error]
|
445
|
+
errors.add(:base, e.message) and return result
|
434
446
|
end
|
435
447
|
|
436
448
|
def billing_firstname
|
@@ -504,10 +516,13 @@ module Spree
|
|
504
516
|
end
|
505
517
|
|
506
518
|
# Tells us if there if the specified promotion is already associated with the order
|
507
|
-
# regardless of whether or not its currently eligible.
|
508
|
-
# you would only want a promotion to apply to order no more than once.
|
509
|
-
|
510
|
-
|
519
|
+
# regardless of whether or not its currently eligible. Useful because generally
|
520
|
+
# you would only want a promotion action to apply to order no more than once.
|
521
|
+
#
|
522
|
+
# Receives an adjustment +originator+ (here a PromotionAction object) and tells
|
523
|
+
# if the order has adjustments from that already
|
524
|
+
def promotion_credit_exists?(originator)
|
525
|
+
!! adjustments.promotion.reload.detect { |credit| credit.originator.id == originator.id }
|
511
526
|
end
|
512
527
|
|
513
528
|
def promo_total
|
@@ -540,6 +555,12 @@ module Spree
|
|
540
555
|
return true unless new_record? or state == 'cart'
|
541
556
|
end
|
542
557
|
|
558
|
+
def ensure_line_items_present
|
559
|
+
unless line_items.present?
|
560
|
+
errors.add(:base, Spree.t(:there_are_no_items_for_this_order)) and return false
|
561
|
+
end
|
562
|
+
end
|
563
|
+
|
543
564
|
def has_available_shipment
|
544
565
|
return unless has_step?("delivery")
|
545
566
|
return unless address?
|
@@ -547,6 +568,12 @@ module Spree
|
|
547
568
|
# errors.add(:base, :no_shipping_methods_available) if available_shipping_methods.empty?
|
548
569
|
end
|
549
570
|
|
571
|
+
def ensure_available_shipping_rates
|
572
|
+
if shipments.empty? || shipments.any? { |shipment| shipment.shipping_rates.blank? }
|
573
|
+
errors.add(:base, Spree.t(:items_cannot_be_shipped)) and return false
|
574
|
+
end
|
575
|
+
end
|
576
|
+
|
550
577
|
def has_available_payment
|
551
578
|
return unless delivery?
|
552
579
|
# errors.add(:base, :no_payment_methods_available) if available_payment_methods.empty?
|
@@ -6,21 +6,22 @@ module Spree
|
|
6
6
|
@order = order
|
7
7
|
end
|
8
8
|
|
9
|
+
# Get current line item for variant if exists
|
10
|
+
# Add variant qty to line_item
|
9
11
|
def add(variant, quantity, currency=nil, shipment=nil)
|
10
|
-
#get current line item for variant if exists
|
11
12
|
line_item = order.find_line_item_by_variant(variant)
|
12
|
-
|
13
|
-
#add variant qty to line_item
|
14
13
|
add_to_line_item(line_item, variant, quantity, currency, shipment)
|
15
14
|
end
|
16
15
|
|
16
|
+
# Get current line item for variant
|
17
|
+
# Remove variant qty from line_item
|
17
18
|
def remove(variant, quantity, shipment=nil)
|
18
|
-
#get current line item for variant
|
19
19
|
line_item = order.find_line_item_by_variant(variant)
|
20
20
|
|
21
|
-
|
21
|
+
unless line_item
|
22
|
+
raise ActiveRecord::RecordNotFound, "Line item not found for variant #{variant.sku}"
|
23
|
+
end
|
22
24
|
|
23
|
-
#remove variant qty from line_item
|
24
25
|
remove_from_line_item(line_item, variant, quantity, shipment)
|
25
26
|
end
|
26
27
|
|
@@ -29,7 +30,7 @@ module Spree
|
|
29
30
|
def add_to_line_item(line_item, variant, quantity, currency=nil, shipment=nil)
|
30
31
|
if line_item
|
31
32
|
line_item.target_shipment = shipment
|
32
|
-
line_item.quantity += quantity
|
33
|
+
line_item.quantity += quantity.to_i
|
33
34
|
line_item.currency = currency unless currency.nil?
|
34
35
|
line_item.save
|
35
36
|
else
|
@@ -6,10 +6,13 @@ module Spree
|
|
6
6
|
@order = order
|
7
7
|
end
|
8
8
|
|
9
|
-
# Only verify inventory for completed orders
|
10
|
-
#
|
9
|
+
# Only verify inventory for completed orders (as orders in frontend checkout
|
10
|
+
# have inventory assigned via +order.create_proposed_shipment+) or when
|
11
|
+
# shipment is explicitly passed
|
11
12
|
#
|
12
|
-
#
|
13
|
+
# In case shipment is passed the stock location should only unstock or
|
14
|
+
# restock items if the order is completed. That is so because stock items
|
15
|
+
# are always unstocked when the order is completed through +shipment.finalize+
|
13
16
|
def verify(line_item, shipment = nil)
|
14
17
|
if order.completed? || shipment.present?
|
15
18
|
|
@@ -51,7 +54,6 @@ module Spree
|
|
51
54
|
#
|
52
55
|
# first unshipped that already includes this variant
|
53
56
|
# first unshipped that's leaving from a stock_location that stocks this variant
|
54
|
-
#
|
55
57
|
def determine_target_shipment(variant)
|
56
58
|
shipment = order.shipments.detect do |shipment|
|
57
59
|
(shipment.ready? || shipment.pending?) && shipment.include?(variant)
|
@@ -63,7 +65,6 @@ module Spree
|
|
63
65
|
end
|
64
66
|
|
65
67
|
def add_to_shipment(shipment, variant, quantity)
|
66
|
-
#create inventory_units
|
67
68
|
on_hand, back_order = shipment.stock_location.fill_status(variant, quantity)
|
68
69
|
|
69
70
|
on_hand.times do
|
@@ -76,11 +77,11 @@ module Spree
|
|
76
77
|
state: 'backordered'}, without_protection: true)
|
77
78
|
end
|
78
79
|
|
79
|
-
|
80
80
|
# adding to this shipment, and removing from stock_location
|
81
|
-
|
81
|
+
if order.completed?
|
82
|
+
shipment.stock_location.unstock(variant, quantity, shipment)
|
83
|
+
end
|
82
84
|
|
83
|
-
# return quantity added
|
84
85
|
quantity
|
85
86
|
end
|
86
87
|
|
@@ -99,14 +100,13 @@ module Spree
|
|
99
100
|
removed_quantity += 1
|
100
101
|
end
|
101
102
|
|
102
|
-
if shipment.inventory_units.count == 0
|
103
|
-
shipment.destroy
|
104
|
-
end
|
103
|
+
shipment.destroy if shipment.inventory_units.count == 0
|
105
104
|
|
106
105
|
# removing this from shipment, and adding to stock_location
|
107
|
-
|
106
|
+
if order.completed?
|
107
|
+
shipment.stock_location.restock variant, removed_quantity, shipment
|
108
|
+
end
|
108
109
|
|
109
|
-
# return quantity removed
|
110
110
|
removed_quantity
|
111
111
|
end
|
112
112
|
end
|
@@ -46,22 +46,12 @@ module Spree
|
|
46
46
|
|
47
47
|
variant = Spree::Variant.find(variant_id)
|
48
48
|
if quantity > 0
|
49
|
-
|
50
|
-
|
49
|
+
line_item = @order.contents.add(variant, quantity, currency)
|
50
|
+
unless line_item.valid?
|
51
|
+
errors.add(:base, line_item.errors.messages.values.join(" "))
|
52
|
+
return false
|
51
53
|
end
|
52
54
|
end
|
53
55
|
end
|
54
|
-
|
55
|
-
def check_stock_levels(variant, quantity)
|
56
|
-
display_name = %Q{#{variant.name}}
|
57
|
-
display_name += %Q{ (#{variant.options_text})} unless variant.options_text.blank?
|
58
|
-
|
59
|
-
if Stock::Quantifier.new(variant).can_supply? quantity
|
60
|
-
true
|
61
|
-
else
|
62
|
-
errors.add(:base, Spree.t(:out_of_stock, :scope => :order_populator, :item => display_name.inspect))
|
63
|
-
return false
|
64
|
-
end
|
65
|
-
end
|
66
56
|
end
|
67
57
|
end
|
@@ -131,7 +131,7 @@ module Spree
|
|
131
131
|
# This promotion provides the most discount, and if two promotions
|
132
132
|
# have the same amount, then it will pick the latest one.
|
133
133
|
def choose_best_promotion_adjustment
|
134
|
-
if best_promotion_adjustment = order.adjustments.promotion.reorder("amount ASC, created_at DESC").first
|
134
|
+
if best_promotion_adjustment = order.adjustments.promotion.eligible.reorder("amount ASC, created_at DESC").first
|
135
135
|
other_promotions = order.adjustments.promotion.where("id NOT IN (?)", best_promotion_adjustment.id)
|
136
136
|
other_promotions.update_all(eligible: false)
|
137
137
|
end
|
@@ -154,6 +154,11 @@ module Spree
|
|
154
154
|
unless response.authorization.nil?
|
155
155
|
self.response_code = response.authorization
|
156
156
|
self.avs_response = response.avs_result['code']
|
157
|
+
|
158
|
+
if response.cvv_result
|
159
|
+
self.cvv_response_code = response.cvv_result['code']
|
160
|
+
self.cvv_response_message = response.cvv_result['message']
|
161
|
+
end
|
157
162
|
end
|
158
163
|
self.send("#{success_state}!")
|
159
164
|
else
|
data/app/models/spree/payment.rb
CHANGED
@@ -2,12 +2,13 @@ module Spree
|
|
2
2
|
class Payment < ActiveRecord::Base
|
3
3
|
include Spree::Payment::Processing
|
4
4
|
belongs_to :order, class_name: 'Spree::Order'
|
5
|
-
belongs_to :source, polymorphic: true
|
5
|
+
belongs_to :source, polymorphic: true
|
6
6
|
belongs_to :payment_method, class_name: 'Spree::PaymentMethod'
|
7
7
|
|
8
8
|
has_many :offsets, class_name: "Spree::Payment", foreign_key: :source_id, conditions: "source_type = 'Spree::Payment' AND amount < 0 AND state = 'completed'"
|
9
9
|
has_many :log_entries, as: :source
|
10
10
|
|
11
|
+
before_validation :validate_source
|
11
12
|
before_save :set_unique_identifier
|
12
13
|
|
13
14
|
after_save :create_payment_profile, if: :profiles_supported?
|
@@ -105,6 +106,16 @@ module Spree
|
|
105
106
|
|
106
107
|
private
|
107
108
|
|
109
|
+
def validate_source
|
110
|
+
if source && !source.valid?
|
111
|
+
source.errors.each do |field, error|
|
112
|
+
field_name = I18n.t("activerecord.attributes.#{source.class.to_s.underscore}.#{field}")
|
113
|
+
self.errors.add(Spree.t(source.class.to_s.demodulize.underscore), "#{field_name} #{error}")
|
114
|
+
end
|
115
|
+
end
|
116
|
+
return !errors.present?
|
117
|
+
end
|
118
|
+
|
108
119
|
def profiles_supported?
|
109
120
|
payment_method.respond_to?(:payment_profiles_supported?) && payment_method.payment_profiles_supported?
|
110
121
|
end
|
@@ -1,5 +1,6 @@
|
|
1
1
|
module Spree
|
2
2
|
class PaymentMethod < ActiveRecord::Base
|
3
|
+
acts_as_paranoid
|
3
4
|
DISPLAY = [:both, :front_end, :back_end]
|
4
5
|
default_scope where(deleted_at: nil)
|
5
6
|
|
@@ -39,10 +40,6 @@ module Spree
|
|
39
40
|
type.demodulize.downcase
|
40
41
|
end
|
41
42
|
|
42
|
-
def destroy
|
43
|
-
touch :deleted_at
|
44
|
-
end
|
45
|
-
|
46
43
|
def self.find_with_destroyed *args
|
47
44
|
self.with_exclusive_scope { find(*args) }
|
48
45
|
end
|