solidus_core 4.7.1 → 4.8.0

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.
Files changed (74) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +3 -0
  3. data/app/helpers/spree/base_helper.rb +3 -3
  4. data/app/helpers/spree/core/controller_helpers/auth.rb +1 -1
  5. data/app/helpers/spree/core/controller_helpers/common.rb +2 -2
  6. data/app/helpers/spree/core/controller_helpers/timezone.rb +55 -0
  7. data/app/helpers/spree/products_helper.rb +3 -3
  8. data/app/jobs/spree/base_job.rb +1 -1
  9. data/app/mailers/spree/base_mailer.rb +2 -2
  10. data/app/models/concerns/spree/user_methods.rb +4 -4
  11. data/app/models/spree/address.rb +1 -1
  12. data/app/models/spree/adjustment.rb +1 -1
  13. data/app/models/spree/calculator/flat_rate.rb +2 -2
  14. data/app/models/spree/calculator/shipping/flat_rate.rb +1 -1
  15. data/app/models/spree/calculator/shipping/flexi_rate.rb +1 -1
  16. data/app/models/spree/calculator/shipping/per_item.rb +1 -1
  17. data/app/models/spree/calculator/shipping/price_sack.rb +1 -1
  18. data/app/models/spree/calculator.rb +1 -1
  19. data/app/models/spree/country.rb +1 -1
  20. data/app/models/spree/customer_return.rb +7 -0
  21. data/app/models/spree/exchange.rb +4 -1
  22. data/app/models/spree/image/active_storage_attachment.rb +15 -0
  23. data/app/models/spree/image/paperclip_attachment.rb +3 -0
  24. data/app/models/spree/image.rb +4 -0
  25. data/app/models/spree/log_entry.rb +26 -22
  26. data/app/models/spree/money.rb +2 -2
  27. data/app/models/spree/order/payments.rb +1 -1
  28. data/app/models/spree/order.rb +15 -17
  29. data/app/models/spree/order_cancellations.rb +1 -0
  30. data/app/models/spree/order_mutex.rb +1 -1
  31. data/app/models/spree/order_shipping.rb +17 -0
  32. data/app/models/spree/order_updater.rb +1 -1
  33. data/app/models/spree/payment/processing.rb +0 -1
  34. data/app/models/spree/payment_create.rb +23 -0
  35. data/app/models/spree/payment_method/bogus_credit_card.rb +4 -0
  36. data/app/models/spree/payment_method/check.rb +4 -2
  37. data/app/models/spree/payment_method.rb +1 -1
  38. data/app/models/spree/price.rb +1 -1
  39. data/app/models/spree/product.rb +10 -7
  40. data/app/models/spree/product_option_type.rb +2 -0
  41. data/app/models/spree/refund.rb +17 -0
  42. data/app/models/spree/return_item/eligibility_validator/time_since_purchase.rb +1 -1
  43. data/app/models/spree/return_item.rb +10 -1
  44. data/app/models/spree/shipment.rb +5 -3
  45. data/app/models/spree/stock/inventory_unit_builder.rb +1 -0
  46. data/app/models/spree/stock/simple_coordinator.rb +9 -2
  47. data/app/models/spree/store.rb +8 -1
  48. data/app/models/spree/store_credit.rb +1 -1
  49. data/app/models/spree/tax_calculator/default.rb +2 -0
  50. data/app/models/spree/taxon.rb +5 -2
  51. data/app/models/spree/variant/pricing_options.rb +1 -1
  52. data/app/models/spree/variant/vat_price_generator.rb +1 -0
  53. data/app/models/spree/variant.rb +3 -3
  54. data/config/locales/en.yml +13 -0
  55. data/db/default/spree/states.rb +1 -1
  56. data/db/migrate/20260924120000_add_address_to_spree_stores.rb +9 -0
  57. data/lib/generators/solidus/install/app_templates/authentication/existing.rb +0 -2
  58. data/lib/generators/solidus/install/app_templates/frontend/starter.rb +19 -1
  59. data/lib/generators/solidus/install/app_templates/payment_method/paypal.rb +2 -1
  60. data/lib/generators/solidus/install/install_generator.rb +7 -7
  61. data/lib/spree/app_configuration.rb +51 -0
  62. data/lib/spree/core/search/base.rb +3 -1
  63. data/lib/spree/core/version.rb +2 -2
  64. data/lib/spree/core.rb +0 -1
  65. data/lib/spree/permitted_attributes.rb +3 -2
  66. data/lib/spree/preferences/statically_configurable.rb +2 -1
  67. data/lib/spree/testing_support/capybara_ext.rb +0 -10
  68. data/lib/spree/testing_support/factories/calculator_factory.rb +6 -0
  69. data/lib/spree/testing_support/factories/return_item_factory.rb +9 -1
  70. data/lib/spree/testing_support/factories/shipping_method_factory.rb +1 -1
  71. data/lib/spree/testing_support/factories/store_factory.rb +4 -0
  72. data/lib/spree/testing_support/order_walkthrough.rb +1 -1
  73. data/solidus_core.gemspec +3 -3
  74. metadata +13 -11
