spree_core 5.4.0.beta → 5.4.0.beta2
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/finders/spree/products/find.rb +1 -28
- data/app/helpers/spree/base_helper.rb +1 -54
- data/app/mailers/spree/base_mailer.rb +4 -3
- data/app/models/concerns/spree/adjustment_source.rb +0 -8
- data/app/models/concerns/spree/admin_user_methods.rb +0 -2
- data/app/models/concerns/spree/image_methods.rb +4 -0
- data/app/models/concerns/spree/metadata.rb +10 -0
- data/app/models/concerns/spree/product_scopes.rb +2 -47
- data/app/models/concerns/spree/stores/markets.rb +7 -7
- data/app/models/concerns/spree/vat_price_calculation.rb +2 -2
- data/app/models/spree/ability.rb +5 -5
- data/app/models/spree/address.rb +3 -2
- data/app/models/spree/adjustable/promotion_accumulator.rb +1 -1
- data/app/models/spree/adjustment.rb +1 -20
- data/app/models/spree/api_key.rb +57 -2
- data/app/models/spree/country.rb +7 -3
- data/app/models/spree/credit_card.rb +0 -27
- data/app/models/spree/current.rb +38 -2
- data/app/models/spree/exports/products.rb +0 -6
- data/app/models/spree/gateway/bogus.rb +9 -9
- data/app/models/spree/gateway.rb +0 -3
- data/app/models/spree/gift_card_batch.rb +4 -0
- data/app/models/spree/image/configuration/active_storage.rb +0 -2
- data/app/models/spree/image.rb +7 -31
- data/app/models/spree/log_entry.rb +8 -5
- data/app/models/spree/order/checkout.rb +0 -18
- data/app/models/spree/order.rb +20 -11
- data/app/models/spree/payment/gateway_options.rb +2 -2
- data/app/models/spree/payment/processing.rb +5 -5
- data/app/models/spree/payment.rb +1 -1
- data/app/models/spree/payment_connection_error.rb +3 -0
- data/app/models/spree/payment_method/check.rb +1 -1
- data/app/models/spree/payment_method/store_credit.rb +5 -5
- data/app/models/spree/payment_response.rb +70 -0
- data/app/models/spree/permission_sets/default_customer.rb +0 -5
- data/app/models/spree/permission_sets/product_display.rb +0 -2
- data/app/models/spree/permission_sets/product_management.rb +0 -2
- data/app/models/spree/product.rb +4 -72
- data/app/models/spree/promotion.rb +2 -14
- data/app/models/spree/promotion_handler/coupon.rb +3 -3
- data/app/models/spree/prototype.rb +0 -3
- data/app/models/spree/refund.rb +6 -2
- data/app/models/spree/shipment/emails.rb +1 -0
- data/app/models/spree/shipping_category.rb +3 -3
- data/app/models/spree/store.rb +10 -49
- data/app/models/spree/store_credit.rb +4 -0
- data/app/models/spree/tax_category.rb +1 -11
- data/app/models/spree/taxon.rb +0 -16
- data/app/models/spree/variant.rb +2 -40
- data/app/models/spree/zone.rb +1 -4
- data/app/services/spree/cart/add_item.rb +8 -4
- data/app/services/spree/cart/create.rb +13 -2
- data/app/services/spree/products/duplicator.rb +0 -12
- data/app/services/spree/products/prepare_nested_attributes.rb +0 -12
- data/config/locales/en.yml +3 -20
- data/db/migrate/20210914000000_spree_four_three.rb +0 -38
- data/db/migrate/20210915064329_add_metadata_to_spree_multiple_tables.rb +0 -1
- data/db/migrate/20260226000000_add_locale_to_spree_orders.rb +5 -0
- data/db/migrate/20260226100000_add_token_digest_to_spree_api_keys.rb +21 -0
- data/lib/generators/spree/cursor_rules/templates/spree_rules.mdc +1 -3
- data/lib/spree/core/configuration.rb +0 -3
- data/lib/spree/core/controller_helpers/strong_parameters.rb +1 -2
- data/lib/spree/core/dependencies.rb +2 -10
- data/lib/spree/core/engine.rb +0 -13
- data/lib/spree/core/pricing/resolver.rb +1 -9
- data/lib/spree/core/version.rb +1 -1
- data/lib/spree/core.rb +10 -25
- data/lib/spree/permitted_attributes.rb +2 -14
- data/lib/spree/testing_support/factories/order_factory.rb +1 -0
- data/lib/spree/testing_support/factories/payment_method_factory.rb +1 -6
- data/lib/spree/testing_support/factories/product_factory.rb +0 -7
- data/lib/spree/testing_support/factories/prototype_factory.rb +0 -2
- data/lib/tasks/core.rake +0 -265
- metadata +8 -101
- data/app/finders/spree/posts/find.rb +0 -137
- data/app/finders/spree/product_properties/find_available.rb +0 -20
- data/app/helpers/spree/mail_helper.rb +0 -27
- data/app/jobs/spree/api_key_touch_job.rb +0 -9
- data/app/mailers/spree/test_mailer.rb +0 -8
- data/app/models/action_text/video_embed.rb +0 -13
- data/app/models/concerns/spree/has_one_link.rb +0 -42
- data/app/models/concerns/spree/linkable.rb +0 -9
- data/app/models/concerns/spree/previewable.rb +0 -17
- data/app/models/spree/data_feed/google.rb +0 -15
- data/app/models/spree/data_feed.rb +0 -42
- data/app/models/spree/gateway/bogus_simple.rb +0 -24
- data/app/models/spree/post.rb +0 -108
- data/app/models/spree/post_category.rb +0 -46
- data/app/models/spree/product_property.rb +0 -51
- data/app/models/spree/property.rb +0 -86
- data/app/models/spree/property_prototype.rb +0 -9
- data/app/models/spree/store_favicon_image.rb +0 -20
- data/app/models/spree/store_logo.rb +0 -4
- data/app/models/spree/store_mailer_logo.rb +0 -7
- data/app/models/spree/taxon_image/configuration/active_storage.rb +0 -26
- data/app/models/spree/taxon_image.rb +0 -28
- data/app/presenters/spree/filters/properties_presenter.rb +0 -23
- data/app/presenters/spree/filters/property_presenter.rb +0 -42
- data/app/services/spree/data_feeds/google/optional_attributes.rb +0 -23
- data/app/services/spree/data_feeds/google/optional_sub_attributes.rb +0 -21
- data/app/services/spree/data_feeds/google/products_list.rb +0 -14
- data/app/services/spree/data_feeds/google/required_attributes.rb +0 -68
- data/app/services/spree/data_feeds/google/rss.rb +0 -109
- data/app/sorters/spree/posts/sort.rb +0 -40
- data/app/views/action_text/video_embeds/_thumbnail.html.erb +0 -1
- data/app/views/action_text/video_embeds/_video_embed.html.erb +0 -3
- data/app/views/layouts/action_text/contents/_content.html.erb +0 -3
- data/app/views/spree/test_mailer/test_email.html.erb +0 -40
- data/app/views/spree/test_mailer/test_email.text.erb +0 -4
- data/config/initializers/oembed.rb +0 -1
- data/db/migrate/20221229132350_create_spree_data_feed_settings.rb +0 -14
- data/db/migrate/20230109084253_create_product_property_translations.rb +0 -24
- data/db/migrate/20230109105943_create_property_translations.rb +0 -24
- data/db/migrate/20230415155958_rename_data_feed_settings_table.rb +0 -5
- data/db/migrate/20230415160828_rename_data_feed_table_columns.rb +0 -7
- data/db/migrate/20230415161226_add_indexes_to_data_feeds_table.rb +0 -5
- data/db/migrate/20230512094803_rename_data_feeds_column_provider_to_type.rb +0 -5
- data/db/migrate/20240914153106_add_display_on_to_spree_properties.rb +0 -5
- data/db/migrate/20240915144935_add_position_to_spree_properties.rb +0 -6
- data/db/migrate/20250121160028_create_spree_posts_and_spree_post_categories.rb +0 -33
- data/db/migrate/20250127083740_add_kind_to_spree_properties.rb +0 -5
- data/db/migrate/20250217171018_create_action_text_video_embeds.rb +0 -11
- data/db/migrate/20250305121657_remove_spree_posts_indices.rb +0 -7
- data/db/migrate/20250730154601_add_unique_index_on_spree_properties_name.rb +0 -24
- data/db/sample_data/posts.rb +0 -7
- data/lib/spree/core/controller_helpers/search.rb +0 -17
- data/lib/spree/core/product_filters.rb +0 -218
- data/lib/spree/core/query_filters/comparable.rb +0 -50
- data/lib/spree/core/query_filters/date.rb +0 -8
- data/lib/spree/core/query_filters/number.rb +0 -8
- data/lib/spree/core/query_filters/text.rb +0 -36
- data/lib/spree/core/query_filters.rb +0 -11
- data/lib/spree/core/search/base.rb +0 -144
- data/lib/spree/testing_support/factories/favicon_image_factory.rb +0 -9
- data/lib/spree/testing_support/factories/google_data_feed_factory.rb +0 -7
- data/lib/spree/testing_support/factories/post_category_factory.rb +0 -7
- data/lib/spree/testing_support/factories/post_factory.rb +0 -22
- data/lib/spree/testing_support/factories/product_property_factory.rb +0 -7
- data/lib/spree/testing_support/factories/property_factory.rb +0 -28
- data/lib/spree/testing_support/factories/taxon_image_factory.rb +0 -9
- data/lib/spree/testing_support/flash.rb +0 -25
- data/lib/spree/testing_support/flatpickr_capybara.rb +0 -124
- data/lib/tasks/exchanges.rake +0 -66
|
@@ -2,7 +2,6 @@ module Spree
|
|
|
2
2
|
class CreditCard < Spree.base_class
|
|
3
3
|
has_prefix_id :card # Stripe: card_
|
|
4
4
|
|
|
5
|
-
include ActiveMerchant::Billing::CreditCardMethods
|
|
6
5
|
include Spree::Metafields
|
|
7
6
|
include Spree::Metadata
|
|
8
7
|
include Spree::PaymentSourceConcern
|
|
@@ -48,7 +47,6 @@ module Spree
|
|
|
48
47
|
}
|
|
49
48
|
scope :not_removed, -> { where(deleted_at: nil) }
|
|
50
49
|
|
|
51
|
-
# needed for some of the ActiveMerchant gateways (eg. SagePay)
|
|
52
50
|
alias_attribute :brand, :cc_type
|
|
53
51
|
|
|
54
52
|
store_accessor :private_metadata, :wallet
|
|
@@ -59,14 +57,6 @@ module Spree
|
|
|
59
57
|
wallet&.[]('type')
|
|
60
58
|
end
|
|
61
59
|
|
|
62
|
-
# ActiveMerchant::Billing::CreditCard added this accessor used by some gateways.
|
|
63
|
-
# More info: https://github.com/spree/spree/issues/6209
|
|
64
|
-
#
|
|
65
|
-
# Returns or sets the track data for the card
|
|
66
|
-
#
|
|
67
|
-
# @return [String]
|
|
68
|
-
attr_accessor :track_data
|
|
69
|
-
|
|
70
60
|
CARD_TYPES = {
|
|
71
61
|
visa: /^4\d{12}(\d{3})?(\d{3})?$/,
|
|
72
62
|
master: /^(5[1-5]\d{4}|677189|222[1-9]\d{2}|22[3-9]\d{3}|2[3-6]\d{4}|27[01]\d{3}|2720\d{2})\d{10}$/,
|
|
@@ -151,10 +141,6 @@ module Spree
|
|
|
151
141
|
brand.present? ? brand.upcase : Spree.t(:no_cc_type)
|
|
152
142
|
end
|
|
153
143
|
|
|
154
|
-
# ActiveMerchant needs first_name/last_name because we pass it a Spree::CreditCard and it calls those methods on it.
|
|
155
|
-
# Looking at the ActiveMerchant source code we should probably be calling #to_active_merchant before passing
|
|
156
|
-
# the object to ActiveMerchant but this should do for now.
|
|
157
|
-
#
|
|
158
144
|
# Returns the first name of the cardholder.
|
|
159
145
|
# @return [String]
|
|
160
146
|
def first_name
|
|
@@ -167,19 +153,6 @@ module Spree
|
|
|
167
153
|
name.to_s.split(/[[:space:]]/, 2)[1]
|
|
168
154
|
end
|
|
169
155
|
|
|
170
|
-
# Returns an ActiveMerchant::Billing::CreditCard object.
|
|
171
|
-
# @return [ActiveMerchant::Billing::CreditCard]
|
|
172
|
-
def to_active_merchant
|
|
173
|
-
ActiveMerchant::Billing::CreditCard.new(
|
|
174
|
-
number: number,
|
|
175
|
-
month: month,
|
|
176
|
-
year: year,
|
|
177
|
-
verification_value: verification_value,
|
|
178
|
-
first_name: first_name,
|
|
179
|
-
last_name: last_name
|
|
180
|
-
)
|
|
181
|
-
end
|
|
182
|
-
|
|
183
156
|
def self.json_api_permitted_attributes
|
|
184
157
|
[
|
|
185
158
|
'number', 'month', 'year', 'expiry', 'verification_value', 'first_name', 'last_name',
|
data/app/models/spree/current.rb
CHANGED
|
@@ -1,23 +1,57 @@
|
|
|
1
1
|
module Spree
|
|
2
|
+
# Thread-safe, per-request attributes for the current store context.
|
|
3
|
+
#
|
|
4
|
+
# All attributes are automatically reset between requests by Rails.
|
|
5
|
+
# Fallback chains ensure sensible defaults when attributes are not explicitly set.
|
|
2
6
|
class Current < ::ActiveSupport::CurrentAttributes
|
|
3
|
-
attribute :store, :market, :currency, :zone, :price_lists, :global_pricing_context
|
|
7
|
+
attribute :store, :market, :currency, :locale, :zone, :default_tax_zone, :price_lists, :global_pricing_context
|
|
4
8
|
|
|
9
|
+
resets { @default_tax_zone_loaded = false }
|
|
10
|
+
|
|
11
|
+
# Returns the current store, falling back to the default store.
|
|
12
|
+
# @return [Spree::Store]
|
|
5
13
|
def store
|
|
6
14
|
super || Spree::Store.default
|
|
7
15
|
end
|
|
8
16
|
|
|
17
|
+
# Returns the current market, falling back to the store's default market.
|
|
18
|
+
# @return [Spree::Market, nil]
|
|
9
19
|
def market
|
|
10
20
|
super || store&.default_market
|
|
11
21
|
end
|
|
12
22
|
|
|
23
|
+
# Returns the current currency.
|
|
24
|
+
# Fallback: market currency -> store default currency.
|
|
25
|
+
# @return [String] currency ISO code, e.g. +"USD"+
|
|
13
26
|
def currency
|
|
14
27
|
super || market&.currency || store&.default_currency
|
|
15
28
|
end
|
|
16
29
|
|
|
30
|
+
# Returns the current locale.
|
|
31
|
+
# Fallback: market default locale -> store default locale.
|
|
32
|
+
# @return [String] locale code, e.g. +"en"+, +"de"+
|
|
33
|
+
def locale
|
|
34
|
+
super || market&.default_locale || store&.default_locale
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Returns the current tax zone, falling back to the default tax zone.
|
|
38
|
+
# @return [Spree::Zone, nil]
|
|
17
39
|
def zone
|
|
18
|
-
super ||
|
|
40
|
+
super || default_tax_zone
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Returns the default tax zone (memoized per request).
|
|
44
|
+
# @return [Spree::Zone, nil]
|
|
45
|
+
def default_tax_zone
|
|
46
|
+
result = super
|
|
47
|
+
return result if result || @default_tax_zone_loaded
|
|
48
|
+
|
|
49
|
+
@default_tax_zone_loaded = true
|
|
50
|
+
self.default_tax_zone = Spree::Zone.find_by(default_tax: true)
|
|
19
51
|
end
|
|
20
52
|
|
|
53
|
+
# Returns the current price lists for the global pricing context.
|
|
54
|
+
# @return [ActiveRecord::Relation<Spree::PriceList>]
|
|
21
55
|
def price_lists
|
|
22
56
|
super || begin
|
|
23
57
|
context = global_pricing_context
|
|
@@ -25,6 +59,8 @@ module Spree
|
|
|
25
59
|
end
|
|
26
60
|
end
|
|
27
61
|
|
|
62
|
+
# Returns the current global pricing context, built from store, currency, zone, and market.
|
|
63
|
+
# @return [Spree::Pricing::Context]
|
|
28
64
|
def global_pricing_context
|
|
29
65
|
super || begin
|
|
30
66
|
self.global_pricing_context = Spree::Pricing::Context.new(
|
|
@@ -4,7 +4,6 @@ module Spree
|
|
|
4
4
|
# to avoid N+1 queries
|
|
5
5
|
def scope_includes
|
|
6
6
|
includes = [:tax_category, :master, :option_types, { taxons: :taxonomy }, { variants_including_master: variant_includes }]
|
|
7
|
-
includes << { product_properties: [:property] } if Spree::Config[:product_properties_enabled]
|
|
8
7
|
includes << { metafields: :metafield_definition }
|
|
9
8
|
includes
|
|
10
9
|
end
|
|
@@ -28,14 +27,9 @@ module Spree
|
|
|
28
27
|
|
|
29
28
|
def csv_headers
|
|
30
29
|
headers = Spree::CSV::ProductVariantPresenter::CSV_HEADERS.dup
|
|
31
|
-
headers += properties_headers if Spree::Config[:product_properties_enabled]
|
|
32
30
|
headers += metafields_headers
|
|
33
31
|
@csv_headers ||= headers
|
|
34
32
|
end
|
|
35
|
-
|
|
36
|
-
def properties_headers
|
|
37
|
-
@properties_headers ||= Spree::Property.order(:position).count.times.flat_map { |n| ["property#{n + 1}_name", "property#{n + 1}_value"] }
|
|
38
|
-
end
|
|
39
33
|
end
|
|
40
34
|
end
|
|
41
35
|
end
|
|
@@ -32,39 +32,39 @@ module Spree
|
|
|
32
32
|
def authorize(_money, credit_card, _options = {})
|
|
33
33
|
profile_id = credit_card.gateway_customer_profile_id
|
|
34
34
|
if VALID_CCS.include?(credit_card.number) || (profile_id&.starts_with?('BGS-'))
|
|
35
|
-
|
|
35
|
+
Spree::PaymentResponse.new(true, 'Bogus Gateway: Forced success', {}, test: true, authorization: '12345', avs_result: { code: 'D' })
|
|
36
36
|
else
|
|
37
|
-
|
|
37
|
+
Spree::PaymentResponse.new(false, 'Bogus Gateway: Forced failure', { message: 'Bogus Gateway: Forced failure' }, test: true)
|
|
38
38
|
end
|
|
39
39
|
end
|
|
40
40
|
|
|
41
41
|
def purchase(_money, credit_card, _options = {})
|
|
42
42
|
profile_id = credit_card.gateway_customer_profile_id
|
|
43
43
|
if VALID_CCS.include?(credit_card.number) || (profile_id&.starts_with?('BGS-'))
|
|
44
|
-
|
|
44
|
+
Spree::PaymentResponse.new(true, 'Bogus Gateway: Forced success', {}, test: true, authorization: '12345', avs_result: { code: 'M' })
|
|
45
45
|
else
|
|
46
|
-
|
|
46
|
+
Spree::PaymentResponse.new(false, 'Bogus Gateway: Forced failure', message: 'Bogus Gateway: Forced failure', test: true)
|
|
47
47
|
end
|
|
48
48
|
end
|
|
49
49
|
|
|
50
50
|
def credit(_money, _credit_card, _response_code, _options = {})
|
|
51
|
-
|
|
51
|
+
Spree::PaymentResponse.new(true, 'Bogus Gateway: Forced success', {}, test: true, authorization: '12345')
|
|
52
52
|
end
|
|
53
53
|
|
|
54
54
|
def capture(_money, authorization, _gateway_options)
|
|
55
55
|
if authorization == '12345'
|
|
56
|
-
|
|
56
|
+
Spree::PaymentResponse.new(true, 'Bogus Gateway: Forced success', {}, test: true)
|
|
57
57
|
else
|
|
58
|
-
|
|
58
|
+
Spree::PaymentResponse.new(false, 'Bogus Gateway: Forced failure', error: 'Bogus Gateway: Forced failure', test: true)
|
|
59
59
|
end
|
|
60
60
|
end
|
|
61
61
|
|
|
62
62
|
def void(_response_code, _credit_card, _options = {})
|
|
63
|
-
|
|
63
|
+
Spree::PaymentResponse.new(true, 'Bogus Gateway: Forced success', {}, test: true, authorization: 'void-12345')
|
|
64
64
|
end
|
|
65
65
|
|
|
66
66
|
def cancel(_response_code, _payment = nil)
|
|
67
|
-
|
|
67
|
+
Spree::PaymentResponse.new(true, 'Bogus Gateway: Forced success', {}, test: true, authorization: '12345')
|
|
68
68
|
end
|
|
69
69
|
|
|
70
70
|
def test?
|
data/app/models/spree/gateway.rb
CHANGED
|
@@ -20,9 +20,6 @@ module Spree
|
|
|
20
20
|
def provider
|
|
21
21
|
gateway_options = options
|
|
22
22
|
gateway_options.delete :login if gateway_options.key?(:login) && gateway_options[:login].nil?
|
|
23
|
-
if gateway_options[:server]
|
|
24
|
-
ActiveMerchant::Billing::Base.mode = gateway_options[:server].to_sym
|
|
25
|
-
end
|
|
26
23
|
@provider ||= provider_class.new(gateway_options)
|
|
27
24
|
end
|
|
28
25
|
|
|
@@ -5,8 +5,6 @@ module Spree
|
|
|
5
5
|
extend ActiveSupport::Concern
|
|
6
6
|
|
|
7
7
|
included do
|
|
8
|
-
validates :attachment, attached: true, content_type: Rails.application.config.active_storage.web_image_content_types
|
|
9
|
-
|
|
10
8
|
# Returns image styles derived from Spree::Config.product_image_variant_sizes
|
|
11
9
|
# Format: { variant_name: 'WxH>' } for API compatibility
|
|
12
10
|
def self.styles
|
data/app/models/spree/image.rb
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
module Spree
|
|
2
2
|
class Image < Asset
|
|
3
|
-
include Spree::Image::Configuration::ActiveStorage
|
|
3
|
+
include Spree::Image::Configuration::ActiveStorage # legacy to be removed in Spree 6
|
|
4
4
|
include Rails.application.routes.url_helpers
|
|
5
|
-
include Spree::ImageMethods
|
|
5
|
+
include Spree::ImageMethods # legacy, will be removed in Spree 6
|
|
6
|
+
|
|
7
|
+
validates :attachment, attached: true, content_type: Rails.application.config.active_storage.web_image_content_types
|
|
6
8
|
|
|
7
9
|
after_commit :touch_product_variants, if: :should_touch_product_variants?, on: :update
|
|
8
10
|
after_commit :update_variant_thumbnail, on: [:create, :destroy]
|
|
@@ -19,7 +21,10 @@ module Spree
|
|
|
19
21
|
# The line below prevents the error.
|
|
20
22
|
self.inheritance_column = nil
|
|
21
23
|
|
|
24
|
+
# @deprecated
|
|
22
25
|
def styles
|
|
26
|
+
Spree::Deprecation.warn("Image#styles is deprecated and will be removed in Spree 6.0. Please use active storage variants with cdn_image_url")
|
|
27
|
+
|
|
23
28
|
self.class.styles.map do |_, size|
|
|
24
29
|
width, height = size.chop.split('x').map(&:to_i)
|
|
25
30
|
|
|
@@ -32,35 +37,6 @@ module Spree
|
|
|
32
37
|
end
|
|
33
38
|
end
|
|
34
39
|
|
|
35
|
-
def style(name)
|
|
36
|
-
size = self.class.styles[name]
|
|
37
|
-
return unless size
|
|
38
|
-
|
|
39
|
-
width, height = size.chop.split('x').map(&:to_i)
|
|
40
|
-
|
|
41
|
-
{
|
|
42
|
-
url: generate_url(size: size),
|
|
43
|
-
size: size,
|
|
44
|
-
width: width,
|
|
45
|
-
height: height
|
|
46
|
-
}
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
def style_dimensions(name)
|
|
50
|
-
size = self.class.styles[name]
|
|
51
|
-
width, height = size.chop.split('x').map(&:to_i)
|
|
52
|
-
|
|
53
|
-
{
|
|
54
|
-
width: width,
|
|
55
|
-
height: height
|
|
56
|
-
}
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
def plp_url
|
|
60
|
-
Spree::Deprecation.warn "Image#plp_url is deprecated. Use variant(:large) instead."
|
|
61
|
-
generate_url(size: self.class.styles[:large])
|
|
62
|
-
end
|
|
63
|
-
|
|
64
40
|
private
|
|
65
41
|
|
|
66
42
|
def touch_product_variants
|
|
@@ -17,11 +17,14 @@ module Spree
|
|
|
17
17
|
end
|
|
18
18
|
|
|
19
19
|
def parsed_details
|
|
20
|
-
@details ||=
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
20
|
+
@details ||= YAML.safe_load(
|
|
21
|
+
details,
|
|
22
|
+
permitted_classes: [
|
|
23
|
+
Spree::PaymentResponse,
|
|
24
|
+
ActiveSupport::HashWithIndifferentAccess,
|
|
25
|
+
(ActiveMerchant::Billing::Response if defined?(ActiveMerchant::Billing::Response))
|
|
26
|
+
].compact
|
|
27
|
+
)
|
|
25
28
|
end
|
|
26
29
|
end
|
|
27
30
|
end
|
|
@@ -89,7 +89,6 @@ module Spree
|
|
|
89
89
|
end
|
|
90
90
|
|
|
91
91
|
after_transition to: :complete, do: :create_user_record
|
|
92
|
-
after_transition to: :complete, do: :persist_user_credit_card
|
|
93
92
|
before_transition to: :payment, do: :set_shipments_cost
|
|
94
93
|
before_transition to: :payment, do: :create_tax_charge!
|
|
95
94
|
before_transition to: :payment, do: :recalculate_store_credit_payment
|
|
@@ -293,23 +292,6 @@ module Spree
|
|
|
293
292
|
Spree::Orders::CreateUserAccount.call(order: self, accepts_email_marketing: accept_marketing?)
|
|
294
293
|
end
|
|
295
294
|
|
|
296
|
-
def persist_user_credit_card
|
|
297
|
-
return unless !temporary_credit_card && user_id && valid_credit_cards.present?
|
|
298
|
-
|
|
299
|
-
valid_credit_cards.first.update(user_id: user_id, default: true)
|
|
300
|
-
end
|
|
301
|
-
|
|
302
|
-
def assign_default_credit_card
|
|
303
|
-
return unless payments.from_credit_card.size.empty? && user_has_valid_default_card? && payment_required?
|
|
304
|
-
|
|
305
|
-
cc = user.default_credit_card
|
|
306
|
-
payments.create!(payment_method_id: cc.payment_method_id, source: cc, amount: total)
|
|
307
|
-
end
|
|
308
|
-
|
|
309
|
-
def user_has_valid_default_card?
|
|
310
|
-
user && user.default_credit_card.try(:valid?)
|
|
311
|
-
end
|
|
312
|
-
|
|
313
295
|
def move_to_next_step_if_address_not_required
|
|
314
296
|
return if requires_ship_address?
|
|
315
297
|
|
data/app/models/spree/order.rb
CHANGED
|
@@ -92,7 +92,7 @@ module Spree
|
|
|
92
92
|
self.whitelisted_ransackable_scopes = %w[refunded partially_refunded multi_search]
|
|
93
93
|
|
|
94
94
|
attr_reader :coupon_code
|
|
95
|
-
attr_accessor :temporary_address
|
|
95
|
+
attr_accessor :temporary_address
|
|
96
96
|
|
|
97
97
|
attribute :state_machine_resumed, :boolean
|
|
98
98
|
|
|
@@ -159,6 +159,7 @@ module Spree
|
|
|
159
159
|
# Needs to happen before save_permalink is called
|
|
160
160
|
before_validation :ensure_store_presence
|
|
161
161
|
before_validation :ensure_currency_presence
|
|
162
|
+
before_validation :ensure_locale_presence
|
|
162
163
|
|
|
163
164
|
before_validation :clone_billing_address, if: :use_billing?
|
|
164
165
|
before_validation :clone_shipping_address, if: :use_shipping?
|
|
@@ -174,6 +175,7 @@ module Spree
|
|
|
174
175
|
validates :item_count, numericality: { greater_than_or_equal_to: 0, less_than: 2**31, only_integer: true, allow_blank: true }
|
|
175
176
|
validates :store
|
|
176
177
|
validates :currency
|
|
178
|
+
validates :locale
|
|
177
179
|
end
|
|
178
180
|
validates :payment_state, inclusion: { in: PAYMENT_STATES, allow_blank: true }
|
|
179
181
|
validates :shipment_state, inclusion: { in: SHIPMENT_STATES, allow_blank: true }
|
|
@@ -186,6 +188,7 @@ module Spree
|
|
|
186
188
|
validates :promo_total, NEGATIVE_MONEY_VALIDATION
|
|
187
189
|
validates :total, MONEY_VALIDATION
|
|
188
190
|
validate :currency_must_be_supported_by_store
|
|
191
|
+
validate :locale_must_be_supported_by_store
|
|
189
192
|
|
|
190
193
|
delegate :update_totals, :persist_totals, to: :updater
|
|
191
194
|
delegate :merge!, to: :merger
|
|
@@ -529,16 +532,6 @@ module Spree
|
|
|
529
532
|
complete? || canceled? || returned?
|
|
530
533
|
end
|
|
531
534
|
|
|
532
|
-
def credit_cards
|
|
533
|
-
credit_card_ids = payments.from_credit_card.pluck(:source_id).uniq
|
|
534
|
-
CreditCard.where(id: credit_card_ids)
|
|
535
|
-
end
|
|
536
|
-
|
|
537
|
-
def valid_credit_cards
|
|
538
|
-
credit_card_ids = payments.from_credit_card.valid.pluck(:source_id).uniq
|
|
539
|
-
CreditCard.where(id: credit_card_ids)
|
|
540
|
-
end
|
|
541
|
-
|
|
542
535
|
# Finalizes an in progress order after checkout is complete.
|
|
543
536
|
# Called after transition to complete state when payments will have been processed
|
|
544
537
|
def finalize!
|
|
@@ -997,6 +990,12 @@ module Spree
|
|
|
997
990
|
self.currency ||= store&.default_currency
|
|
998
991
|
end
|
|
999
992
|
|
|
993
|
+
# Sets the locale from Spree::Current.locale when not already set.
|
|
994
|
+
# Called as a before_validation callback, mirroring ensure_currency_presence.
|
|
995
|
+
def ensure_locale_presence
|
|
996
|
+
self.locale ||= Spree::Current.locale
|
|
997
|
+
end
|
|
998
|
+
|
|
1000
999
|
def currency_must_be_supported_by_store
|
|
1001
1000
|
return if currency.blank? || store.blank?
|
|
1002
1001
|
|
|
@@ -1006,6 +1005,16 @@ module Spree
|
|
|
1006
1005
|
end
|
|
1007
1006
|
end
|
|
1008
1007
|
|
|
1008
|
+
# Validates that the order's locale is within the store's supported locales.
|
|
1009
|
+
# Mirrors currency_must_be_supported_by_store.
|
|
1010
|
+
def locale_must_be_supported_by_store
|
|
1011
|
+
return if locale.blank? || store.blank?
|
|
1012
|
+
|
|
1013
|
+
unless store.supported_locales_list.include?(locale)
|
|
1014
|
+
errors.add(:locale, Spree.t(:locale_not_supported_by_store))
|
|
1015
|
+
end
|
|
1016
|
+
end
|
|
1017
|
+
|
|
1009
1018
|
def collect_payment_methods
|
|
1010
1019
|
Spree::Deprecation.warn('`Order#collect_payment_methods` is deprecated and will be removed in Spree 5.5. Use `collect_frontend_payment_methods` instead.')
|
|
1011
1020
|
|
|
@@ -51,11 +51,11 @@ module Spree
|
|
|
51
51
|
end
|
|
52
52
|
|
|
53
53
|
def billing_address
|
|
54
|
-
order.bill_address.try(:
|
|
54
|
+
order.bill_address.try(:gateway_hash)
|
|
55
55
|
end
|
|
56
56
|
|
|
57
57
|
def shipping_address
|
|
58
|
-
order.ship_address.try(:
|
|
58
|
+
order.ship_address.try(:gateway_hash)
|
|
59
59
|
end
|
|
60
60
|
|
|
61
61
|
def hash_methods
|
|
@@ -48,7 +48,7 @@ module Spree
|
|
|
48
48
|
amount ||= money.amount_in_cents
|
|
49
49
|
started_processing!
|
|
50
50
|
protect_from_connection_error do
|
|
51
|
-
#
|
|
51
|
+
# Capture the payment amount
|
|
52
52
|
response = payment_method.capture(
|
|
53
53
|
amount,
|
|
54
54
|
response_code,
|
|
@@ -71,7 +71,7 @@ module Spree
|
|
|
71
71
|
# so supply the authorization itself as well as the credit card, rather than just the authorization code
|
|
72
72
|
response = payment_method.void(response_code, source, gateway_options)
|
|
73
73
|
else
|
|
74
|
-
# Standard
|
|
74
|
+
# Standard void usage
|
|
75
75
|
response = payment_method.void(response_code, gateway_options)
|
|
76
76
|
end
|
|
77
77
|
record_response(response)
|
|
@@ -165,15 +165,15 @@ module Spree
|
|
|
165
165
|
|
|
166
166
|
def protect_from_connection_error
|
|
167
167
|
yield
|
|
168
|
-
rescue
|
|
168
|
+
rescue Spree::PaymentConnectionError => e
|
|
169
169
|
failure!
|
|
170
170
|
gateway_error(e)
|
|
171
171
|
end
|
|
172
172
|
|
|
173
173
|
def gateway_error(error)
|
|
174
|
-
text = if error.is_a?
|
|
174
|
+
text = if error.is_a? Spree::PaymentResponse
|
|
175
175
|
error.params['message'] || error.params['response_reason_text'] || error.message
|
|
176
|
-
elsif error.is_a?
|
|
176
|
+
elsif error.is_a? Spree::PaymentConnectionError
|
|
177
177
|
Spree.t(:unable_to_connect_to_gateway)
|
|
178
178
|
else
|
|
179
179
|
error.to_s
|
data/app/models/spree/payment.rb
CHANGED
|
@@ -22,7 +22,7 @@ module Spree
|
|
|
22
22
|
|
|
23
23
|
def authorize(amount_in_cents, store_credit, gateway_options = {})
|
|
24
24
|
if store_credit.nil?
|
|
25
|
-
|
|
25
|
+
Spree::PaymentResponse.new(false, Spree.t('store_credit_payment_method.unable_to_find'), {}, {})
|
|
26
26
|
else
|
|
27
27
|
action = lambda do |store_credit|
|
|
28
28
|
store_credit.authorize(
|
|
@@ -58,7 +58,7 @@ module Spree
|
|
|
58
58
|
end
|
|
59
59
|
|
|
60
60
|
if event.blank?
|
|
61
|
-
|
|
61
|
+
Spree::PaymentResponse.new(false, Spree.t('store_credit_payment_method.unable_to_find'), {}, {})
|
|
62
62
|
else
|
|
63
63
|
capture(amount_in_cents, event.authorization_code, gateway_options)
|
|
64
64
|
end
|
|
@@ -111,14 +111,14 @@ module Spree
|
|
|
111
111
|
store_credit.with_lock do
|
|
112
112
|
if response = action.call(store_credit)
|
|
113
113
|
# note that we only need to return the auth code on an 'auth', but it's innocuous to always return
|
|
114
|
-
|
|
114
|
+
Spree::PaymentResponse.new(
|
|
115
115
|
true,
|
|
116
116
|
Spree.t('store_credit_payment_method.successful_action', action: action_name),
|
|
117
117
|
{},
|
|
118
118
|
authorization: auth_code || response
|
|
119
119
|
)
|
|
120
120
|
else
|
|
121
|
-
|
|
121
|
+
Spree::PaymentResponse.new(false, store_credit.errors.full_messages.to_sentence, {}, {})
|
|
122
122
|
end
|
|
123
123
|
end
|
|
124
124
|
end
|
|
@@ -128,7 +128,7 @@ module Spree
|
|
|
128
128
|
store_credit = StoreCreditEvent.find_by(authorization_code: auth_code).try(:store_credit)
|
|
129
129
|
|
|
130
130
|
if store_credit.nil?
|
|
131
|
-
|
|
131
|
+
Spree::PaymentResponse.new(
|
|
132
132
|
false,
|
|
133
133
|
Spree.t('store_credit_payment_method.unable_to_find_for_action', auth_code: auth_code, action: action_name),
|
|
134
134
|
{},
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
module Spree
|
|
2
|
+
# Lightweight value object representing a payment gateway response.
|
|
3
|
+
#
|
|
4
|
+
# This is Spree's native replacement for +ActiveMerchant::Billing::Response+.
|
|
5
|
+
# It carries the same interface so existing payment method implementations
|
|
6
|
+
# (Bogus, Check, StoreCredit, and third-party gateways) can return it without
|
|
7
|
+
# any callers needing to change.
|
|
8
|
+
#
|
|
9
|
+
# @example Successful authorization
|
|
10
|
+
# Spree::PaymentResponse.new(true, 'Transaction approved', {},
|
|
11
|
+
# authorization: 'ch_abc123',
|
|
12
|
+
# avs_result: { code: 'D' },
|
|
13
|
+
# cvv_result: { code: 'M', message: 'Match' },
|
|
14
|
+
# test: true)
|
|
15
|
+
#
|
|
16
|
+
# @example Failed charge
|
|
17
|
+
# Spree::PaymentResponse.new(false, 'Card declined', { message: 'Insufficient funds' })
|
|
18
|
+
#
|
|
19
|
+
class PaymentResponse
|
|
20
|
+
# @return [HashWithIndifferentAccess] raw gateway params
|
|
21
|
+
attr_reader :params
|
|
22
|
+
|
|
23
|
+
# @return [String] human-readable result message
|
|
24
|
+
attr_reader :message
|
|
25
|
+
|
|
26
|
+
# @return [Boolean] whether the response came from a test/sandbox environment
|
|
27
|
+
attr_reader :test
|
|
28
|
+
|
|
29
|
+
# @return [String, nil] gateway authorization / transaction reference
|
|
30
|
+
attr_reader :authorization
|
|
31
|
+
|
|
32
|
+
# @return [Hash] AVS (Address Verification System) result with +"code"+ key
|
|
33
|
+
attr_reader :avs_result
|
|
34
|
+
|
|
35
|
+
# @return [Hash] CVV result with +"code"+ and +"message"+ keys
|
|
36
|
+
attr_reader :cvv_result
|
|
37
|
+
|
|
38
|
+
# @param success [Boolean] whether the gateway action succeeded
|
|
39
|
+
# @param message [String] human-readable result message
|
|
40
|
+
# @param params [Hash] raw key/value pairs returned by the gateway
|
|
41
|
+
# @param options [Hash] additional metadata
|
|
42
|
+
# @option options [String] :authorization gateway transaction reference
|
|
43
|
+
# @option options [Hash] :avs_result must contain +:code+
|
|
44
|
+
# @option options [Hash] :cvv_result may contain +:code+ and +:message+
|
|
45
|
+
# @option options [Boolean] :test sandbox/test flag
|
|
46
|
+
def initialize(success, message, params = {}, options = {})
|
|
47
|
+
@success = success
|
|
48
|
+
@message = message
|
|
49
|
+
@params = params.with_indifferent_access
|
|
50
|
+
@test = options[:test] || false
|
|
51
|
+
@authorization = options[:authorization]
|
|
52
|
+
@avs_result = options[:avs_result] ? { 'code' => options[:avs_result][:code] } : { 'code' => nil }
|
|
53
|
+
@cvv_result = if options[:cvv_result]
|
|
54
|
+
{ 'code' => options[:cvv_result][:code], 'message' => options[:cvv_result][:message] }
|
|
55
|
+
else
|
|
56
|
+
{ 'code' => nil, 'message' => nil }
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# @return [Boolean] whether the gateway action succeeded
|
|
61
|
+
def success?
|
|
62
|
+
@success
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# @return [Boolean] whether the response came from a test/sandbox environment
|
|
66
|
+
def test?
|
|
67
|
+
@test
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
@@ -15,8 +15,6 @@ module Spree
|
|
|
15
15
|
can :read, Spree::OptionType
|
|
16
16
|
can :read, Spree::OptionValue
|
|
17
17
|
can :read, Spree::Product
|
|
18
|
-
can :read, Spree::ProductProperty
|
|
19
|
-
can :read, Spree::Property
|
|
20
18
|
can :read, Spree::State
|
|
21
19
|
can :read, Spree::Store
|
|
22
20
|
can :read, Spree::Taxon
|
|
@@ -26,9 +24,6 @@ module Spree
|
|
|
26
24
|
|
|
27
25
|
# Content pages
|
|
28
26
|
can :read, Spree::Policy
|
|
29
|
-
can :read, Spree::Page if defined?(Spree::Page)
|
|
30
|
-
can :read, Spree::Post if defined?(Spree::Post)
|
|
31
|
-
can :read, Spree::PostCategory if defined?(Spree::PostCategory)
|
|
32
27
|
|
|
33
28
|
# Order management for the user's own orders
|
|
34
29
|
can :create, Spree::Order
|
|
@@ -14,8 +14,6 @@ module Spree
|
|
|
14
14
|
can [:read, :admin], Spree::Variant
|
|
15
15
|
can [:read, :admin], Spree::OptionType
|
|
16
16
|
can [:read, :admin], Spree::OptionValue
|
|
17
|
-
can [:read, :admin], Spree::Property
|
|
18
|
-
can [:read, :admin], Spree::ProductProperty
|
|
19
17
|
can [:read, :admin], Spree::Metafield
|
|
20
18
|
can [:read, :admin], Spree::Taxon
|
|
21
19
|
can [:read, :admin], Spree::Taxonomy
|
|
@@ -14,8 +14,6 @@ module Spree
|
|
|
14
14
|
can :manage, Spree::Variant
|
|
15
15
|
can :manage, Spree::OptionType
|
|
16
16
|
can :manage, Spree::OptionValue
|
|
17
|
-
can :manage, Spree::Property
|
|
18
|
-
can :manage, Spree::ProductProperty
|
|
19
17
|
can :manage, Spree::Taxon
|
|
20
18
|
can :manage, Spree::Taxonomy
|
|
21
19
|
can :manage, Spree::Classification
|