spree_core 4.1.13 → 4.2.0.rc4

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 (150) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/spree/base_controller.rb +1 -2
  3. data/app/finders/spree/addresses/find.rb +1 -12
  4. data/app/finders/spree/base_finder.rb +14 -0
  5. data/app/finders/spree/countries/find.rb +11 -3
  6. data/app/finders/spree/credit_cards/find.rb +2 -2
  7. data/app/finders/spree/orders/find_current.rb +1 -1
  8. data/app/helpers/spree/base_helper.rb +61 -20
  9. data/app/helpers/spree/mail_helper.rb +29 -0
  10. data/app/helpers/spree/products_helper.rb +2 -1
  11. data/app/mailers/spree/base_mailer.rb +19 -5
  12. data/app/mailers/spree/order_mailer.rb +13 -4
  13. data/app/mailers/spree/reimbursement_mailer.rb +4 -2
  14. data/app/mailers/spree/shipment_mailer.rb +4 -2
  15. data/app/models/concerns/spree/default_price.rb +3 -6
  16. data/app/models/concerns/spree/user_methods.rb +11 -5
  17. data/app/models/concerns/spree/user_payment_source.rb +1 -1
  18. data/app/models/spree/ability.rb +45 -34
  19. data/app/models/spree/address.rb +17 -1
  20. data/app/models/spree/adjustment.rb +1 -0
  21. data/app/models/spree/app_configuration.rb +4 -0
  22. data/app/models/spree/app_dependencies.rb +4 -2
  23. data/app/models/spree/base.rb +5 -0
  24. data/app/models/spree/credit_card.rb +5 -0
  25. data/app/models/spree/fulfilment_changer.rb +58 -16
  26. data/app/models/spree/inventory_unit.rb +2 -7
  27. data/app/models/spree/line_item.rb +8 -7
  28. data/app/models/spree/log_entry.rb +1 -1
  29. data/app/models/spree/option_type.rb +7 -1
  30. data/app/models/spree/order.rb +27 -5
  31. data/app/models/spree/order/payments.rb +10 -2
  32. data/app/models/spree/payment.rb +18 -4
  33. data/app/models/spree/payment/processing.rb +2 -2
  34. data/app/models/spree/payment_method.rb +3 -3
  35. data/app/models/spree/preferences/store.rb +1 -1
  36. data/app/models/spree/price.rb +25 -6
  37. data/app/models/spree/product.rb +29 -9
  38. data/app/models/spree/promotion.rb +10 -15
  39. data/app/models/spree/promotion/rules/product.rb +2 -1
  40. data/app/models/spree/promotion/rules/user.rb +2 -1
  41. data/app/models/spree/promotion_handler/coupon.rb +1 -1
  42. data/app/models/spree/promotion_handler/promotion_duplicator.rb +9 -3
  43. data/app/models/spree/refund.rb +2 -2
  44. data/app/models/spree/reimbursement.rb +2 -0
  45. data/app/models/spree/return_item/eligibility_validator/default.rb +0 -2
  46. data/app/models/spree/return_item/eligibility_validator/{r_m_a_required.rb → rma_required.rb} +0 -0
  47. data/app/models/spree/shipment.rb +3 -6
  48. data/app/models/spree/shipping_method.rb +1 -5
  49. data/app/models/spree/shipping_rate.rb +2 -11
  50. data/app/models/spree/stock/availability_validator.rb +3 -4
  51. data/app/models/spree/stock_item.rb +1 -5
  52. data/app/models/spree/stock_location.rb +13 -2
  53. data/app/models/spree/store.rb +51 -2
  54. data/app/models/spree/store_credit.rb +1 -1
  55. data/app/models/spree/variant.rb +16 -10
  56. data/app/models/spree/zone.rb +17 -4
  57. data/app/presenters/spree/variant_presenter.rb +9 -1
  58. data/app/presenters/spree/variants/option_types_presenter.rb +1 -0
  59. data/app/services/spree/account/addresses/create.rb +6 -1
  60. data/app/services/spree/account/addresses/{base.rb → helper.rb} +1 -3
  61. data/app/services/spree/account/addresses/update.rb +6 -1
  62. data/app/services/spree/compare_line_items.rb +4 -2
  63. data/app/sorters/spree/base_sorter.rb +35 -0
  64. data/app/sorters/spree/orders/sort.rb +1 -37
  65. data/app/sorters/spree/products/sort.rb +9 -32
  66. data/app/validators/email_validator.rb +1 -1
  67. data/app/views/layouts/spree/base_mailer.html.erb +45 -40
  68. data/app/views/spree/order_mailer/cancel_email.html.erb +19 -25
  69. data/app/views/spree/order_mailer/cancel_email.text.erb +24 -2
  70. data/app/views/spree/order_mailer/confirm_email.html.erb +18 -65
  71. data/app/views/spree/order_mailer/confirm_email.text.erb +2 -1
  72. data/app/views/spree/order_mailer/store_owner_notification_email.html.erb +23 -0
  73. data/app/views/spree/order_mailer/store_owner_notification_email.text.erb +38 -0
  74. data/app/views/spree/reimbursement_mailer/reimbursement_email.html.erb +53 -58
  75. data/app/views/spree/reimbursement_mailer/reimbursement_email.text.erb +3 -1
  76. data/app/views/spree/shared/_base_mailer_footer.html.erb +6 -14
  77. data/app/views/spree/shared/_base_mailer_header.html.erb +12 -32
  78. data/app/views/spree/shared/_base_mailer_stylesheets.html.erb +293 -625
  79. data/app/views/spree/shared/_purchased_items_table.html.erb +60 -0
  80. data/app/views/spree/shared/purchased_items_table/_adjustment.html.erb +13 -0
  81. data/app/views/spree/shared/purchased_items_table/_line_item.html.erb +27 -0
  82. data/app/views/spree/shared/purchased_items_table/_subtotal.html.erb +13 -0
  83. data/app/views/spree/shared/purchased_items_table/_total.html.erb +13 -0
  84. data/app/views/spree/shipment_mailer/shipped_email.html.erb +31 -36
  85. data/app/views/spree/shipment_mailer/shipped_email.text.erb +2 -1
  86. data/config/initializers/assets.rb +1 -0
  87. data/config/initializers/inflections.rb +3 -0
  88. data/config/initializers/rails61_fixes.rb +3 -0
  89. data/config/locales/en.yml +145 -19
  90. data/db/default/spree/countries.rb +10 -4
  91. data/db/default/spree/states.rb +42 -5
  92. data/db/default/spree/stores.rb +17 -12
  93. data/db/default/spree/zones.rb +5 -2
  94. data/db/migrate/20130326175857_add_stock_location_to_rma.rb +1 -1
  95. data/db/migrate/20140309033438_create_store_from_preferences.rb +1 -1
  96. data/db/migrate/20191017121054_add_supported_currencies_to_store.rb +10 -0
  97. data/db/migrate/20200102141311_add_social_to_spree_stores.rb +3 -0
  98. data/db/migrate/20200308210757_add_default_locale_to_spree_store.rb +7 -0
  99. data/db/migrate/20200310145140_add_customer_support_email_to_spree_store.rb +7 -0
  100. data/db/migrate/20200421095017_add_compare_at_amount_to_spree_prices.rb +7 -0
  101. data/db/migrate/20200423123001_add_default_country_id_to_spree_store.rb +9 -0
  102. data/db/migrate/20200430072209_add_footer_fields_to_spree_stores.rb +8 -0
  103. data/db/migrate/20200513154939_add_show_property_to_spree_product_properties.rb +5 -0
  104. data/db/migrate/20200607161221_add_store_owner_order_notification_delivered_to_spree_orders.rb +7 -0
  105. data/db/migrate/20200607161222_add_new_order_notifications_email_to_spree_stores.rb +7 -0
  106. data/db/migrate/20200610113542_add_label_to_spree_addresses.rb +5 -0
  107. data/db/migrate/20200826075557_add_unique_index_on_taxon_id_and_product_id_to_spree_products_taxons.rb +5 -0
  108. data/db/migrate/20201006110150_add_checkout_zone_field_to_store.rb +12 -0
  109. data/db/migrate/20201012091259_add_filterable_column_to_spree_option_types.rb +6 -0
  110. data/db/migrate/20201013084504_add_seo_robots_to_spree_stores.rb +5 -0
  111. data/db/migrate/20201127084048_add_default_country_kind_to_spree_zones.rb +5 -0
  112. data/db/migrate/20210112193440_remove_contact_email_from_spree_stores.rb +5 -0
  113. data/db/migrate/20210114182625_create_spree_payment_methods_stores.rb +10 -0
  114. data/db/migrate/20210114220232_migrate_data_payment_methods_stores.rb +15 -0
  115. data/db/migrate/20210117112551_remove_store_id_from_spree_payment_methods.rb +5 -0
  116. data/lib/generators/spree/install/templates/vendor/assets/javascripts/spree/backend/all.js +0 -2
  117. data/lib/generators/spree/install/templates/vendor/assets/javascripts/spree/frontend/all.js +0 -2
  118. data/lib/generators/spree/mailers_preview/mailers_preview_generator.rb +23 -0
  119. data/lib/generators/spree/mailers_preview/templates/mailers/previews/order_preview.rb +13 -0
  120. data/lib/generators/spree/mailers_preview/templates/mailers/previews/reimbursement_preview.rb +5 -0
  121. data/lib/generators/spree/mailers_preview/templates/mailers/previews/shipment_preview.rb +5 -0
  122. data/lib/generators/spree/mailers_preview/templates/mailers/previews/user_preview.rb +11 -0
  123. data/lib/spree/core.rb +2 -0
  124. data/lib/spree/core/controller_helpers/common.rb +1 -0
  125. data/lib/spree/core/controller_helpers/currency_helpers.rb +15 -0
  126. data/lib/spree/core/controller_helpers/order.rb +9 -4
  127. data/lib/spree/core/controller_helpers/store.rb +16 -1
  128. data/lib/spree/core/importer/order.rb +9 -9
  129. data/lib/spree/core/product_filters.rb +3 -3
  130. data/lib/spree/core/version.rb +1 -1
  131. data/lib/spree/i18n.rb +7 -21
  132. data/lib/spree/permitted_attributes.rb +8 -5
  133. data/lib/spree/service_module.rb +6 -2
  134. data/lib/spree/testing_support/authorization_helpers.rb +7 -4
  135. data/lib/spree/testing_support/capybara_config.rb +1 -1
  136. data/lib/spree/testing_support/factories/promotion_factory.rb +29 -17
  137. data/lib/spree/testing_support/factories/shipment_factory.rb +7 -9
  138. data/lib/spree/testing_support/factories/store_factory.rb +11 -8
  139. data/lib/spree/testing_support/factories/zone_factory.rb +16 -13
  140. data/lib/spree/testing_support/i18n.rb +1 -1
  141. data/lib/spree/testing_support/order_walkthrough.rb +8 -3
  142. data/lib/spree/testing_support/rspec_retry_config.rb +10 -0
  143. data/spree_core.gemspec +10 -8
  144. data/vendor/assets/javascripts/cleave.js +1669 -0
  145. metadata +105 -30
  146. data/app/views/spree/order_mailer/_adjustment.html.erb +0 -8
  147. data/app/views/spree/order_mailer/_subtotal.html.erb +0 -8
  148. data/app/views/spree/order_mailer/_total.html.erb +0 -8
  149. data/lib/spree/i18n/base.rb +0 -17
  150. data/lib/spree/i18n/initializer.rb +0 -1