@@ -8,6 +8,10 @@ module Spree
8
8
  # * :payment_method_id Id of payment method used for this payment
9
9
  # * :source_attributes Attributes used to build the source of this payment. Usually a {CreditCard}
10
10
  # * :wallet_payment_source_id (Integer): The id of a {WalletPaymentSource} to use
11
+ # * :gateway_customer_profile_id, :gateway_payment_profile_id (String): Gateway
12
+ # identifiers for a new {CreditCard}, e.g. a one-time token. Raises
13
+ # ActiveRecord::RecordNotFound if either already belongs to a {CreditCard}
14
+ # owned by a different user.
11
15
  # @param request_env [Hash] rack env of user creating the payment
12
16
  # @param payment [Payment] Internal use only. Instead of making a new payment, change the attributes for an existing one.
13
17
  def initialize(order, attributes, payment: nil, request_env: {})
@@ -44,6 +48,7 @@ module Spree
44
48
  def build_source
45
49
  payment_method = payment.payment_method
46
50
  if source_attributes.present? && payment_method.try(:payment_source_class)
51
+ ensure_gateway_profile_ownership!(payment_method.payment_source_class)
47
52
  payment.source = payment_method.payment_source_class.new(source_attributes)
48
53
  payment.source.payment_method_id = payment_method.id
49
54
  if order && payment.source.respond_to?(:user=)
@@ -52,6 +57,24 @@ module Spree
52
57
  end
53
58
  end
54
59
 
60
+ # Gateway profile ids may only be submitted for a new source when they are
61
+ # unknown to the store (e.g. a one-time token) or already belong to the
62
+ # order's user. Raises if either id is stored on a {CreditCard} owned by a
63
+ # different user, so customers cannot pay with another customer's stored
64
+ # gateway credential.
65
+ def ensure_gateway_profile_ownership!(source_class)
66
+ return unless source_class <= Spree::CreditCard
67
+
68
+ %i[gateway_customer_profile_id gateway_payment_profile_id].each do |attribute|
69
+ value = source_attributes[attribute]
70
+ next if value.blank?
71
+
72
+ foreign_cards = Spree::CreditCard.where(attribute => value).where.not(user_id: nil)
73
+ foreign_cards = foreign_cards.where.not(user_id: order.user_id) if order&.user_id
74
+ raise ActiveRecord::RecordNotFound if foreign_cards.exists?
75
+ end
76
+ end
77
+
55
78
  def build_from_wallet_payment_source
56
79
  wallet_payment_source_id = source_attributes.fetch(:wallet_payment_source_id)
57
80
  raise(ActiveRecord::RecordNotFound) if order.user.nil?
@@ -83,6 +83,10 @@ module Spree
83
83
  %w[capture void credit]
84
84
  end
85
85
 
86
+ def can_credit?(payment)
87
+ payment.completed? && payment.credit_allowed > 0
88
+ end
89
+
86
90
  private
87
91
 
88
92
  def generate_profile_id(success)
