spree_core 2.0.3 → 2.0.4
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 +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
|