@@ -32,7 +32,7 @@ module Spree
32
32
  end
33
33
 
34
34
  def pending_payments
35
- payments.select(&:pending?)
35
+ payments.pending
36
36
  end
37
37
 
38
38
  def unprocessed_payments
@@ -52,7 +52,7 @@ module Spree
52
52
 
53
53
  payment.public_send(method)
54
54
 
55
- if payment.completed? && payment_total != total
55
+ if payment.completed? && payment_total != total_without_pending_store_credits
56
56
  self.payment_total += payment.amount
57
57
  end
58
58
  end
@@ -60,6 +60,14 @@ module Spree
60
60
  result = !!Spree::Config[:allow_checkout_on_gateway_error]
61
61
  errors.add(:base, e.message) && (return result)
62
62
  end
63
+
64
+ # Pending store credits are not added to `self.payment_total`.
65
+ # It can cause a situation where the amount of the credit card payment reduced with store credits
66
+ # may be added twice to `self.payment_total` causing wrong `order.outstanding_balance`
67
+ # calculations and thus an incorrect payment state.
68
+ def total_without_pending_store_credits
69
+ total - payments.map { |p| p.amount if p.source.is_a?(Spree::StoreCredit) && p.pending? }.sum(&:to_f)
70
+ end
63
71
  end