@@ -6,16 +6,18 @@ module Spree
6
6
  %w[capture void credit]
7
7
  end
8
8
 
9
- # Indicates whether its possible to capture the payment
10
9
  def can_capture?(payment)
11
10
  ["checkout", "pending"].include?(payment.state)
12
11
  end
13
12
 
14
- # Indicates whether its possible to void the payment.
15
13
  def can_void?(payment)
16
14
  payment.state != "void"
17
15
  end
18
16
 
17
+ def can_credit?(payment)
18
+ payment.completed? && payment.credit_allowed > 0
19
+ end
20
+
19
21
  def capture(*)
20
22
  simulated_successful_billing_response
21
23
  end
@@ -156,7 +156,7 @@ module Spree
156
156
  end
157
157
 
158
158
  def auto_capture?
159
- auto_capture.nil? ? Spree::Config[:auto_capture] : auto_capture
159
+ auto_capture.nil? ? Spree::Config.auto_capture : auto_capture
160
160
  end
161
161
 
162
162
  # Check if given source is supported by this payment method
@@ -74,7 +74,7 @@ module Spree
74
74
  end
75
75
 
76
76
  def check_price
77
- self.currency ||= Spree::Config[:currency]
77
+ self.currency ||= Spree::Config.currency
78
78
  end
79
79
 
80
80
  def pricing_options
@@ -124,7 +124,7 @@ module Spree
124
124
  validates :meta_keywords, length: {maximum: 255}
125
125
  validates :meta_title, length: {maximum: 255}
126
126
  validates :name, presence: true
127
- validates :price, presence: true, if: proc { Spree::Config[:require_master_price] }
127
+ validates :price, presence: true, if: proc { Spree::Config.require_master_price }
128
128
  validates :slug, presence: true, uniqueness: {allow_blank: true, case_sensitive: true}
129
129
 
130
130
  attr_accessor :option_values_hash
@@ -355,14 +355,17 @@ module Spree
355
355
  run_callbacks(:touch)
356
356
  end
357
357
 
358
- # Iterate through this product's taxons and taxonomies and touch their timestamps in a batch
358
+ # Iterate through this product's taxons and taxonomies and touch their timestamps
359
359
  def touch_taxons
360
- taxons_to_touch = taxons.flat_map(&:self_and_ancestors).uniq
361
- unless taxons_to_touch.empty?
362
- Spree::Taxon.where(id: taxons_to_touch.map(&:id)).update_all(updated_at: Time.current)
360
+ taxons_to_touch = taxons.flat_map(&:self_and_ancestors).uniq.sort_by(&:id)
361
+ return if taxons_to_touch.empty?
363
362
 
364
- taxonomy_ids_to_touch = taxons_to_touch.flat_map(&:taxonomy_id).uniq
365
- Spree::Taxonomy.where(id: taxonomy_ids_to_touch).update_all(updated_at: Time.current)
363
+ time = Time.current
364
+ taxons_to_touch.each { |taxon| taxon.update_column(:updated_at, time) }
365
+
366
+ taxonomy_ids_to_touch = taxons_to_touch.map(&:taxonomy_id).uniq
367
+ Spree::Taxonomy.where(id: taxonomy_ids_to_touch).order(:id).each do |taxonomy|
368
+ taxonomy.touch(time:)
366
369
  end
367
370
  end
368
371
 
@@ -5,5 +5,7 @@ module Spree
5
5
  belongs_to :product, class_name: "Spree::Product", inverse_of: :product_option_types, touch: true
6
6
  belongs_to :option_type, class_name: "Spree::OptionType", inverse_of: :product_option_types
7
7
  acts_as_list scope: :product
8
+
9
+ delegate :name, :presentation, :option_values, to: :option_type
8
10
  end
9
11
  end
@@ -15,6 +15,7 @@ module Spree
15
15
  validates :amount, presence: true, numericality: {greater_than: 0}
16
16
 
17
17
  validate :amount_is_less_than_or_equal_to_allowed_amount, on: :create
18
+ validate :payment_is_in_refundable_state, on: :create
18
19
 
