spree_core 5.4.0.beta → 5.4.0.beta3
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 +2 -42
- 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 +21 -49
- 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 +60 -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/market.rb +1 -2
- data/app/models/spree/market_country.rb +17 -0
- data/app/models/spree/newsletter_subscriber.rb +0 -3
- data/app/models/spree/order/checkout.rb +0 -18
- data/app/models/spree/order.rb +22 -16
- 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 +5 -85
- 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/reimbursement.rb +0 -2
- data/app/models/spree/shipment.rb +0 -1
- data/app/models/spree/shipment_handler.rb +0 -2
- 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/newsletter/subscribe.rb +2 -2
- data/app/services/spree/products/duplicator.rb +0 -12
- data/app/services/spree/products/prepare_nested_attributes.rb +0 -12
- data/app/subscribers/spree/invitation_email_subscriber.rb +1 -1
- data/config/locales/en.yml +4 -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/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 -26
- 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/cli.rake +50 -0
- data/lib/tasks/core.rake +0 -265
- metadata +9 -111
- 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/filter_param.rb +0 -21
- 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/newsletter_subscriber/emails.rb +0 -12
- data/app/models/spree/order/emails.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/reimbursement/emails.rb +0 -11
- data/app/models/spree/shipment/emails.rb +0 -11
- 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/generators/spree/cursor_rules/cursor_rules_generator.rb +0 -19
- data/lib/generators/spree/cursor_rules/templates/spree_rules.mdc +0 -387
- data/lib/spree/core/controller_helpers/search.rb +0 -17
- data/lib/spree/core/importer/order.rb +0 -244
- data/lib/spree/core/importer/product.rb +0 -67
- data/lib/spree/core/importer.rb +0 -9
- 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
|
@@ -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
|
data/app/models/spree/product.rb
CHANGED
|
@@ -72,9 +72,6 @@ module Spree
|
|
|
72
72
|
|
|
73
73
|
has_many :product_option_types, -> { order(:position) }, dependent: :destroy, inverse_of: :product
|
|
74
74
|
has_many :option_types, through: :product_option_types
|
|
75
|
-
has_many :product_properties, dependent: :destroy, inverse_of: :product
|
|
76
|
-
has_many :properties, through: :product_properties
|
|
77
|
-
|
|
78
75
|
has_many :classifications, -> { order(created_at: :asc) }, dependent: :delete_all, inverse_of: :product
|
|
79
76
|
has_many :taxons, through: :classifications, before_remove: :remove_taxon
|
|
80
77
|
has_many :taxonomies, through: :taxons
|
|
@@ -200,24 +197,9 @@ module Spree
|
|
|
200
197
|
scope :by_source, ->(source) { send(source) }
|
|
201
198
|
scope :paused, -> { where(status: 'paused') }
|
|
202
199
|
scope :published, -> { where(status: 'active') }
|
|
203
|
-
scope :in_stock_items, -> { joins(:variants).merge(Spree::Variant.in_stock_or_backorderable) }
|
|
204
|
-
scope :out_of_stock_items, lambda {
|
|
205
|
-
joins(variants_including_master: :stock_items).
|
|
206
|
-
where(spree_variants: { track_inventory: true }).
|
|
207
|
-
where.not(id: Spree::Variant.where(track_inventory: false).pluck(:product_id).uniq).
|
|
208
|
-
where(spree_stock_items: { backorderable: false }).
|
|
209
|
-
group(:id).
|
|
210
|
-
having("SUM(#{Spree::StockItem.table_name}.count_on_hand) <= 0")
|
|
211
|
-
}
|
|
212
|
-
scope :out_of_stock, lambda {
|
|
213
|
-
joins(:stock_items).where("#{Spree::Variant.table_name}.track_inventory = ? OR #{Spree::StockItem.table_name}.count_on_hand <= ?", false, 0)
|
|
214
|
-
}
|
|
215
200
|
|
|
216
201
|
attr_accessor :option_values_hash
|
|
217
202
|
|
|
218
|
-
accepts_nested_attributes_for :product_properties, allow_destroy: true, reject_if: lambda { |pp|
|
|
219
|
-
pp[:property_id].blank? || (pp[:id].blank? && pp[:value].blank?)
|
|
220
|
-
}
|
|
221
203
|
accepts_nested_attributes_for(
|
|
222
204
|
:variants,
|
|
223
205
|
allow_destroy: true,
|
|
@@ -236,9 +218,9 @@ module Spree
|
|
|
236
218
|
|
|
237
219
|
self.whitelisted_ransackable_attributes = %w[description name slug discontinue_on status available_on created_at updated_at]
|
|
238
220
|
self.whitelisted_ransackable_associations = %w[taxons stores variants_including_master master variants tags labels
|
|
239
|
-
shipping_category classifications option_types
|
|
221
|
+
shipping_category classifications option_types]
|
|
240
222
|
self.whitelisted_ransackable_scopes = %w[not_discontinued search_by_name in_taxon price_between
|
|
241
|
-
multi_search
|
|
223
|
+
multi_search in_stock out_of_stock with_option_value_ids
|
|
242
224
|
ascend_by_price descend_by_price]
|
|
243
225
|
|
|
244
226
|
[
|
|
@@ -417,7 +399,7 @@ module Spree
|
|
|
417
399
|
# Returns the short description for the product
|
|
418
400
|
# @return [String]
|
|
419
401
|
def storefront_description
|
|
420
|
-
|
|
402
|
+
description
|
|
421
403
|
end
|
|
422
404
|
|
|
423
405
|
# Returns tax category for Product
|
|
@@ -479,13 +461,6 @@ module Spree
|
|
|
479
461
|
Products::Duplicator.call(product: self)
|
|
480
462
|
end
|
|
481
463
|
|
|
482
|
-
# use deleted? rather than checking the attribute directly. this
|
|
483
|
-
# allows extensions to override deleted? if they want to provide
|
|
484
|
-
# their own definition.
|
|
485
|
-
def deleted?
|
|
486
|
-
!!deleted_at
|
|
487
|
-
end
|
|
488
|
-
|
|
489
464
|
# determine if product is available.
|
|
490
465
|
# deleted products and products with status different than active
|
|
491
466
|
# are not available
|
|
@@ -513,14 +488,6 @@ module Spree
|
|
|
513
488
|
variants_including_master.any?(&:backordered?)
|
|
514
489
|
end
|
|
515
490
|
|
|
516
|
-
# split variants list into hash which shows mapping of opt value onto matching variants
|
|
517
|
-
# eg categorise_variants_from_option(color) => {"red" -> [...], "blue" -> [...]}
|
|
518
|
-
def categorise_variants_from_option(opt_type)
|
|
519
|
-
return {} unless option_types.include?(opt_type)
|
|
520
|
-
|
|
521
|
-
variants.active.group_by { |v| v.option_values.detect { |o| o.option_type == opt_type } }
|
|
522
|
-
end
|
|
523
|
-
|
|
524
491
|
def self.like_any(fields, values)
|
|
525
492
|
conditions = fields.product(values).map do |(field, value)|
|
|
526
493
|
arel_table[field].matches("%#{value}%")
|
|
@@ -537,48 +504,6 @@ module Spree
|
|
|
537
504
|
variants.active(current_currency).joins(:option_value_variants)
|
|
538
505
|
end
|
|
539
506
|
|
|
540
|
-
def empty_option_values?
|
|
541
|
-
options.empty? || options.any? do |opt|
|
|
542
|
-
opt.option_type.option_values.empty?
|
|
543
|
-
end
|
|
544
|
-
end
|
|
545
|
-
|
|
546
|
-
def property(property_name)
|
|
547
|
-
if product_properties.loaded?
|
|
548
|
-
product_properties.detect { |property| property.property.name == property_name }.try(:value)
|
|
549
|
-
else
|
|
550
|
-
product_properties.joins(:property).find_by(spree_properties: { name: property_name }).try(:value)
|
|
551
|
-
end
|
|
552
|
-
end
|
|
553
|
-
|
|
554
|
-
def set_property(property_name, property_value, property_presentation = property_name)
|
|
555
|
-
property_name = property_name.to_s.parameterize
|
|
556
|
-
ApplicationRecord.transaction do
|
|
557
|
-
# Manual first_or_create to work around Mobility bug
|
|
558
|
-
property = if Property.where(name: property_name).exists?
|
|
559
|
-
existing_property = Property.where(name: property_name).first
|
|
560
|
-
existing_property.presentation ||= property_presentation
|
|
561
|
-
existing_property.save
|
|
562
|
-
existing_property
|
|
563
|
-
else
|
|
564
|
-
Property.create(name: property_name, presentation: property_presentation)
|
|
565
|
-
end
|
|
566
|
-
|
|
567
|
-
product_property = if ProductProperty.where(product: self, property: property).exists?
|
|
568
|
-
ProductProperty.where(product: self, property: property).first
|
|
569
|
-
else
|
|
570
|
-
ProductProperty.new(product: self, property: property)
|
|
571
|
-
end
|
|
572
|
-
|
|
573
|
-
product_property.value = property_value
|
|
574
|
-
product_property.save!
|
|
575
|
-
end
|
|
576
|
-
end
|
|
577
|
-
|
|
578
|
-
def remove_property(property_name)
|
|
579
|
-
product_properties.joins(:property).find_by(spree_properties: { name: property_name.parameterize })&.destroy
|
|
580
|
-
end
|
|
581
|
-
|
|
582
507
|
def total_on_hand
|
|
583
508
|
@total_on_hand ||= if any_variants_not_track_inventory?
|
|
584
509
|
BigDecimal::INFINITY
|
|
@@ -668,9 +593,7 @@ module Spree
|
|
|
668
593
|
def taxons_for_store(store)
|
|
669
594
|
return if classification_count.zero?
|
|
670
595
|
|
|
671
|
-
|
|
672
|
-
taxons.loaded? ? taxons.find_all { |taxon| taxon.taxonomy.store_id == store.id } : taxons.for_store(store)
|
|
673
|
-
end
|
|
596
|
+
taxons.loaded? ? taxons.find_all { |taxon| taxon.taxonomy.store_id == store.id } : taxons.for_store(store)
|
|
674
597
|
end
|
|
675
598
|
|
|
676
599
|
def any_variant_in_stock_or_backorderable?
|
|
@@ -702,7 +625,7 @@ module Spree
|
|
|
702
625
|
|
|
703
626
|
def to_csv(store = nil)
|
|
704
627
|
store ||= stores.default || stores.first
|
|
705
|
-
properties_for_csv = if Spree::Config[:product_properties_enabled]
|
|
628
|
+
properties_for_csv = if respond_to?(:product_properties) && Spree::Config.respond_to?(:product_properties_enabled) && Spree::Config[:product_properties_enabled]
|
|
706
629
|
Spree::Property.order(:position).flat_map do |property|
|
|
707
630
|
[
|
|
708
631
|
property.name,
|
|
@@ -746,9 +669,6 @@ module Spree
|
|
|
746
669
|
|
|
747
670
|
def add_associations_from_prototype
|
|
748
671
|
if prototype_id && prototype = Spree::Prototype.find_by(id: prototype_id)
|
|
749
|
-
prototype.properties.each do |property|
|
|
750
|
-
product_properties.create(property: property, value: 'Placeholder')
|
|
751
|
-
end
|
|
752
672
|
self.option_types = prototype.option_types
|
|
753
673
|
self.taxons = prototype.taxons
|
|
754
674
|
end
|
|
@@ -190,26 +190,14 @@ module Spree
|
|
|
190
190
|
!!eligible_rules(promotable, options)
|
|
191
191
|
end
|
|
192
192
|
|
|
193
|
-
# We cache the rules to avoid multiple database queries
|
|
194
|
-
# this is useful for orders with many line items
|
|
195
|
-
#
|
|
196
|
-
# @return [Array<Spree::PromotionRule>]
|
|
197
|
-
def cached_rules
|
|
198
|
-
Rails.cache.fetch("#{cache_key_with_version}/rules") do
|
|
199
|
-
rules.to_a
|
|
200
|
-
end
|
|
201
|
-
rescue TypeError # when using null_store in test environment
|
|
202
|
-
rules.to_a
|
|
203
|
-
end
|
|
204
|
-
|
|
205
193
|
# eligible_rules returns an array of promotion rules where eligible? is true for the promotable
|
|
206
194
|
# if there are no such rules, an empty array is returned
|
|
207
195
|
# if the rules make this promotable ineligible, then nil is returned (i.e. this promotable is not eligible)
|
|
208
196
|
def eligible_rules(promotable, options = {})
|
|
209
197
|
# Promotions without rules are eligible by default.
|
|
210
|
-
return [] if
|
|
198
|
+
return [] if rules.none?
|
|
211
199
|
|
|
212
|
-
specific_rules =
|
|
200
|
+
specific_rules = rules.select { |rule| rule.applicable?(promotable) }
|
|
213
201
|
return [] if specific_rules.none?
|
|
214
202
|
|
|
215
203
|
rule_eligibility = Hash[specific_rules.map do |rule|
|
|
@@ -177,8 +177,8 @@ module Spree
|
|
|
177
177
|
|
|
178
178
|
# Check for applied adjustments.
|
|
179
179
|
discount = order.all_adjustments.promotion.eligible.detect do |p|
|
|
180
|
-
p.
|
|
181
|
-
Spree::CouponCode.unused.where(promotion_id: p.
|
|
180
|
+
p.source.promotion.code.try(:downcase) == coupon_code ||
|
|
181
|
+
Spree::CouponCode.unused.where(promotion_id: p.source.promotion_id, code: coupon_code).exists?
|
|
182
182
|
end
|
|
183
183
|
|
|
184
184
|
# Check for applied line items.
|
|
@@ -209,7 +209,7 @@ module Spree
|
|
|
209
209
|
end
|
|
210
210
|
|
|
211
211
|
def handle_coupon_code(discount, coupon_code)
|
|
212
|
-
Spree::CouponCode.unused.find_by(promotion_id: discount.
|
|
212
|
+
Spree::CouponCode.unused.find_by(promotion_id: discount.source.promotion_id, code: coupon_code)&.apply_order!(order)
|
|
213
213
|
end
|
|
214
214
|
|
|
215
215
|
def load_gift_card_code
|
|
@@ -4,9 +4,6 @@ module Spree
|
|
|
4
4
|
|
|
5
5
|
include Spree::Metadata
|
|
6
6
|
|
|
7
|
-
has_many :property_prototypes, class_name: 'Spree::PropertyPrototype'
|
|
8
|
-
has_many :properties, through: :property_prototypes, class_name: 'Spree::Property'
|
|
9
|
-
|
|
10
7
|
has_many :option_type_prototypes, class_name: 'Spree::OptionTypePrototype'
|
|
11
8
|
has_many :option_types, through: :option_type_prototypes, class_name: 'Spree::OptionType'
|
|
12
9
|
|
data/app/models/spree/refund.rb
CHANGED
|
@@ -36,6 +36,10 @@ module Spree
|
|
|
36
36
|
|
|
37
37
|
delegate :order, :currency, to: :payment
|
|
38
38
|
|
|
39
|
+
def amount=(amount)
|
|
40
|
+
self[:amount] = Spree::LocalizedNumber.parse(amount)
|
|
41
|
+
end
|
|
42
|
+
|
|
39
43
|
def money
|
|
40
44
|
Spree::Money.new(amount, currency: currency)
|
|
41
45
|
end
|
|
@@ -83,7 +87,7 @@ module Spree
|
|
|
83
87
|
update_order
|
|
84
88
|
end
|
|
85
89
|
|
|
86
|
-
# return
|
|
90
|
+
# return a payment response object if successful or else raise an error
|
|
87
91
|
def process!(credit_cents)
|
|
88
92
|
refund_total_in_cents = calculate_refund_amount(credit_cents)
|
|
89
93
|
|
|
@@ -102,7 +106,7 @@ module Spree
|
|
|
102
106
|
end
|
|
103
107
|
|
|
104
108
|
response
|
|
105
|
-
rescue
|
|
109
|
+
rescue Spree::PaymentConnectionError => e
|
|
106
110
|
Rails.logger.error(Spree.t(:gateway_error) + " #{e.inspect}")
|
|
107
111
|
raise Core::GatewayError, Spree.t(:unable_to_connect_to_gateway)
|
|
108
112
|
end
|
|
@@ -4,7 +4,6 @@ module Spree
|
|
|
4
4
|
|
|
5
5
|
include Spree::Core::NumberGenerator.new(prefix: 'RI', length: 9)
|
|
6
6
|
include Spree::NumberIdentifier
|
|
7
|
-
include Spree::Reimbursement::Emails
|
|
8
7
|
|
|
9
8
|
class IncompleteReimbursementError < StandardError; end
|
|
10
9
|
|
|
@@ -116,7 +115,6 @@ module Spree
|
|
|
116
115
|
if unpaid_amount_within_tolerance?
|
|
117
116
|
reimbursed!
|
|
118
117
|
reimbursement_success_hooks.each { |h| h.call self }
|
|
119
|
-
send_reimbursement_email
|
|
120
118
|
else
|
|
121
119
|
errored!
|
|
122
120
|
reimbursement_failure_hooks.each { |h| h.call self }
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
module Spree
|
|
2
2
|
class ShipmentHandler
|
|
3
|
-
include Spree::Shipment::Emails
|
|
4
3
|
include Spree::IntegrationsConcern
|
|
5
4
|
|
|
6
5
|
class << self
|
|
@@ -25,7 +24,6 @@ module Spree
|
|
|
25
24
|
@shipment.process_order_payments if Spree::Config[:auto_capture_on_dispatch]
|
|
26
25
|
@shipment.touch :shipped_at
|
|
27
26
|
update_order_shipment_state
|
|
28
|
-
send_shipped_email
|
|
29
27
|
end
|
|
30
28
|
|
|
31
29
|
protected
|
|
@@ -16,10 +16,10 @@ module Spree
|
|
|
16
16
|
find_by(name: DIGITAL_NAME)
|
|
17
17
|
end
|
|
18
18
|
|
|
19
|
+
# Returns true if this shipping category includes a digital shipping method
|
|
20
|
+
# @return [Boolean]
|
|
19
21
|
def includes_digital_shipping_method?
|
|
20
|
-
|
|
21
|
-
shipping_methods.digital.exists?
|
|
22
|
-
end
|
|
22
|
+
@includes_digital_shipping_method ||= shipping_methods.digital.exists?
|
|
23
23
|
end
|
|
24
24
|
end
|
|
25
25
|
end
|
data/app/models/spree/store.rb
CHANGED
|
@@ -75,7 +75,6 @@ module Spree
|
|
|
75
75
|
|
|
76
76
|
has_many :store_products, class_name: 'Spree::StoreProduct'
|
|
77
77
|
has_many :products, through: :store_products, class_name: 'Spree::Product'
|
|
78
|
-
has_many :product_properties, through: :products, class_name: 'Spree::ProductProperty'
|
|
79
78
|
has_many :variants, through: :products, class_name: 'Spree::Variant', source: :variants_including_master
|
|
80
79
|
has_many :stock_items, through: :variants, class_name: 'Spree::StockItem'
|
|
81
80
|
has_many :inventory_units, through: :variants, class_name: 'Spree::InventoryUnit'
|
|
@@ -93,17 +92,12 @@ module Spree
|
|
|
93
92
|
|
|
94
93
|
has_many :wishlists, class_name: 'Spree::Wishlist'
|
|
95
94
|
|
|
96
|
-
has_many :data_feeds, class_name: 'Spree::DataFeed'
|
|
97
|
-
|
|
98
95
|
belongs_to :default_country, class_name: 'Spree::Country'
|
|
99
96
|
belongs_to :checkout_zone, class_name: 'Spree::Zone'
|
|
100
97
|
|
|
101
98
|
has_many :reports, class_name: 'Spree::Report'
|
|
102
99
|
has_many :exports, class_name: 'Spree::Export'
|
|
103
100
|
|
|
104
|
-
has_many :posts, class_name: 'Spree::Post', dependent: :destroy, inverse_of: :store
|
|
105
|
-
has_many :post_categories, class_name: 'Spree::PostCategory', dependent: :destroy, inverse_of: :store
|
|
106
|
-
|
|
107
101
|
has_many :integrations, class_name: 'Spree::Integration'
|
|
108
102
|
|
|
109
103
|
has_many :gift_cards, class_name: 'Spree::GiftCard', dependent: :destroy
|
|
@@ -165,9 +159,7 @@ module Spree
|
|
|
165
159
|
after_create :ensure_default_market
|
|
166
160
|
after_create :ensure_default_taxonomies_are_created
|
|
167
161
|
after_create :ensure_default_automatic_taxons
|
|
168
|
-
after_create :ensure_default_post_categories_are_created
|
|
169
162
|
after_create :create_default_policies
|
|
170
|
-
after_commit :clear_cache
|
|
171
163
|
|
|
172
164
|
#
|
|
173
165
|
# Scopes
|
|
@@ -184,17 +176,15 @@ module Spree
|
|
|
184
176
|
|
|
185
177
|
# @deprecated The or_initialize behavior will be removed in Spree 5.5.
|
|
186
178
|
def self.default
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
Spree::
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
new(default: true)
|
|
197
|
-
end
|
|
179
|
+
# workaround for Mobility bug with first_or_initialize
|
|
180
|
+
if where(default: true).any?
|
|
181
|
+
where(default: true).first
|
|
182
|
+
else
|
|
183
|
+
Spree::Deprecation.warn(
|
|
184
|
+
'Spree::Store.default returning a new unpersisted store when no default store exists is deprecated ' \
|
|
185
|
+
'and will be removed in Spree 5.5. Please ensure a default store is created before calling Store.default.'
|
|
186
|
+
)
|
|
187
|
+
new(default: true)
|
|
198
188
|
end
|
|
199
189
|
end
|
|
200
190
|
|
|
@@ -296,9 +286,7 @@ module Spree
|
|
|
296
286
|
# @param country [Spree::Country] the country to get the states for
|
|
297
287
|
# @return [Array<Spree::State>]
|
|
298
288
|
def states_available_for_checkout(country)
|
|
299
|
-
|
|
300
|
-
country.states.to_a
|
|
301
|
-
end
|
|
289
|
+
country.states.to_a
|
|
302
290
|
end
|
|
303
291
|
|
|
304
292
|
# @deprecated Use {Spree::Zone.all} or {#countries_with_shipping_coverage} instead.
|
|
@@ -388,18 +376,6 @@ module Spree
|
|
|
388
376
|
|
|
389
377
|
private
|
|
390
378
|
|
|
391
|
-
def countries_available_for_checkout_cache_key
|
|
392
|
-
"#{cache_key_with_version}/countries_available_for_checkout"
|
|
393
|
-
end
|
|
394
|
-
|
|
395
|
-
def states_available_for_checkout_cache_key(country)
|
|
396
|
-
"#{cache_key_with_version}/states_available_for_checkout/#{country&.cache_key_with_version}"
|
|
397
|
-
end
|
|
398
|
-
|
|
399
|
-
def clear_cache
|
|
400
|
-
Rails.cache.delete('default_store')
|
|
401
|
-
end
|
|
402
|
-
|
|
403
379
|
def ensure_default_market
|
|
404
380
|
return if markets.exists?
|
|
405
381
|
|
|
@@ -463,21 +439,6 @@ module Spree
|
|
|
463
439
|
end
|
|
464
440
|
end
|
|
465
441
|
|
|
466
|
-
def ensure_default_post_categories_are_created
|
|
467
|
-
Spree::Events.disable do
|
|
468
|
-
[
|
|
469
|
-
translate_with_store_locale_fallback('spree.default_post_categories.resources'),
|
|
470
|
-
translate_with_store_locale_fallback('spree.default_post_categories.articles'),
|
|
471
|
-
translate_with_store_locale_fallback('spree.default_post_categories.news')
|
|
472
|
-
].each do |category_title|
|
|
473
|
-
# Use exists?/create pattern for safety
|
|
474
|
-
next if post_categories.where(title: category_title).exists?
|
|
475
|
-
|
|
476
|
-
post_categories.create(title: category_title)
|
|
477
|
-
end
|
|
478
|
-
end
|
|
479
|
-
end
|
|
480
|
-
|
|
481
442
|
def create_default_policies
|
|
482
443
|
Spree::Events.disable do
|
|
483
444
|
[
|
|
@@ -54,6 +54,10 @@ module Spree
|
|
|
54
54
|
extend Spree::DisplayMoney
|
|
55
55
|
money_methods :amount, :amount_used, :amount_remaining, :amount_authorized
|
|
56
56
|
|
|
57
|
+
def amount=(amount)
|
|
58
|
+
self[:amount] = Spree::LocalizedNumber.parse(amount)
|
|
59
|
+
end
|
|
60
|
+
|
|
57
61
|
self.whitelisted_ransackable_attributes = %w[user_id created_by_id amount currency type_id]
|
|
58
62
|
self.whitelisted_ransackable_associations = %w[type user created_by]
|
|
59
63
|
|
|
@@ -10,15 +10,11 @@ module Spree
|
|
|
10
10
|
has_many :variants, dependent: :nullify
|
|
11
11
|
|
|
12
12
|
before_save :set_default_category
|
|
13
|
-
after_update :delete_cache
|
|
14
|
-
after_create :delete_cache
|
|
15
13
|
|
|
16
14
|
self.whitelisted_ransackable_attributes = %w[name is_default tax_code]
|
|
17
15
|
|
|
18
16
|
def self.default
|
|
19
|
-
|
|
20
|
-
find_by(is_default: true)
|
|
21
|
-
end
|
|
17
|
+
find_by(is_default: true)
|
|
22
18
|
end
|
|
23
19
|
|
|
24
20
|
def set_default_category
|
|
@@ -28,11 +24,5 @@ module Spree
|
|
|
28
24
|
tax_category.update_columns(is_default: false, updated_at: Time.current)
|
|
29
25
|
end
|
|
30
26
|
end
|
|
31
|
-
|
|
32
|
-
private
|
|
33
|
-
|
|
34
|
-
def delete_cache
|
|
35
|
-
Rails.cache.delete('default_tax_category')
|
|
36
|
-
end
|
|
37
27
|
end
|
|
38
28
|
end
|
data/app/models/spree/taxon.rb
CHANGED
|
@@ -38,8 +38,6 @@ module Spree
|
|
|
38
38
|
has_one :store, through: :taxonomy
|
|
39
39
|
has_many :classifications, -> { order(:position) }, dependent: :destroy_async, inverse_of: :taxon
|
|
40
40
|
has_many :products, through: :classifications
|
|
41
|
-
# @deprecated Use Spree::Taxon#image (Active Storage) instead. Will be removed in Spree 5.5.
|
|
42
|
-
has_one :icon, as: :viewable, dependent: :destroy, class_name: 'Spree::TaxonImage'
|
|
43
41
|
|
|
44
42
|
has_many :prototype_taxons, class_name: 'Spree::PrototypeTaxon', dependent: :destroy
|
|
45
43
|
has_many :prototypes, through: :prototype_taxons, class_name: 'Spree::Prototype'
|
|
@@ -60,7 +58,6 @@ module Spree
|
|
|
60
58
|
validates :taxonomy, presence: true
|
|
61
59
|
validates :permalink, uniqueness: { case_sensitive: false, scope: [:parent_id, :taxonomy_id] }
|
|
62
60
|
validates :hide_from_nav, inclusion: { in: [true, false] }
|
|
63
|
-
validates_associated :icon
|
|
64
61
|
validate :check_for_root, on: :create
|
|
65
62
|
validate :parent_belongs_to_same_taxonomy
|
|
66
63
|
with_options length: { maximum: 255 }, allow_blank: true do
|
|
@@ -312,19 +309,6 @@ module Spree
|
|
|
312
309
|
end
|
|
313
310
|
end
|
|
314
311
|
|
|
315
|
-
# indicate which filters should be used for a taxon
|
|
316
|
-
# this method should be customized to your own site
|
|
317
|
-
def applicable_filters
|
|
318
|
-
Spree::Deprecation.warn('applicable_filters is deprecated and will be removed in Spree 5.5')
|
|
319
|
-
fs = []
|
|
320
|
-
# fs << ProductFilters.taxons_below(self)
|
|
321
|
-
## unless it's a root taxon? left open for demo purposes
|
|
322
|
-
|
|
323
|
-
fs << Spree::Core::ProductFilters.price_filter if Spree::Core::ProductFilters.respond_to?(:price_filter)
|
|
324
|
-
fs << Spree::Core::ProductFilters.brand_filter if Spree::Core::ProductFilters.respond_to?(:brand_filter)
|
|
325
|
-
fs
|
|
326
|
-
end
|
|
327
|
-
|
|
328
312
|
# Return meta_title if set otherwise generates from taxon name
|
|
329
313
|
def seo_title
|
|
330
314
|
meta_title.blank? ? name : meta_title
|