64
72
  end
65
73
  end
@@ -14,7 +14,7 @@ module Spree
14
14
 
15
15
  with_options inverse_of: :payments do
16
16
  belongs_to :order, class_name: 'Spree::Order', touch: true
17
- belongs_to :payment_method, class_name: 'Spree::PaymentMethod'
17
+ belongs_to :payment_method, -> { with_deleted }, class_name: 'Spree::PaymentMethod'
18
18
  end
19
19
  belongs_to :source, polymorphic: true
20
20
 
@@ -195,14 +195,28 @@ module Spree
195
195
 
196
196
  def validate_source
197
197
  if source && !source.valid?
198
- source.errors.each do |field, error|
199
- field_name = I18n.t("activerecord.attributes.#{source.class.to_s.underscore}.#{field}")
200
- errors.add(Spree.t(source.class.to_s.demodulize.underscore), "#{field_name} #{error}")
198
+ if Rails::VERSION::STRING >= '6.1'
199
+ source.errors.map { |error| { field: error.attribute, message: error&.message } }.each do |err|
200
+ next if err[:field].blank? || err[:message].blank?
201
+
202
+ add_source_error(err[:field], err[:message])
203
+ end
204
+ else
205
+ source.errors.messages.each do |field, error|
206
+ next if field.blank? || error.empty?
207
+
208
+ add_source_error(field, error.first)
209
+ end
201
210
  end