19
20
  attr_reader :perform_response
20
21
 
@@ -91,6 +92,22 @@ module Spree
91
92
  end
92
93
  end
93
94
 
95
+ def payment_is_in_refundable_state
96
+ return if payment.nil? || Spree::Config.refundable_payment_states.include?(payment.state)
97
+
98
+ if Spree::Config.require_refundable_payment_state
99
+ errors.add(:payment, :not_refundable)
100
+ else
101
+ Spree.deprecator.warn(
102
+ "Creating a refund for a payment in the '#{payment.state}' state is deprecated " \
103
+ "and will become a validation error in Solidus 5.0. Refunds should only be created " \
104
+ "for payments in one of these states: #{Spree::Config.refundable_payment_states.join(", ")}. " \
105
+ "Set `Spree::Config.require_refundable_payment_state = true` to adopt the new " \
106
+ "behavior early."
107
+ )
108
+ end
109
+ end
110
+
94
111
  def update_order
95
112
  payment.order.recalculate
96
113
  end
@@ -5,7 +5,7 @@ module Spree
5
5
  module EligibilityValidator
6
6
  class TimeSincePurchase < Spree::ReturnItem::EligibilityValidator::BaseValidator
7
7
  def eligible_for_return?
8
- if (@return_item.inventory_unit.order.completed_at + Spree::Config[:return_eligibility_number_of_days].days) > Time.current
8
+ if (@return_item.inventory_unit.order.completed_at + Spree::Config.return_eligibility_number_of_days.days) > Time.current
9
9
  true
10
10
  else
11
11
  add_error(:number_of_days, I18n.t("spree.return_item_time_period_ineligible"))
@@ -41,6 +41,7 @@ module Spree
41
41
 
42
42
  validate :eligible_exchange_variant
43
43
  validate :belongs_to_same_customer_order
44
+ validate :belongs_to_return_authorization_order, if: -> { inventory_unit_id_changed? || return_authorization_id_changed? }
44
45
  validate :validate_acceptance_status_for_reimbursement
45
46
  validate :validate_no_other_completed_return_items
46
47
 
@@ -179,7 +180,7 @@ module Spree
179
180
  end
180
181
 
181
182
  def currency
182
- return_authorization.try(:currency) || Spree::Config[:currency]
183
+ return_authorization.try(:currency) || Spree::Config.currency
183
184
  end
184
185
 
185
186
  private
@@ -226,6 +227,14 @@ module Spree
226
227
  end
227
228
  end
228
229
 
230
+ def belongs_to_return_authorization_order
231
+ return unless return_authorization && inventory_unit
232
+
233
+ if return_authorization.order_id != inventory_unit.order_id
234
+ errors.add(:base, I18n.t("spree.return_items_cannot_be_associated_with_multiple_orders"))
235
+ end
236
+ end
237
+
229
238
  def eligible_exchange_variant
230
239
  return unless exchange_variant && exchange_variant_id_changed?
231
240
  unless eligible_exchange_variants.include?(exchange_variant)
@@ -55,7 +55,7 @@ module Spree
55
55
  def can_transition_from_pending_to_ready?
56
56
  order.can_ship? &&
57
57
  inventory_units.all? { |iu| iu.shipped? || iu.allow_ship? || iu.canceled? } &&
58
- (order.paid? || !Spree::Config[:require_payment_to_ship])
58
+ (order.paid? || !Spree::Config.require_payment_to_ship)
59
59
  end
60
60
 
61
61
  def can_transition_from_canceled_to_ready?
@@ -83,7 +83,7 @@ module Spree
83
83
  end
84
84
 
85
85
  def currency
86
- order ? order.currency : Spree::Config[:currency]
86
+ order ? order.currency : Spree::Config.currency
87
87
  end
88
88
 
89
89
  # @return [BigDecimal] the amount of this shipment, taking into
@@ -229,6 +229,8 @@ module Spree
229
229
  self.state =
230
230
  if shipped?
231
231
  "shipped"
232
+ elsif inventory_units.none?
233
+ "pending"
232
234
  elsif order.canceled? || inventory_units.all?(&:canceled?)
