solidus_core 2.2.2 → 2.3.0.beta1
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/README.md +4 -7
- data/app/assets/javascripts/spree.js.erb +2 -2
- data/app/helpers/spree/base_helper.rb +3 -4
- data/app/models/spree/address.rb +1 -1
- data/app/models/spree/adjustment.rb +3 -1
- data/app/models/spree/app_configuration.rb +43 -0
- data/app/models/spree/billing_integration.rb +2 -2
- data/app/models/spree/calculator/default_tax.rb +3 -1
- data/app/models/spree/calculator/distributed_amount.rb +24 -0
- data/app/models/spree/calculator/free_shipping.rb +0 -1
- data/app/models/spree/calculator/tiered_flat_rate.rb +17 -3
- data/app/models/spree/calculator/tiered_percent.rb +18 -3
- data/app/models/spree/distributed_amounts_handler.rb +43 -0
- data/app/models/spree/gateway/bogus.rb +7 -83
- data/app/models/spree/gateway/bogus_simple.rb +7 -20
- data/app/models/spree/gateway.rb +8 -58
- data/app/models/spree/image.rb +1 -1
- data/app/models/spree/line_item.rb +1 -1
- data/app/models/spree/option_value.rb +1 -1
- data/app/models/spree/order/checkout.rb +1 -4
- data/app/models/spree/order/number_generator.rb +43 -0
- data/app/models/spree/order.rb +33 -38
- data/app/models/spree/order_contents.rb +1 -1
- data/app/models/spree/order_taxation.rb +79 -0
- data/app/models/spree/order_update_attributes.rb +0 -2
- data/app/models/spree/order_updater.rb +55 -33
- data/app/models/spree/payment.rb +0 -1
- data/app/models/spree/payment_method/bogus_credit_card.rb +87 -0
- data/app/models/spree/payment_method/check.rb +14 -6
- data/app/models/spree/payment_method/credit_card.rb +41 -0
- data/app/models/spree/payment_method/simple_bogus_credit_card.rb +24 -0
- data/app/models/spree/payment_method/store_credit.rb +5 -13
- data/app/models/spree/payment_method.rb +126 -40
- data/app/models/spree/preferences/preferable.rb +5 -1
- data/app/models/spree/preferences/store.rb +2 -2
- data/app/models/spree/product/scopes.rb +14 -1
- data/app/models/spree/product.rb +10 -4
- data/app/models/spree/promotion_action.rb +4 -0
- data/app/models/spree/promotion_code/batch_builder.rb +3 -2
- data/app/models/spree/promotion_rule.rb +4 -0
- data/app/models/spree/role.rb +2 -0
- data/app/models/spree/role_user.rb +2 -0
- data/app/models/spree/shipment.rb +4 -2
- data/app/models/spree/shipping_method.rb +3 -1
- data/app/models/spree/shipping_rate.rb +1 -1
- data/app/models/spree/state.rb +10 -2
- data/app/models/spree/stock_item.rb +3 -3
- data/app/models/spree/store.rb +5 -0
- data/app/models/spree/store_credit.rb +2 -2
- data/app/models/spree/store_credit_event.rb +1 -1
- data/app/models/spree/store_selector/by_server_name.rb +30 -0
- data/app/models/spree/store_selector/legacy.rb +48 -0
- data/app/models/spree/tax/item_tax.rb +20 -0
- data/app/models/spree/tax/order_adjuster.rb +2 -14
- data/app/models/spree/tax/order_tax.rb +18 -0
- data/app/models/spree/tax/shipping_rate_taxer.rb +4 -13
- data/app/models/spree/tax/tax_helpers.rb +5 -3
- data/app/models/spree/tax_calculator/default.rb +83 -0
- data/app/models/spree/tax_calculator/shipping_rate.rb +46 -0
- data/app/models/spree/tax_category.rb +9 -1
- data/app/models/spree/tax_rate.rb +31 -7
- data/app/models/spree/tax_rate_tax_category.rb +6 -0
- data/app/models/spree/taxon.rb +1 -1
- data/app/models/spree/variant.rb +1 -1
- data/app/views/spree/{shipment_mailer → carton_mailer}/shipped_email.html.erb +3 -3
- data/app/views/spree/order_mailer/cancel_email.html.erb +3 -3
- data/app/views/spree/order_mailer/confirm_email.html.erb +2 -2
- data/app/views/spree/order_mailer/inventory_cancellation_email.html.erb +26 -0
- data/app/views/spree/reimbursement_mailer/reimbursement_email.html.erb +2 -2
- data/app/views/spree/test_mailer/test_email.html.erb +2 -2
- data/config/locales/en.yml +66 -57
- data/db/default/spree/refund_reasons.rb +1 -0
- data/db/default/spree/shipping_categories.rb +1 -0
- data/db/default/spree/stock_locations.rb +2 -0
- data/db/default/spree/stores.rb +3 -4
- data/db/migrate/20170412103617_transform_tax_rate_category_relation.rb +48 -0
- data/db/migrate/20170422134804_add_roles_unique_constraints.rb +6 -0
- data/db/migrate/20170522143442_add_time_range_to_tax_rate.rb +6 -0
- data/db/migrate/20170608074534_rename_bogus_gateways.rb +13 -0
- data/lib/generators/spree/custom_user/custom_user_generator.rb +1 -1
- data/lib/generators/spree/dummy/dummy_generator.rb +10 -4
- data/lib/generators/spree/dummy/templates/rails/database.yml +12 -12
- data/lib/generators/spree/install/install_generator.rb +5 -5
- data/lib/generators/spree/install/templates/config/initializers/{spree.rb → solidus.rb} +0 -0
- data/lib/solidus/migrations/rename_gateways.rb +39 -0
- data/lib/spree/core/controller_helpers/auth.rb +1 -1
- data/lib/spree/core/controller_helpers/order.rb +10 -5
- data/lib/spree/core/controller_helpers/store.rb +1 -9
- data/lib/spree/core/current_store.rb +6 -14
- data/lib/spree/core/engine.rb +4 -3
- data/lib/spree/core/importer/order.rb +4 -4
- data/lib/spree/core/version.rb +1 -1
- data/lib/spree/core.rb +0 -1
- data/lib/spree/localized_number.rb +2 -1
- data/lib/spree/permitted_attributes.rb +12 -6
- data/lib/spree/testing_support/capybara_ext.rb +0 -1
- data/lib/spree/testing_support/factories/adjustment_factory.rb +5 -1
- data/lib/spree/testing_support/factories/order_factory.rb +26 -24
- data/lib/spree/testing_support/factories/payment_factory.rb +4 -0
- data/lib/spree/testing_support/factories/payment_method_factory.rb +3 -3
- data/lib/spree/testing_support/factories/shipment_factory.rb +7 -3
- data/lib/spree/testing_support/factories/tax_rate_factory.rb +1 -1
- data/lib/spree/testing_support/factories/variant_factory.rb +3 -1
- data/lib/tasks/migrations/copy_order_bill_address_to_credit_card.rake +0 -4
- data/lib/tasks/migrations/migrate_user_addresses.rake +2 -2
- data/lib/tasks/migrations/rename_gateways.rake +19 -0
- data/solidus_core.gemspec +2 -3
- data/spec/lib/spree/core/controller_helpers/order_spec.rb +32 -6
- data/spec/lib/spree/core/controller_helpers/payment_parameters_spec.rb +0 -1
- data/spec/lib/spree/core/current_store_spec.rb +6 -11
- data/spec/lib/spree/core/price_migrator_spec.rb +4 -4
- data/spec/lib/spree/core/testing_support/factories/order_factory_spec.rb +199 -91
- data/spec/lib/spree/core/testing_support/factories/variant_factory_spec.rb +18 -0
- data/spec/lib/spree/localized_number_spec.rb +6 -0
- data/spec/mailers/carton_mailer_spec.rb +3 -3
- data/spec/models/spree/address_spec.rb +3 -3
- data/spec/models/spree/adjustment_spec.rb +71 -27
- data/spec/models/spree/calculator/default_tax_spec.rb +72 -1
- data/spec/models/spree/calculator/distributed_amount_spec.rb +32 -0
- data/spec/models/spree/calculator/tiered_flat_rate_spec.rb +20 -1
- data/spec/models/spree/calculator/tiered_percent_spec.rb +20 -1
- data/spec/models/spree/distributed_amounts_handler_spec.rb +79 -0
- data/spec/models/spree/gateway/bogus_simple.rb +7 -13
- data/spec/models/spree/gateway/bogus_spec.rb +8 -4
- data/spec/models/spree/gateway_spec.rb +6 -105
- data/spec/models/spree/image_spec.rb +23 -0
- data/spec/models/spree/order/checkout_spec.rb +3 -18
- data/spec/models/spree/order/number_generator_spec.rb +45 -0
- data/spec/models/spree/order/outstanding_balance_integration_spec.rb +135 -0
- data/spec/models/spree/order/payment_spec.rb +7 -2
- data/spec/models/spree/order/state_machine_spec.rb +4 -2
- data/spec/models/spree/order_capturing_spec.rb +8 -8
- data/spec/models/spree/order_contents_spec.rb +8 -1
- data/spec/models/spree/order_shipping_spec.rb +5 -1
- data/spec/models/spree/order_spec.rb +156 -83
- data/spec/models/spree/order_taxation_spec.rb +126 -0
- data/spec/models/spree/order_update_attributes_spec.rb +1 -5
- data/spec/models/spree/order_updater_spec.rb +20 -21
- data/spec/models/spree/payment_create_spec.rb +14 -6
- data/spec/models/spree/payment_method/bogus_credit_card_spec.rb +8 -0
- data/spec/models/spree/payment_method/check_spec.rb +78 -0
- data/spec/models/spree/payment_method/credit_card_spec.rb +66 -0
- data/spec/models/spree/payment_method/simple_bogus_credit_card_spec.rb +18 -0
- data/spec/models/spree/payment_method_spec.rb +47 -2
- data/spec/models/spree/payment_spec.rb +6 -8
- data/spec/models/spree/preference_spec.rb +1 -1
- data/spec/models/spree/price_spec.rb +1 -1
- data/spec/models/spree/product/scopes_spec.rb +46 -0
- data/spec/models/spree/promotion_action_spec.rb +4 -0
- data/spec/models/spree/promotion_code/batch_builder_spec.rb +25 -3
- data/spec/models/spree/promotion_code_batch_spec.rb +0 -6
- data/spec/models/spree/promotion_handler/coupon_spec.rb +1 -1
- data/spec/models/spree/promotion_rule_spec.rb +5 -0
- data/spec/models/spree/reimbursement_type/original_payment_spec.rb +1 -1
- data/spec/models/spree/shipment_spec.rb +24 -3
- data/spec/models/spree/shipping_rate_spec.rb +5 -5
- data/spec/models/spree/state_spec.rb +31 -4
- data/spec/models/spree/stock/coordinator_spec.rb +24 -0
- data/spec/models/spree/stock/estimator_spec.rb +1 -1
- data/spec/models/spree/store_selector/by_server_name_spec.rb +26 -0
- data/spec/models/spree/store_selector/legacy_spec.rb +44 -0
- data/spec/models/spree/store_spec.rb +10 -2
- data/spec/models/spree/tax/order_adjuster_spec.rb +11 -21
- data/spec/models/spree/tax/shipping_rate_taxer_spec.rb +10 -3
- data/spec/models/spree/tax/taxation_integration_spec.rb +43 -8
- data/spec/models/spree/tax_calculator/default_spec.rb +54 -0
- data/spec/models/spree/tax_rate_spec.rb +92 -0
- data/spec/models/spree/variant/vat_price_generator_spec.rb +4 -4
- data/spec/models/spree/variant_spec.rb +8 -2
- data/spec/spec_helper.rb +2 -1
- data/spec/support/test_gateway.rb +1 -1
- metadata +45 -24
- data/app/models/spree/tax/item_adjuster.rb +0 -51
- data/spec/models/spree/tax/item_adjuster_spec.rb +0 -82
|
@@ -1,12 +1,23 @@
|
|
|
1
1
|
module Spree
|
|
2
|
-
#
|
|
2
|
+
# A base class which is used for implementing payment methods.
|
|
3
|
+
#
|
|
4
|
+
# See https://github.com/solidusio/solidus_gateway/ for
|
|
5
|
+
# offically supported payment method implementations.
|
|
6
|
+
#
|
|
7
|
+
# Uses STI (single table inheritance) to store all implemented payment methods
|
|
8
|
+
# in one table (+spree_payment_methods+).
|
|
9
|
+
#
|
|
10
|
+
# This class is not meant to be instantiated. Please create instances of concrete payment methods.
|
|
3
11
|
#
|
|
4
12
|
class PaymentMethod < Spree::Base
|
|
13
|
+
preference :server, :string, default: 'test'
|
|
14
|
+
preference :test_mode, :boolean, default: true
|
|
15
|
+
|
|
5
16
|
acts_as_paranoid
|
|
6
17
|
acts_as_list
|
|
7
18
|
DISPLAY = [:both, :front_end, :back_end]
|
|
8
19
|
|
|
9
|
-
validates :name, presence: true
|
|
20
|
+
validates :name, :type, presence: true
|
|
10
21
|
|
|
11
22
|
has_many :payments, class_name: "Spree::Payment", inverse_of: :payment_method
|
|
12
23
|
has_many :credit_cards, class_name: "Spree::CreditCard"
|
|
@@ -22,19 +33,85 @@ module Spree
|
|
|
22
33
|
store.payment_methods.empty? ? all : where(id: store.payment_method_ids)
|
|
23
34
|
end
|
|
24
35
|
|
|
36
|
+
delegate :authorize, :purchase, :capture, :void, :credit, to: :gateway
|
|
37
|
+
|
|
25
38
|
include Spree::Preferences::StaticallyConfigurable
|
|
26
39
|
|
|
27
|
-
|
|
28
|
-
|
|
40
|
+
class << self
|
|
41
|
+
def providers
|
|
42
|
+
Spree::Deprecation.warn 'Spree::PaymentMethod.providers is deprecated and will be deleted in Solidus 3.0. ' \
|
|
43
|
+
'Please use Rails.application.config.spree.payment_methods instead'
|
|
44
|
+
Rails.application.config.spree.payment_methods
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def available(display_on = nil, store: nil)
|
|
48
|
+
Spree::Deprecation.warn "Spree::PaymentMethod.available is deprecated."\
|
|
49
|
+
"Please use .active, .available_to_users, and .available_to_admin scopes instead."\
|
|
50
|
+
"For payment methods associated with a specific store, use Spree::PaymentMethod.available_to_store(your_store)"\
|
|
51
|
+
" as the base applying any further filtering"
|
|
52
|
+
|
|
53
|
+
display_on = display_on.to_s
|
|
54
|
+
|
|
55
|
+
available_payment_methods =
|
|
56
|
+
case display_on
|
|
57
|
+
when 'front_end'
|
|
58
|
+
active.available_to_users
|
|
59
|
+
when 'back_end'
|
|
60
|
+
active.available_to_admin
|
|
61
|
+
else
|
|
62
|
+
active.available_to_users.available_to_admin
|
|
63
|
+
end
|
|
64
|
+
available_payment_methods.select do |p|
|
|
65
|
+
store.nil? || store.payment_methods.empty? || store.payment_methods.include?(p)
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def active?
|
|
70
|
+
where(type: to_s, active: true).count > 0
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def find_with_destroyed(*args)
|
|
74
|
+
unscoped { find(*args) }
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# Represents the gateway of this payment method
|
|
79
|
+
#
|
|
80
|
+
# The gateway is responsible for communicating with the providers API.
|
|
81
|
+
#
|
|
82
|
+
# It implements methods for:
|
|
83
|
+
#
|
|
84
|
+
# - authorize
|
|
85
|
+
# - purchase
|
|
86
|
+
# - capture
|
|
87
|
+
# - void
|
|
88
|
+
# - credit
|
|
89
|
+
#
|
|
90
|
+
def gateway
|
|
91
|
+
gateway_options = options
|
|
92
|
+
gateway_options.delete :login if gateway_options.key?(:login) && gateway_options[:login].nil?
|
|
93
|
+
if gateway_options[:server]
|
|
94
|
+
ActiveMerchant::Billing::Base.mode = gateway_options[:server].to_sym
|
|
95
|
+
end
|
|
96
|
+
@gateway ||= gateway_class.new(gateway_options)
|
|
29
97
|
end
|
|
98
|
+
alias_method :provider, :gateway
|
|
99
|
+
deprecate provider: :gateway, deprecator: Spree::Deprecation
|
|
30
100
|
|
|
31
|
-
|
|
32
|
-
|
|
101
|
+
# Represents all preferences as a Hash
|
|
102
|
+
#
|
|
103
|
+
# Each preference is a key holding the value(s) and gets passed to the gateway via +gateway_options+
|
|
104
|
+
#
|
|
105
|
+
# @return Hash
|
|
106
|
+
def options
|
|
107
|
+
preferences.to_hash
|
|
33
108
|
end
|
|
34
109
|
|
|
35
|
-
# The class that will
|
|
36
|
-
#
|
|
37
|
-
#
|
|
110
|
+
# The class that will store payment sources (re)usable with this payment method
|
|
111
|
+
#
|
|
112
|
+
# Used by Spree::Payment as source (e.g. Spree::CreditCard in the case of a credit card payment method).
|
|
113
|
+
#
|
|
114
|
+
# Returning nil means the payment method doesn't support storing sources (e.g. Spree::PaymentMethod::Check)
|
|
38
115
|
def payment_source_class
|
|
39
116
|
raise ::NotImplementedError, "You must implement payment_source_class method for #{self.class}."
|
|
40
117
|
end
|
|
@@ -62,39 +139,27 @@ module Spree
|
|
|
62
139
|
end
|
|
63
140
|
end
|
|
64
141
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
available_payment_methods.select do |p|
|
|
83
|
-
store.nil? || store.payment_methods.empty? || store.payment_methods.include?(p)
|
|
84
|
-
end
|
|
85
|
-
end
|
|
86
|
-
|
|
87
|
-
def self.active?
|
|
88
|
-
where(type: to_s, active: true).count > 0
|
|
89
|
-
end
|
|
90
|
-
|
|
91
|
-
def method_type
|
|
142
|
+
# Used as partial name for your payment method
|
|
143
|
+
#
|
|
144
|
+
# Currently your payment method needs to provide these partials:
|
|
145
|
+
#
|
|
146
|
+
# 1. app/views/spree/checkout/payment/_{partial_name}.html.erb
|
|
147
|
+
# The form your customer enters the payment information in during checkout
|
|
148
|
+
#
|
|
149
|
+
# 2. app/views/spree/checkout/existing_payment/_{partial_name}.html.erb
|
|
150
|
+
# The payment information of your customers reusable sources during checkout
|
|
151
|
+
#
|
|
152
|
+
# 3. app/views/spree/admin/payments/source_forms/_{partial_name}.html.erb
|
|
153
|
+
# The form an admin enters payment information in when creating orders in the backend
|
|
154
|
+
#
|
|
155
|
+
# 4. app/views/spree/admin/payments/source_views/_{partial_name}.html.erb
|
|
156
|
+
# The view that represents your payment method on orders in the backend
|
|
157
|
+
#
|
|
158
|
+
def partial_name
|
|
92
159
|
type.demodulize.downcase
|
|
93
160
|
end
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
unscoped { find(*args) }
|
|
97
|
-
end
|
|
161
|
+
alias_method :method_type, :partial_name
|
|
162
|
+
deprecate method_type: :partial_name, deprecator: Spree::Deprecation
|
|
98
163
|
|
|
99
164
|
def payment_profiles_supported?
|
|
100
165
|
false
|
|
@@ -114,6 +179,11 @@ module Spree
|
|
|
114
179
|
auto_capture.nil? ? Spree::Config[:auto_capture] : auto_capture
|
|
115
180
|
end
|
|
116
181
|
|
|
182
|
+
# Check if given source is supported by this payment method
|
|
183
|
+
#
|
|
184
|
+
# Please implement validation logic in your payment method implementation
|
|
185
|
+
#
|
|
186
|
+
# @see Spree::PaymentMethod::CreditCard#supports?
|
|
117
187
|
def supports?(_source)
|
|
118
188
|
true
|
|
119
189
|
end
|
|
@@ -125,5 +195,21 @@ module Spree
|
|
|
125
195
|
def store_credit?
|
|
126
196
|
is_a? Spree::PaymentMethod::StoreCredit
|
|
127
197
|
end
|
|
198
|
+
|
|
199
|
+
protected
|
|
200
|
+
|
|
201
|
+
# Represents the gateway class of this payment method
|
|
202
|
+
#
|
|
203
|
+
def gateway_class
|
|
204
|
+
if respond_to? :provider_class
|
|
205
|
+
Spree::Deprecation.warn \
|
|
206
|
+
"provider_class is deprecated and will be removed from Solidus 3.0 " \
|
|
207
|
+
"(use gateway_class instead)"
|
|
208
|
+
public_send :provider_class
|
|
209
|
+
else
|
|
210
|
+
raise ::NotImplementedError, "You must implement gateway_class method for #{self.class}."
|
|
211
|
+
end
|
|
212
|
+
end
|
|
213
|
+
deprecate provider_class: :gateway_class, deprecator: Spree::Deprecation
|
|
128
214
|
end
|
|
129
215
|
end
|
|
@@ -104,7 +104,11 @@ module Spree::Preferences::Preferable
|
|
|
104
104
|
when :password
|
|
105
105
|
value.to_s
|
|
106
106
|
when :decimal
|
|
107
|
-
|
|
107
|
+
begin
|
|
108
|
+
value.to_s.to_d
|
|
109
|
+
rescue ArgumentError
|
|
110
|
+
BigDecimal.new(0)
|
|
111
|
+
end
|
|
108
112
|
when :integer
|
|
109
113
|
value.to_i
|
|
110
114
|
when :boolean
|
|
@@ -33,7 +33,7 @@ module Spree::Preferences
|
|
|
33
33
|
# has been cleared from the cache
|
|
34
34
|
|
|
35
35
|
# does it exist in the database?
|
|
36
|
-
if preference = Spree::Preference.
|
|
36
|
+
if preference = Spree::Preference.find_by(key: key)
|
|
37
37
|
# it does exist
|
|
38
38
|
val = preference.value
|
|
39
39
|
else
|
|
@@ -74,7 +74,7 @@ module Spree::Preferences
|
|
|
74
74
|
def destroy(cache_key)
|
|
75
75
|
return unless should_persist?
|
|
76
76
|
|
|
77
|
-
preference = Spree::Preference.
|
|
77
|
+
preference = Spree::Preference.find_by(key: cache_key)
|
|
78
78
|
preference.destroy if preference
|
|
79
79
|
end
|
|
80
80
|
|
|
@@ -171,9 +171,13 @@ module Spree
|
|
|
171
171
|
where("#{Spree::Product.quoted_table_name}.deleted_at IS NULL or #{Spree::Product.quoted_table_name}.deleted_at >= ?", Time.current)
|
|
172
172
|
end
|
|
173
173
|
|
|
174
|
+
scope :with_master_price, -> do
|
|
175
|
+
joins(:master).where(Spree::Price.where(Spree::Variant.arel_table[:id].eq(Spree::Price.arel_table[:variant_id])).exists)
|
|
176
|
+
end
|
|
177
|
+
|
|
174
178
|
# Can't use add_search_scope for this as it needs a default argument
|
|
175
179
|
def self.available(available_on = nil)
|
|
176
|
-
|
|
180
|
+
with_master_price.where("#{Spree::Product.quoted_table_name}.available_on <= ?", available_on || Time.current)
|
|
177
181
|
end
|
|
178
182
|
search_scopes << :available
|
|
179
183
|
|
|
@@ -181,7 +185,16 @@ module Spree
|
|
|
181
185
|
group("spree_products.id").joins(:taxons).where(Spree::Taxon.arel_table[:name].eq(name))
|
|
182
186
|
end
|
|
183
187
|
|
|
188
|
+
def self.with_variant_sku_cont(sku)
|
|
189
|
+
sku_match = "%#{sku}%"
|
|
190
|
+
variant_table = Spree::Variant.arel_table
|
|
191
|
+
subquery = Spree::Variant.where(variant_table[:sku].matches(sku_match).and(variant_table[:product_id].eq(arel_table[:id])))
|
|
192
|
+
where(subquery.exists)
|
|
193
|
+
end
|
|
194
|
+
|
|
184
195
|
def self.distinct_by_product_ids(sort_order = nil)
|
|
196
|
+
Spree::Deprecation.warn "Product.distinct_by_product_ids is deprecated and should not be used"
|
|
197
|
+
|
|
185
198
|
sort_column = sort_order.split(" ").first
|
|
186
199
|
|
|
187
200
|
# Postgres will complain when using ordering by expressions not present in
|
data/app/models/spree/product.rb
CHANGED
|
@@ -80,7 +80,7 @@ module Spree
|
|
|
80
80
|
|
|
81
81
|
after_initialize :ensure_master
|
|
82
82
|
|
|
83
|
-
after_save :run_touch_callbacks, if: :
|
|
83
|
+
after_save :run_touch_callbacks, if: :saved_changes?
|
|
84
84
|
after_touch :touch_taxons
|
|
85
85
|
|
|
86
86
|
before_validation :normalize_slug, on: :update
|
|
@@ -103,6 +103,10 @@ module Spree
|
|
|
103
103
|
self.whitelisted_ransackable_associations = %w[stores variants_including_master master variants]
|
|
104
104
|
self.whitelisted_ransackable_attributes = %w[slug]
|
|
105
105
|
|
|
106
|
+
def self.ransackable_scopes(_auth_object = nil)
|
|
107
|
+
%i(with_deleted with_variant_sku_cont)
|
|
108
|
+
end
|
|
109
|
+
|
|
106
110
|
# @return [Boolean] true if there are any variants
|
|
107
111
|
def has_variants?
|
|
108
112
|
variants.any?
|
|
@@ -339,10 +343,12 @@ module Spree
|
|
|
339
343
|
# Iterate through this products taxons and taxonomies and touch their timestamps in a batch
|
|
340
344
|
def touch_taxons
|
|
341
345
|
taxons_to_touch = taxons.map(&:self_and_ancestors).flatten.uniq
|
|
342
|
-
|
|
346
|
+
unless taxons_to_touch.empty?
|
|
347
|
+
Spree::Taxon.where(id: taxons_to_touch.map(&:id)).update_all(updated_at: Time.current)
|
|
343
348
|
|
|
344
|
-
|
|
345
|
-
|
|
349
|
+
taxonomy_ids_to_touch = taxons_to_touch.map(&:taxonomy_id).flatten.uniq
|
|
350
|
+
Spree::Taxonomy.where(id: taxonomy_ids_to_touch).update_all(updated_at: Time.current)
|
|
351
|
+
end
|
|
346
352
|
end
|
|
347
353
|
|
|
348
354
|
def remove_taxon(taxon)
|
|
@@ -2,10 +2,11 @@ class ::Spree::PromotionCode::BatchBuilder
|
|
|
2
2
|
attr_reader :promotion_code_batch
|
|
3
3
|
delegate :promotion, :number_of_codes, :base_code, to: :promotion_code_batch
|
|
4
4
|
|
|
5
|
-
class_attribute :random_code_length, :batch_size, :sample_characters
|
|
5
|
+
class_attribute :random_code_length, :batch_size, :sample_characters, :join_characters
|
|
6
6
|
self.random_code_length = 6
|
|
7
7
|
self.batch_size = 1_000
|
|
8
8
|
self.sample_characters = ('a'..'z').to_a + (2..9).to_a.map(&:to_s)
|
|
9
|
+
self.join_characters = "_"
|
|
9
10
|
|
|
10
11
|
def initialize(promotion_code_batch)
|
|
11
12
|
@promotion_code_batch = promotion_code_batch
|
|
@@ -54,7 +55,7 @@ class ::Spree::PromotionCode::BatchBuilder
|
|
|
54
55
|
sample_characters.sample
|
|
55
56
|
end.join
|
|
56
57
|
|
|
57
|
-
"#{base_code}
|
|
58
|
+
"#{base_code}#{join_characters}#{suffix}"
|
|
58
59
|
end
|
|
59
60
|
|
|
60
61
|
def get_unique_codes(code_set)
|
data/app/models/spree/role.rb
CHANGED
|
@@ -95,6 +95,7 @@ module Spree
|
|
|
95
95
|
def add_shipping_method(shipping_method, selected = false)
|
|
96
96
|
shipping_rates.create(shipping_method: shipping_method, selected: selected, cost: cost)
|
|
97
97
|
end
|
|
98
|
+
deprecate :add_shipping_method, deprecator: Spree::Deprecation
|
|
98
99
|
|
|
99
100
|
def after_cancel
|
|
100
101
|
manifest.each { |item| manifest_restock(item) }
|
|
@@ -171,7 +172,7 @@ module Spree
|
|
|
171
172
|
end
|
|
172
173
|
|
|
173
174
|
def refresh_rates
|
|
174
|
-
return shipping_rates if shipped?
|
|
175
|
+
return shipping_rates if shipped?
|
|
175
176
|
return [] unless can_get_rates?
|
|
176
177
|
|
|
177
178
|
# StockEstimator.new assigment below will replace the current shipping_method
|
|
@@ -250,7 +251,7 @@ module Spree
|
|
|
250
251
|
end
|
|
251
252
|
|
|
252
253
|
def shipping_method
|
|
253
|
-
selected_shipping_rate.try(:shipping_method)
|
|
254
|
+
selected_shipping_rate.try(:shipping_method)
|
|
254
255
|
end
|
|
255
256
|
|
|
256
257
|
# Only one of either included_tax_total or additional_tax_total is set
|
|
@@ -332,6 +333,7 @@ module Spree
|
|
|
332
333
|
order.contents.add(variant, quantity, { shipment: new_shipment })
|
|
333
334
|
|
|
334
335
|
refresh_rates
|
|
336
|
+
new_shipment.refresh_rates
|
|
335
337
|
save!
|
|
336
338
|
new_shipment.save!
|
|
337
339
|
end
|
|
@@ -36,10 +36,12 @@ module Spree
|
|
|
36
36
|
# cause this to return incorrect results.
|
|
37
37
|
join_table = Spree::ShippingMethodCategory.arel_table
|
|
38
38
|
having = join_table[:id].count(true).eq(shipping_category_ids.count)
|
|
39
|
-
joins(:shipping_method_categories).
|
|
39
|
+
subquery = joins(:shipping_method_categories).
|
|
40
40
|
where(spree_shipping_method_categories: { shipping_category_id: shipping_category_ids }).
|
|
41
41
|
group('spree_shipping_methods.id').
|
|
42
42
|
having(having)
|
|
43
|
+
|
|
44
|
+
where(id: subquery.select(:id))
|
|
43
45
|
end
|
|
44
46
|
|
|
45
47
|
# @param stock_location [Spree::StockLocation] stock location
|
|
@@ -3,7 +3,7 @@ module Spree
|
|
|
3
3
|
# method has been selected to deliver the shipment.
|
|
4
4
|
#
|
|
5
5
|
class ShippingRate < Spree::Base
|
|
6
|
-
belongs_to :shipment, class_name: 'Spree::Shipment'
|
|
6
|
+
belongs_to :shipment, class_name: 'Spree::Shipment', touch: true
|
|
7
7
|
belongs_to :shipping_method, -> { with_deleted }, class_name: 'Spree::ShippingMethod', inverse_of: :shipping_rates
|
|
8
8
|
|
|
9
9
|
has_many :taxes,
|
data/app/models/spree/state.rb
CHANGED
|
@@ -5,8 +5,16 @@ module Spree
|
|
|
5
5
|
|
|
6
6
|
validates :country, :name, presence: true
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
where(
|
|
8
|
+
scope :with_name_or_abbr, ->(name_or_abbr) do
|
|
9
|
+
where(
|
|
10
|
+
arel_table[:name].matches(name_or_abbr).or(
|
|
11
|
+
arel_table[:abbr].matches(name_or_abbr)
|
|
12
|
+
)
|
|
13
|
+
)
|
|
14
|
+
end
|
|
15
|
+
class << self
|
|
16
|
+
alias_method :find_all_by_name_or_abbr, :with_name_or_abbr
|
|
17
|
+
deprecate find_all_by_name_or_abbr: :with_name_or_abbr, deprecator: Spree::Deprecation
|
|
10
18
|
end
|
|
11
19
|
|
|
12
20
|
# table of { country.id => [ state.id , state.name ] }, arrays sorted by name
|
|
@@ -15,7 +15,7 @@ module Spree
|
|
|
15
15
|
# @return [String] the name of this stock item's variant
|
|
16
16
|
delegate :name, to: :variant, prefix: true
|
|
17
17
|
|
|
18
|
-
after_save :conditional_variant_touch, if: :
|
|
18
|
+
after_save :conditional_variant_touch, if: :saved_changes?
|
|
19
19
|
after_touch { variant.touch }
|
|
20
20
|
|
|
21
21
|
self.whitelisted_ransackable_attributes = ['count_on_hand', 'stock_location_id']
|
|
@@ -103,8 +103,8 @@ module Spree
|
|
|
103
103
|
def should_touch_variant?
|
|
104
104
|
# the variant_id changes from nil when a new stock location is added
|
|
105
105
|
inventory_cache_threshold &&
|
|
106
|
-
(
|
|
107
|
-
|
|
106
|
+
(saved_change_to_count_on_hand && saved_change_to_count_on_hand.any? { |c| c < inventory_cache_threshold }) ||
|
|
107
|
+
saved_change_to_variant_id?
|
|
108
108
|
end
|
|
109
109
|
|
|
110
110
|
def inventory_cache_threshold
|
data/app/models/spree/store.rb
CHANGED
|
@@ -21,7 +21,12 @@ module Spree
|
|
|
21
21
|
|
|
22
22
|
scope :by_url, lambda { |url| where("url like ?", "%#{url}%") }
|
|
23
23
|
|
|
24
|
+
class << self
|
|
25
|
+
deprecate :by_url, "Spree::Store.by_url is DEPRECATED", deprecator: Spree::Deprecation
|
|
26
|
+
end
|
|
27
|
+
|
|
24
28
|
def self.current(store_key)
|
|
29
|
+
Spree::Deprecation.warn "Spree::Store.current is DEPRECATED"
|
|
25
30
|
current_store = Store.find_by(code: store_key) || Store.by_url(store_key).first if store_key
|
|
26
31
|
current_store || Store.default
|
|
27
32
|
end
|
|
@@ -239,7 +239,7 @@ class Spree::StoreCredit < Spree::PaymentSource
|
|
|
239
239
|
end
|
|
240
240
|
|
|
241
241
|
def store_event
|
|
242
|
-
return unless
|
|
242
|
+
return unless saved_change_to_amount? || saved_change_to_amount_used? || saved_change_to_amount_authorized? || [ELIGIBLE_ACTION, INVALIDATE_ACTION].include?(action)
|
|
243
243
|
|
|
244
244
|
event = if action
|
|
245
245
|
store_credit_events.build(action: action)
|
|
@@ -285,7 +285,7 @@ class Spree::StoreCredit < Spree::PaymentSource
|
|
|
285
285
|
def associate_credit_type
|
|
286
286
|
unless type_id
|
|
287
287
|
credit_type_name = category.try(:non_expiring?) ? Spree.t("store_credit.non_expiring") : Spree.t("store_credit.expiring")
|
|
288
|
-
self.credit_type = Spree::StoreCreditType.
|
|
288
|
+
self.credit_type = Spree::StoreCreditType.find_by(name: credit_type_name)
|
|
289
289
|
end
|
|
290
290
|
end
|
|
291
291
|
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Default implementation for finding the current store is given an HTTP request
|
|
2
|
+
#
|
|
3
|
+
# This is the new default behaviour, starting in Solidus 2.3.0. For the old
|
|
4
|
+
# behaviour see Spree::StoreSelector::Legacy.
|
|
5
|
+
#
|
|
6
|
+
# This attempts to find a Spree::Store with a URL matching the domain name of
|
|
7
|
+
# the request exactly. Failing that it will return the store marked as default.
|
|
8
|
+
module Spree
|
|
9
|
+
module StoreSelector
|
|
10
|
+
class ByServerName
|
|
11
|
+
def initialize(request)
|
|
12
|
+
@request = request
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# Chooses the current store based on a request.
|
|
16
|
+
# @return [Spree::Store]
|
|
17
|
+
def store
|
|
18
|
+
server_name = @request.env['SERVER_NAME']
|
|
19
|
+
|
|
20
|
+
# We select a store which either matches our server name, or is default.
|
|
21
|
+
# We sort by `default ASC` so that a store matching SERVER_NAME will come
|
|
22
|
+
# first, and we will find that instead of the default.
|
|
23
|
+
store = Spree::Store.where(url: server_name).or(Store.where(default: true)).order(default: :asc).first
|
|
24
|
+
|
|
25
|
+
# Provide a fallback, mostly for legacy/testing purposes
|
|
26
|
+
store || Spree::Store.new
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# This class provides the old behaviour for finding a matching Spree::Store
|
|
2
|
+
# based on a request.
|
|
3
|
+
#
|
|
4
|
+
# To enable this, somewhere inside config/initializers/ add
|
|
5
|
+
#
|
|
6
|
+
# Spree::Config.current_store_selector_class = Spree::StoreSelector::Legacy
|
|
7
|
+
#
|
|
8
|
+
# This classes behaviour is somewhat complicated and has issues, which is why
|
|
9
|
+
# it has been replaced with Spree::StoreSelector::ByServerName by default.
|
|
10
|
+
#
|
|
11
|
+
# It will:
|
|
12
|
+
# * Find a "store_key"
|
|
13
|
+
# * from the HTTP_SPREE_STORE header, if it exists
|
|
14
|
+
# * or the server's domain name if HTTP_SPREE_STORE isn't set
|
|
15
|
+
# * Find a store, using the first match of:
|
|
16
|
+
# * having a code matching the store_key exactly
|
|
17
|
+
# * having a url which contains the store_key anywhere as a substring
|
|
18
|
+
# * has default set to true
|
|
19
|
+
#
|
|
20
|
+
module Spree
|
|
21
|
+
module StoreSelector
|
|
22
|
+
class Legacy
|
|
23
|
+
def initialize(request)
|
|
24
|
+
@request = request
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Chooses the current store based on a request.
|
|
28
|
+
# Checks request headers for HTTP_SPREE_STORE and falls back to
|
|
29
|
+
# looking up by the requesting server's name.
|
|
30
|
+
# @return [Spree::Store]
|
|
31
|
+
def store
|
|
32
|
+
current_store =
|
|
33
|
+
if store_key
|
|
34
|
+
Spree::Store.find_by(code: store_key) ||
|
|
35
|
+
Store.where("url like ?", "%#{store_key}%").first
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
current_store || Spree::Store.default
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
private
|
|
42
|
+
|
|
43
|
+
def store_key
|
|
44
|
+
@request.headers['HTTP_SPREE_STORE'] || @request.env['SERVER_NAME']
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
module Spree
|
|
2
|
+
module Tax
|
|
3
|
+
# Simple object used to hold tax data for an item.
|
|
4
|
+
#
|
|
5
|
+
# This generic object will hold the amount of tax that should be applied to
|
|
6
|
+
# an item. (Either a {Spree::LineItem} or a {Spree::Shipment}.)
|
|
7
|
+
#
|
|
8
|
+
# @attr_reader [Integer] item_id the {Spree::LineItem} or {Spree::Shipment} ID
|
|
9
|
+
# @attr_reader [String] label information about the taxes
|
|
10
|
+
# @attr_reader [Spree::TaxRate] tax_rate will be used as the source for tax
|
|
11
|
+
# adjustments
|
|
12
|
+
# @attr_reader [BigDecimal] amount the amount of tax applied to the item
|
|
13
|
+
# @attr_reader [Boolean] included_in_price whether the amount is included
|
|
14
|
+
# in the items price, or additional tax.
|
|
15
|
+
class ItemTax
|
|
16
|
+
include ActiveModel::Model
|
|
17
|
+
attr_accessor :item_id, :label, :tax_rate, :amount, :included_in_price
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -4,8 +4,6 @@ module Spree
|
|
|
4
4
|
class OrderAdjuster
|
|
5
5
|
attr_reader :order
|
|
6
6
|
|
|
7
|
-
include TaxHelpers
|
|
8
|
-
|
|
9
7
|
# @param [Spree::Order] order to be adjusted
|
|
10
8
|
def initialize(order)
|
|
11
9
|
@order = order
|
|
@@ -14,18 +12,8 @@ module Spree
|
|
|
14
12
|
# Creates tax adjustments for all taxable items (shipments and line items)
|
|
15
13
|
# in the given order.
|
|
16
14
|
def adjust!
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
end
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
private
|
|
23
|
-
|
|
24
|
-
def order_wide_options
|
|
25
|
-
{
|
|
26
|
-
rates_for_order: rates_for_order(order),
|
|
27
|
-
rates_for_default_zone: rates_for_default_zone
|
|
28
|
-
}
|
|
15
|
+
taxes = Spree::Config.tax_calculator_class.new(order).calculate
|
|
16
|
+
Spree::OrderTaxation.new(order).apply(taxes)
|
|
29
17
|
end
|
|
30
18
|
end
|
|
31
19
|
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
module Spree
|
|
2
|
+
module Tax
|
|
3
|
+
# Simple object to pass back tax data from a calculator.
|
|
4
|
+
#
|
|
5
|
+
# Will be used by {Spree::OrderTaxation} to create or update tax
|
|
6
|
+
# adjustments on an order.
|
|
7
|
+
#
|
|
8
|
+
# @attr_reader [Integer] order_id the {Spree::Order} these taxes apply to
|
|
9
|
+
# @attr_reader [Array<Spree::Tax::ItemTax>] line_item_taxes an array of
|
|
10
|
+
# tax data for order's line items
|
|
11
|
+
# @attr_reader [Array<Spree::Tax::ItemTax>] shipment_taxes an array of
|
|
12
|
+
# tax data for the order's shipments
|
|
13
|
+
class OrderTax
|
|
14
|
+
include ActiveModel::Model
|
|
15
|
+
attr_accessor :order_id, :line_item_taxes, :shipment_taxes
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|