202
211
  end
203
212
  !errors.present?
204
213
  end
205
214
 
215
+ def add_source_error(field, message)
216
+ field_name = I18n.t("activerecord.attributes.#{source.class.to_s.underscore}.#{field}")
217
+ errors.add(Spree.t(source.class.to_s.demodulize.underscore), "#{field_name} #{message}")
218
+ end
219
+
206
220
  def profiles_supported?
207
221
  payment_method.respond_to?(:payment_profiles_supported?) && payment_method.payment_profiles_supported?
208
222
  end
@@ -163,8 +163,8 @@ module Spree
163
163
  else
164
164
  error.to_s
165
165
  end
166
- logger.error(Spree.t(:gateway_error))
167
- logger.error(" #{error.to_yaml}")
166
+ Rails.logger.error(Spree.t(:gateway_error))
167
+ Rails.logger.error(" #{error.to_yaml}")
168
168
  raise Core::GatewayError, text
169
169
  end
170
170
 
@@ -12,7 +12,7 @@ module Spree
12
12
 
13
13
  validates :name, presence: true
14
14
 
15
- belongs_to :store
15
+ has_and_belongs_to_many :stores
16
16
 
17
17
  with_options dependent: :restrict_with_error do
18
18
  has_many :payments, class_name: 'Spree::Payment', inverse_of: :payment_method