233
235
  "canceled"
234
236
  elsif !order.can_ship?
@@ -267,7 +269,7 @@ module Spree
267
269
  def to_package
268
270
  package = Stock::Package.new(stock_location)
269
271
  package.shipment = self
270
- inventory_units.includes(variant: :product).joins(:variant).group_by(&:state).each do |state, state_inventory_units|
272
+ inventory_units.not_canceled.includes(variant: :product).joins(:variant).group_by(&:state).each do |state, state_inventory_units|
271
273
  package.add_multiple state_inventory_units, state.to_sym
272
274
  end
273
275
  package
@@ -8,6 +8,7 @@ module Spree
8
8
  end
9
9
 
10
10
  def units
11
+ ActiveRecord::Associations::Preloader.new(records: @order.line_items, associations: {variant: :product}).call
11
12
  @order.line_items.flat_map do |line_item|
12
13
  build_units(line_item, line_item.quantity)
13
14
  end
@@ -12,7 +12,7 @@ module Spree
12
12
  # * Combine allocated and on hand inventory into a single shipment per-location
13
13
  #
14
14
  # Allocation logic can be changed using a custom class (as
15
- # configured in Spree::Config::stock_allocator_class )
15
+ # configured in Spree::Config.stock.allocator_class)
16
16
  #
17
17
  # After allocation, splitters are run on each Package (as configured in
18
18
  # Spree::Config.environment.stock_splitters)
@@ -27,7 +27,14 @@ module Spree
27
27
  :filtered_stock_locations, :inventory_units_by_variant, :desired,
28
28
  :availability, :allocator, :packages
29
29
 
30
- def initialize(order, inventory_units = nil)
30
+ def initialize(order, inventory_units_deprecated = nil, inventory_units: nil)
31
+ if inventory_units_deprecated
32
+ Spree.deprecator.warn "Using the `inventory_units` positional " \
33
+ "argument is deprecated in favor of using the keyword argument. "
34
+
35
+ inventory_units ||= inventory_units_deprecated
36
+ end
37
+
31
38
  @order = order
32
39
  @inventory_units =
33
40
  inventory_units || Spree::Config.stock.inventory_unit_builder_class.new(order).units
@@ -17,6 +17,8 @@ module Spree
17
17
 
18
18
  has_many :orders, class_name: "Spree::Order"
19
19
 
20
+ belongs_to :address, class_name: "Spree::Address", optional: true, validate: true
21
+
20
22
  validates :code, presence: true, uniqueness: {allow_blank: true, case_sensitive: true}
21
23
  validates :name, presence: true
22
24
  validates :url, presence: true
@@ -25,7 +27,7 @@ module Spree
25
27
  self.allowed_ransackable_attributes = %w[name url code]
26
28
 
27
29
  before_save :ensure_default_exists_and_is_unique
28
- before_destroy :validate_not_default
30
+ before_destroy :validate_not_default, prepend: true
29
31
 