@@ -79,9 +79,9 @@ module Spree
79
79
  end
80
80
 
81
81
  def available_for_store?(store)
82
- return true if store.blank? || store_id.blank?
82
+ return true if store.blank?
83
83
 
84
- store_id == store.id
84
+ store_ids.include?(store.id)
85
85
  end
86
86
  end
87
87
  end
@@ -6,7 +6,7 @@
6
6
 
7
7
  require 'singleton'
8
8
 
9
- DB_EXCEPTIONS = if defined? PG
9
+ DB_EXCEPTIONS ||= if defined? PG
10
10
  [PG::ConnectionBad, ActiveRecord::NoDatabaseError]
11
11
  elsif defined? Mysql2
12
12
  [Mysql2::Error::ConnectionError, ActiveRecord::NoDatabaseError]
@@ -6,7 +6,7 @@ module Spree
6
6
 
7
7
  MAXIMUM_AMOUNT = BigDecimal('99_999_999.99')
8
8
 
9
- belongs_to :variant, class_name: 'Spree::Variant', inverse_of: :prices, touch: true
9
+ belongs_to :variant, -> { with_deleted }, class_name: 'Spree::Variant', inverse_of: :prices, touch: true
10
10
 
11
11
  before_validation :ensure_currency
12
12
 
@@ -15,10 +15,16 @@ module Spree
15
15
  less_than_or_equal_to: MAXIMUM_AMOUNT
16
16
  }
17
17
 
18
+ validates :compare_at_amount, allow_nil: true, numericality: {
19
+ greater_than_or_equal_to: 0,
20
+ less_than_or_equal_to: MAXIMUM_AMOUNT
21
+ }
22
+
18
23
  extend DisplayMoney
19
- money_methods :amount, :price
24
+ money_methods :amount, :price, :compare_at_amount
25
+ alias display_compare_at_price display_compare_at_amount
20
26
 
21
- self.whitelisted_ransackable_attributes = ['amount']
27
+ self.whitelisted_ransackable_attributes = ['amount', 'compare_at_amount']
22
28
 
23
29
  def money
24
30
  Spree::Money.new(amount || 0, currency: currency)
@@ -28,20 +34,33 @@ module Spree
28
34
  self[:amount] = Spree::LocalizedNumber.parse(amount)
29
35
  end
30
36
 
37
+ def compare_at_money
38
+ Spree::Money.new(compare_at_amount || 0, currency: currency)
39
+ end
40
+
41
+ def compare_at_amount=(compare_at_amount)
42
+ self[:compare_at_amount] = Spree::LocalizedNumber.parse(compare_at_amount)
43
+ end
44
+
31
45
  alias_attribute :price, :amount
46
+ alias_attribute :compare_at_price, :compare_at_amount
32
47
 
33
48
  def price_including_vat_for(price_options)
34
49
  options = price_options.merge(tax_category: variant.tax_category)
35
50
  gross_amount(price, options)
36
51
  end
37
52
 
53
+ def compare_at_price_including_vat_for(price_options)
54
+ options = price_options.merge(tax_category: variant.tax_category)
55
+ gross_amount(compare_at_price, options)
56
+ end
57
+
38
58
  def display_price_including_vat_for(price_options)
39
59
  Spree::Money.new(price_including_vat_for(price_options), currency: currency)
40
60
  end
41
61
 
42
- # Remove variant default_scope `deleted_at: nil`
43
- def variant
44
- Spree::Variant.unscoped { super }
62
+ def display_compare_at_price_including_vat_for(price_options)
63
+ Spree::Money.new(compare_at_price_including_vat_for(price_options), currency: currency)
45
64
  end
46
65
 
47
66
  private
@@ -113,17 +113,17 @@ module Spree
113
113
 
114
114
  self.whitelisted_ransackable_associations = %w[taxons stores variants_including_master master variants]
115
115
  self.whitelisted_ransackable_attributes = %w[description name slug discontinue_on]
116
- self.whitelisted_ransackable_scopes = %w[not_discontinued]
116
+ self.whitelisted_ransackable_scopes = %w[not_discontinued search_by_name]
117
117
 
118
118
  [
119
119
  :sku, :price, :currency, :weight, :height, :width, :depth, :is_master,
120
- :cost_currency, :price_in, :amount_in, :cost_price
120
+ :cost_currency, :price_in, :amount_in, :cost_price, :compare_at_price
121
121
  ].each do |method_name|
122
122
  delegate method_name, :"#{method_name}=", to: :find_or_build_master
123
123
  end
124
124
 
125
125
  delegate :display_amount, :display_price, :has_default_price?,
126
- :images, to: :find_or_build_master
126
+ :display_compare_at_price, :images, to: :find_or_build_master
127
127
 
128
128
  alias master_images images
129
129
 
@@ -160,10 +160,8 @@ module Spree
160
160
  #
161
161
  # @return [Spree::Variant]
162
162
  def default_variant
163
- track_inventory = Spree::Config[:track_inventory_levels]
164
-
165
- Rails.cache.fetch("spree/default-variant/#{cache_key_with_version}/#{track_inventory}") do
166
- if track_inventory && variants.in_stock_or_backorderable.any?
163
+ Rails.cache.fetch(default_variant_cache_key) do
164
+ if Spree::Config[:track_inventory_levels] && variants.in_stock_or_backorderable.any?
167
165
  variants.in_stock_or_backorderable.first
168
166
  else
169
167
  has_variants? ? variants.first : master
@@ -252,6 +250,14 @@ module Spree
252
250
  where conditions.inject(:or)
253
251
  end
254
252
 
253
+ def self.search_by_name(query)
254
+ if defined?(SpreeGlobalize)
255
+ joins(:translations).order(:name).where("LOWER(#{Product::Translation.table_name}.name) LIKE LOWER(:query)", query: "%#{query}%").distinct
256
+ else
257
+ where("LOWER(#{Product.table_name}.name) LIKE LOWER(:query)", query: "%#{query}%")
258
+ end
259
+ end
260
+
255
261
  # Suitable for displaying only variants that has at least one option value.
256
262
  # There may be scenarios where an option type is removed and along with it
257
263
  # all option values. At that point all variants associated with only those
@@ -344,6 +350,10 @@ module Spree
344
350
  save
345
351
  end
346
352
 
353
+ def default_variant_cache_key
354
+ "spree/default-variant/#{cache_key_with_version}/#{Spree::Config[:track_inventory_levels]}"
355
+ end
356
+
347
357
  def ensure_master
348
358
  return unless new_record?
349
359
 
@@ -401,8 +411,18 @@ module Spree
401
411
  # We call master.default_price here to ensure price is initialized.
402
412
  # Required to avoid Variant#check_price validation failing on create.
403
413
  unless master.default_price && master.valid?
404
- master.errors.each do |att, error|
405
- errors.add(att, error)
414
+ if Rails::VERSION::STRING >= '6.1'
415
+ master.errors.map { |error| { field: error.attribute, message: error&.message } }.each do |err|
416
+ next if err[:field].blank? || err[:message].blank?
417
+
418
+ errors.add(err[:field], err[:message])
419
+ end
420
+ else
421
+ master.errors.messages.each do |field, error|
422
+ next if field.blank? || error.empty?
423
+
424
+ errors.add(field, error.first)
425
+ end
406
426
  end
407
427
  end
408
428
  end
@@ -28,6 +28,8 @@ module Spree
28
28
 
29
29
  before_save :normalize_blank_values