30
32
  enum :reverse_charge_status, {
31
33
  disabled: 0,
@@ -51,6 +53,10 @@ module Spree
51
53
  end
52
54
  end
53
55
 
56
+ def address_attributes=(attributes)
57
+ self.address = Spree::Address.immutable_merge(address, attributes)
58
+ end
59
+
54
60
  def self.default
55
61
  where(default: true).first || new
56
62
  end
@@ -73,6 +79,7 @@ module Spree
73
79
  def validate_not_default
74
80
  if default
75
81
  errors.add(:base, :cannot_destroy_default_store)
82
+ throw :abort
76
83
  end
77
84
  end
78
85
  end
@@ -209,7 +209,7 @@ class Spree::StoreCredit < Spree::PaymentSource
209
209
  def create_credit_record(amount, action_attributes = {})
210
210
  # Setting credit_to_new_allocation to true will create a new allocation anytime #credit is called
211
211
  # If it is not set, it will update the store credit's amount in place
212
- credit = if Spree::Config[:credit_to_new_allocation]
212
+ credit = if Spree::Config.credit_to_new_allocation
213
213
  Spree::StoreCredit.new(create_credit_record_params(amount))
214
214
  else
215
215
  self.amount_used = amount_used - amount
@@ -23,6 +23,8 @@ module Spree
23
23
  #
24
24
  # @return [Spree::Tax::OrderTax] the calculated taxes for the order
25
25
  def calculate
26
+ ActiveRecord::Associations::Preloader.new(records: order.line_items, associations: {variant: :product}).call
27
+
26
28
  Spree::Tax::OrderTax.new(
27
29
  order_id: order.id,
28
30
  order_taxes: order_rates,
@@ -140,8 +140,11 @@ module Spree
140
140
  private
141
141
 
142
142
  def touch_ancestors_and_taxonomy
143
- # Touches all ancestors at once to avoid recursive taxonomy touch, and reduce queries.
144
- self.class.default_scoped.where(id: ancestors.pluck(:id)).update_all(updated_at: Time.current)
143
+ # Touches ancestors directly rather than through #touch to avoid a recursive taxonomy touch.
144
+ time = Time.current
145
+ self.class.default_scoped.where(id: ancestors.pluck(:id)).order(:id).each do |ancestor|
146
+ ancestor.update_column(:updated_at, time)
147
+ end
145
148
  # Have taxonomy touch happen in #touch_ancestors_and_taxonomy rather than association option in order for imports to override.
146
149
  taxonomy.try!(:touch)
147
150
  end
@@ -54,7 +54,7 @@ module Spree
54
54
  # @return [Spree::Variant::PricingOptions] pricing options for pricing a line item
55
55
  def self.from_context(context)
56
56
  new(
57
- currency: context.current_store.try!(:default_currency).presence || Spree::Config[:currency],
57
+ currency: context.current_store.try!(:default_currency).presence || Spree::Config.currency,
58
58
  country_iso: context.current_store.try!(:cart_tax_country_iso).presence
59
59
  )
60
60
  end
@@ -25,6 +25,7 @@ module Spree
25
25
  def run
26
26
  # Early return if there is no VAT rates in the current store.
27
27
  return if !variant.tax_category || variant_vat_rates.empty?
28
+ return if variant.default_price&.amount.nil?
28
29
 
29
30
  country_isos_requiring_price.each do |country_iso|
30
31
  # Don't re-create the default price
@@ -400,17 +400,17 @@ module Spree
400
400
 
401
401
  # Ensures a new variant takes the product master price when price is not supplied
402
402
  def set_price
403
- self.price = product.master.price if price.nil? && Spree::Config[:require_master_price] && !is_master?
403
+ self.price = product.master.price if price.nil? && Spree::Config.require_master_price && !is_master?
404
404
  end
405
405
 
406
406
  def check_price
407
- if price.nil? && Spree::Config[:require_master_price] && is_master?
407
+ if price.nil? && Spree::Config.require_master_price && is_master?
408
408
  errors.add :price, "Must supply price for variant or master.price for product."
409
409
  end
410
410
  end
411
411
 
412
412
  def set_cost_currency
413
- self.cost_currency = Spree::Config[:currency] if cost_currency.blank?
413
+ self.cost_currency = Spree::Config.currency if cost_currency.blank?
414
414
  end
415
415
 
416
416
  def create_stock_items
@@ -158,6 +158,9 @@ en:
158
158
  display_on: Display
159
159
  name: Name
160
160
  preference_source: Preference Source
161
+ preferred_server: Server
162
+ preferred_test_mode: Test Mode
163
+ store_ids: Stores
161
164
  type: Type
162
165
  spree/price:
163
166
  amount: Price
@@ -191,6 +194,7 @@ en:
191
194
  sku: Master SKU
192
195
  slug: Slug
193
196
  tax_category: Tax Category
197
+ taxon_ids: Categories
194
198
  weight: Weight
195
199
  width: Width
196
200
  spree/product_property:
@@ -395,12 +399,15 @@ en:
395
399
  tax_code: Tax Code
396
400
  spree/tax_rate:
397
401
  amount: Rate
402
+ calculator_type: Calculator
398
403
  expires_at: Expiration Date
399
404
  included_in_price: Included in Price
405
+ level: Tax Rate Level
400
406
  name: Name
401
407
  show_rate_in_label: Show Rate in Label
402
408
  starts_at: Start Date
403
409
  tax_categories: Tax Categories
410
+ tax_category_ids: Tax Categories
404
411
  spree/taxon:
405
412
  description: Description
406
413
  icon: Icon
@@ -408,6 +415,7 @@ en:
408
415
  meta_keywords: Meta Keywords
409
416
  meta_title: Meta Title
410
417
  name: Name
418
+ parent_id: Parent Category
411
419
  permalink: Permalink
412
420
  position: Position
413
421
  spree/taxonomy:
@@ -495,6 +503,8 @@ en:
495
503
  attributes:
496
504
  amount:
497
505
  greater_than_allowed: is greater than the allowed amount.
506
+ payment:
507
+ not_refundable: cannot be refunded in its current state.
498
508
  spree/reimbursement:
499
509
  attributes:
500
510
  base:
@@ -1130,6 +1140,7 @@ en:
1130
1140
  choose_currency: Choose Currency
1131
1141
  choose_dashboard_locale: Choose Dashboard Locale
1132
1142
  choose_dashboard_theme: Choose Dashboard Theme
1143
+ choose_dashboard_timezone: Choose Dashboard Timezone
1133
1144
  choose_location: Choose Location
1134
1145
  choose_reason: Choose Reason
1135
1146
  city: City
@@ -1942,6 +1953,7 @@ en:
1942
1953
  payment_could_not_be_created: Payment could not be created.
1943
1954
  payment_identifier: Payment Identifier
1944
1955
  payment_information: Payment Information
1956
+ payment_is_not_refundable: This payment cannot be refunded in its current state.
1945
1957
  payment_method: Payment Method
1946
1958
  payment_method_not_supported: That payment method is unsupported. Please choose another one.
1947
1959
  payment_method_settings_warning: If you are changing the payment method type, you must save first before you can edit the payment method settings
@@ -2093,6 +2105,7 @@ en:
2093
2105
  return_items: Return Items
2094
2106
  return_items_cannot_be_associated_with_multiple_orders: Return items cannot be associated with multiple orders.
2095
2107
  return_items_cannot_be_created_for_inventory_units_that_are_already_awaiting_exchange: Return items cannot be created for inventory units that are already awaiting exchange.
2108
+ return_items_must_have_shipped_inventory_units: Return items can only be created for shipped inventory units.
2096
2109
  return_number: Return Number
2097
2110
  return_quantity: Return Quantity
2098
2111
  return_reasons: Return Reasons
@@ -13,7 +13,7 @@ ActiveRecord::Base.transaction do
13
13
  carmen_country = Carmen::Country.coded(country.iso)
14
14
  next unless carmen_country.subregions?
15
15
 
16
- if Spree::Config[:countries_that_use_nested_subregions].include? country.iso
16
+ if Spree::Config.countries_that_use_nested_subregions.include? country.iso
17
17
  create_states(carmen_country.subregions.flat_map(&:subregions), country)
18
18
  else
19
19
  create_states(carmen_country.subregions, country)
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ class AddAddressToSpreeStores < ActiveRecord::Migration[7.0]
4
+ def change
5
+ change_table :spree_stores do |t|
6
+ t.references :address, type: :integer, foreign_key: {to_table: :spree_addresses}
7
+ end
8
+ end
9
+ end
@@ -4,9 +4,7 @@ begin
4
4
  user_class.classify.constantize
5
5
  rescue NameError
6
6
  say_status :error, "Can't find an existing user class named #{user_class.classify}, plese set up one before using this authentication option.", :red
7
- # rubocop:disable Rails/Exit
8
7
  abort
9
- # rubocop:enable Rails/Exit
10
8
  end
11
9
 
12
10
  generate "spree:custom_user #{user_class.shellescape}"
@@ -1 +1,19 @@
1
- apply "https://github.com/solidusio/solidus_starter_frontend/raw/v4.7/template.rb"
1
+ # frozen_string_literal: true
2
+
3
+ template =
4
+ ENV["SOLIDUS_STOREFRONT_TEMPLATE"] ||
5
+ begin
6
+ version = Spree.solidus_version if defined?(Spree) && Spree.respond_to?(:solidus_version)
7
+ gem_version = version ? Gem::Version.new(version) : nil
8
+
9
+ ref =
10
+ if gem_version && !gem_version.prerelease?
11
+ "v#{gem_version.segments[0, 2].join(".")}"
12
+ else
13
+ "main"
14
+ end
15
+
16
+ "https://github.com/solidusio/solidus/raw/#{ref}/storefront/template.rb"
17
+ end
18
+
19
+ apply template
@@ -1,5 +1,6 @@
1
1
  unless Bundler.locked_gems.dependencies["solidus_paypal_commerce_platform"]
2
- bundle_command "add solidus_paypal_commerce_platform --version='~> 1.0'"
2
+ # The released gem uses the old enum syntax and breaks on recent Ruby/Rails, so install from GitHub.
3
+ bundle_command "add solidus_paypal_commerce_platform --github solidusio/solidus_paypal_commerce_platform"
3
4
  end
4
5
 
5
6
  generate "solidus_paypal_commerce_platform:install --migrate=#{options[:migrate]}"
@@ -126,7 +126,7 @@ module Solidus
126
126
  def install_file_attachment
127
127
  if options[:active_storage]
128
128
  say_status :assets, "Active Storage", :green
129
- rake "active_storage:install"
129
+ rake "active_storage:install", abort_on_failure: true
130
130
  else
131
131
  say_status :assets, "Paperclip", :green
132
132
  gsub_file "config/initializers/spree.rb", "::ActiveStorageAttachment", "::PaperclipAttachment"
@@ -158,19 +158,19 @@ module Solidus
158
158
 
159
159
  def install_migrations
160
160
  say_status :copying, "migrations"
161
- rake "railties:install:migrations"
161
+ rake "railties:install:migrations", abort_on_failure: true
162
162
  end
163
163
 
164
164
  def create_database
165
165
  say_status :creating, "database"
166
- rake "db:create"
166
+ rake "db:create", abort_on_failure: true
167
167
  end
168
168
 
169
169
  def run_migrations
170
170
  if @run_migrations
171
171
  say_status :running, "migrations"
172
172
 
173
- rake "db:migrate"
173
+ rake "db:migrate", abort_on_failure: true
174
174
  else
175
175
  say_status :skipping, "migrations (don't forget to run rake db:migrate)"
176
176
  end
@@ -178,8 +178,8 @@ module Solidus
178
178
 
179
179
  def install_subcomponents
180
180
  apply_template_for :authentication, @selected_authentication
181
- apply_template_for :frontend, @selected_frontend
182
181
  apply_template_for :payment_method, @selected_payment_method
182
+ apply_template_for :frontend, @selected_frontend
183
183
  end
184
184
 
185
185
  def install_solidus_admin
@@ -200,7 +200,7 @@ module Solidus
200
200
  rake_options << "ADMIN_EMAIL=#{options[:admin_email]}" if options[:admin_email]
201
201
  rake_options << "ADMIN_PASSWORD=#{options[:admin_password]}" if options[:admin_password]
202
202
 
203
- rake("db:seed #{rake_options.join(" ")}")
203
+ rake("db:seed #{rake_options.join(" ")}", abort_on_failure: true)
204
204
  else
205
205
  say_status :skipping, "seed data (you can always run rake db:seed)"
206
206
  end
@@ -209,7 +209,7 @@ module Solidus
209
209
  def load_sample_data
210
210
  if @load_sample_data
211
211
  say_status :loading, "sample data"
212
- rake "spree_sample:load"
212
+ rake "spree_sample:load", abort_on_failure: true
213
213
  else
214
214
  say_status :skipping, "sample data (you can always run rake spree_sample:load)"
215
215
  end