30
30
 
31
+ before_validation :normalize_code
32
+
31
33
  scope :coupons, -> { where.not(code: nil) }
32
34
  scope :advertised, -> { where(advertise: true) }
33
35
  scope :applied, lambda {
@@ -192,21 +194,10 @@ module Spree
192
194
  end
193
195
 
194
196
  def used_by?(user, excluded_orders = [])
195
- [
196
- :adjustments,
197
- :line_item_adjustments,
198
- :shipment_adjustments
199
- ].any? do |adjustment_type|
200
- user.orders.complete.joins(adjustment_type).where(
201
- spree_adjustments: {
202
- source_type: 'Spree::PromotionAction',
203
- source_id: actions.map(&:id),
204
- eligible: true
205
- }
206
- ).where.not(
207
- id: excluded_orders.map(&:id)
208
- ).any?
209
- end
197
+ user.orders.complete.joins(:promotions).joins(:all_adjustments).
198
+ where.not(spree_orders: { id: excluded_orders.map(&:id) }).
199
+ where(spree_promotions: { id: id }).
200
+ where(spree_adjustments: { source_type: 'Spree::PromotionAction', eligible: true }).any?
210
201
  end
211
202
 
212
203
  private
@@ -227,6 +218,10 @@ module Spree
227
218
  end
228
219
  end
229
220
 
221
+ def normalize_code
222
+ self.code = code.strip if code.present?
223
+ end
224
+
230
225
  def match_all?
231
226
  match_policy == 'all'
232
227
  end
@@ -58,7 +58,8 @@ module Spree
58
58
  end
59
59
 
60
60
  def product_ids_string=(s)
61
- self.product_ids = s.to_s.split(',').map(&:strip)
61
+ # check this
62
+ self.product_ids = s
62
63
  end
63
64
  end
64
65
  end
@@ -22,7 +22,8 @@ module Spree
22
22
  end
23
23
 
24
24
  def user_ids_string=(s)
25
- self.user_ids = s.to_s.split(',').map(&:strip)
25
+ # check this
26
+ self.user_ids = s
26
27
  end
27
28
  end
28
29
  end
@@ -27,7 +27,7 @@ module Spree
27
27
  promotion = order.promotions.with_coupon_code(coupon_code)
28
28
  if promotion.present?
29
29
  # Order promotion has to be destroyed before line item removing
30
- order.order_promotions.find_by!(promotion_id: promotion.id).destroy
30
+ order.order_promotions.where(promotion_id: promotion.id).destroy_all
31
31
 
32
32
  remove_promotion_adjustments(promotion)
33
33
  remove_promotion_line_items(promotion)
@@ -1,15 +1,16 @@
1
1
  module Spree
2
2
  module PromotionHandler
3
3
  class PromotionDuplicator
4
- def initialize(promotion)
4
+ def initialize(promotion, random_string: nil)
5
5
  @promotion = promotion
6
+ @random_string = random_string || generate_random_string(4)
6
7
  end
7
8
 
8
9
  def duplicate
9
10
  @new_promotion = @promotion.dup
10
- @new_promotion.path = "#{@promotion.path}_new"
11
+ @new_promotion.path = "#{@promotion.path}_#{@random_string}"
11
12
  @new_promotion.name = "New #{@promotion.name}"
12
- @new_promotion.code = "#{@promotion.code}_new"
13
+ @new_promotion.code = "#{@promotion.code}_#{@random_string}"
13
14
 
14
15
  ActiveRecord::Base.transaction do
15
16
  @new_promotion.save
@@ -33,6 +34,11 @@ module Spree
33
34
  end
34
35
  end
35
36
 
37
+ def generate_random_string(number)
38
+ charset = Array('A'..'Z') + Array('a'..'z')
39
+ Array.new(number) { charset.sample }.join
40
+ end
41
+
36
42
  def copy_actions
37
43
  @promotion.promotion_actions.each do |action|
38
44
  new_action = action.dup
@@ -61,14 +61,14 @@ module Spree
61
61
  end
62
62
 
63
63
  unless response.success?
64
- logger.error(Spree.t(:gateway_error) + " #{response.to_yaml}")
64
+ Rails.logger.error(Spree.t(:gateway_error) + " #{response.to_yaml}")
65
65
  text = response.params['message'] || response.params['response_reason_text'] || response.message
66
66
  raise Core::GatewayError, text
67
67
  end
68
68
 
69
69
  response
70
70
  rescue ActiveMerchant::ConnectionError => e
71
- logger.error(Spree.t(:gateway_error) + " #{e.inspect}")
71
+ Rails.logger.error(Spree.t(:gateway_error) + " #{e.inspect}")
72
72
  raise Core::GatewayError, Spree.t(:unable_to_connect_to_gateway)
73
73
  end
74
74
 
@@ -60,6 +60,8 @@ module Spree
60
60
  class_attribute :reimbursement_failure_hooks
61
61
  self.reimbursement_failure_hooks = []
62
62
 
63
+ delegate :store, :currency, to: :order
64
+
63
65
  state_machine :reimbursement_status, initial: :pending do
64
66
  event :errored do
65
67
  transition to: :errored, from: :pending
@@ -1,5 +1,3 @@
1
- require_relative 'r_m_a_required'
2
-
3
1
  module Spree
4
2
  class ReturnItem::EligibilityValidator::Default < Spree::ReturnItem::EligibilityValidator::BaseValidator
5
3
  class_attribute :permitted_eligibility_validators
@@ -42,6 +42,8 @@ module Spree
42
42
  scope :reverse_chronological, -> { order(Arel.sql('coalesce(spree_shipments.shipped_at, spree_shipments.created_at) desc'), id: :desc) }
43
43
  scope :valid, -> { where.not(state: :canceled) }
44
44
 
45
+ delegate :store, :currency, to: :order
46
+
45
47
  # shipment state machine (see http://github.com/pluginaweek/state_machine/tree/master for details)
46
48
  state_machine initial: :pending, use_transactions: false do
47
49
  event :ready do
@@ -104,11 +106,6 @@ module Spree
104
106
  inventory_units.any?(&:backordered?)
105
107
  end
106
108
 
107
- # TODO: delegate currency to Order, order.currency is mandatory
108
- def currency
109
- order ? order.currency : Spree::Config[:currency]
110
- end
111
-
112
109
  # Determines the appropriate +state+ according to the following logic:
113
110
  #
114
111
  # pending unless order is complete and +order.payment_state+ is +paid+
@@ -365,7 +362,7 @@ module Spree
365
362
  desired_shipment: shipment_to_transfer_to,
366
363
  variant: variant,
367
364
  quantity: quantity
368
- ).run!
365
+ )
369
366
  end
370
367
 
371
368
  private
@@ -19,7 +19,7 @@ module Spree
19
19
  foreign_key: 'shipping_method_id'
20
20
  has_many :zones, through: :shipping_method_zones, class_name: 'Spree::Zone'
21
21
 
22
- belongs_to :tax_category, class_name: 'Spree::TaxCategory', optional: true
22
+ belongs_to :tax_category, -> { with_deleted }, class_name: 'Spree::TaxCategory', optional: true
23
23
 
24
24
  validates :name, :display_on, presence: true
25
25
 
@@ -44,10 +44,6 @@ module Spree
44
44
  select { |c| c.to_s.constantize < Spree::ShippingCalculator }
45
45
  end
46
46
 
47
- def tax_category
48
- Spree::TaxCategory.unscoped { super }
49
- end
50
-
51
47
  def available_to_display?(display_filter)
52
48
  (frontend? && display_filter == DISPLAY_ON_FRONT_END) ||
53
49
  (backend? && display_filter == DISPLAY_ON_BACK_END)