spree_core 4.8.3 → 4.9.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 (82) hide show
  1. checksums.yaml +4 -4
  2. data/app/finders/spree/line_items/find_by_variant.rb +4 -2
  3. data/app/finders/spree/products/find.rb +1 -1
  4. data/app/finders/spree/variants/find.rb +30 -0
  5. data/app/models/spree/address.rb +12 -2
  6. data/app/models/spree/adjustment.rb +5 -0
  7. data/app/models/spree/asset.rb +8 -0
  8. data/app/models/spree/calculator/flat_rate.rb +3 -0
  9. data/app/models/spree/calculator/flexi_rate.rb +3 -0
  10. data/app/models/spree/calculator/percent_on_line_item.rb +3 -0
  11. data/app/models/spree/calculator/shipping/flat_rate.rb +13 -1
  12. data/app/models/spree/cms_section_image.rb +0 -6
  13. data/app/models/spree/customer_return.rb +1 -0
  14. data/app/models/spree/icon.rb +0 -6
  15. data/app/models/spree/image/configuration/active_storage.rb +0 -8
  16. data/app/models/spree/image.rb +17 -0
  17. data/app/models/spree/line_item.rb +23 -6
  18. data/app/models/spree/option_value_variant.rb +4 -0
  19. data/app/models/spree/order/currency_updater.rb +2 -2
  20. data/app/models/spree/order/webhooks.rb +19 -0
  21. data/app/models/spree/order.rb +17 -6
  22. data/app/models/spree/order_merger.rb +6 -0
  23. data/app/models/spree/payment/gateway_options.rb +4 -0
  24. data/app/models/spree/payment/webhooks.rb +15 -0
  25. data/app/models/spree/payment.rb +7 -7
  26. data/app/models/spree/price.rb +45 -0
  27. data/app/models/spree/product/webhooks.rb +17 -0
  28. data/app/models/spree/product.rb +7 -9
  29. data/app/models/spree/promotion/actions/free_shipping.rb +13 -0
  30. data/app/models/spree/promotion/rules/first_order.rb +6 -1
  31. data/app/models/spree/promotion.rb +2 -2
  32. data/app/models/spree/promotion_handler/coupon.rb +3 -2
  33. data/app/models/spree/refund.rb +14 -2
  34. data/app/models/spree/reimbursement/emails.rb +11 -0
  35. data/app/models/spree/reimbursement.rb +1 -6
  36. data/app/models/spree/role_user.rb +1 -1
  37. data/app/models/spree/shipment/emails.rb +11 -0
  38. data/app/models/spree/shipment/webhooks.rb +11 -0
  39. data/app/models/spree/shipment.rb +58 -7
  40. data/app/models/spree/shipment_handler.rb +2 -6
  41. data/app/models/spree/shipping_method.rb +6 -0
  42. data/app/models/spree/shipping_method_zone.rb +4 -2
  43. data/app/models/spree/shipping_rate.rb +1 -1
  44. data/app/models/spree/stock/package.rb +4 -0
  45. data/app/models/spree/stock/quantifier.rb +22 -4
  46. data/app/models/spree/stock_item/webhooks.rb +6 -0
  47. data/app/models/spree/stock_item.rb +1 -3
  48. data/app/models/spree/stock_location.rb +15 -0
  49. data/app/models/spree/stock_movement/webhooks.rb +6 -0
  50. data/app/models/spree/stock_movement.rb +1 -3
  51. data/app/models/spree/store.rb +1 -5
  52. data/app/models/spree/store_credit.rb +11 -12
  53. data/app/models/spree/store_favicon_image.rb +0 -6
  54. data/app/models/spree/store_logo.rb +0 -5
  55. data/app/models/spree/store_mailer_logo.rb +0 -6
  56. data/app/models/spree/tax_rate.rb +3 -1
  57. data/app/models/spree/taxon_image/configuration/active_storage.rb +0 -6
  58. data/app/models/spree/variant/webhooks.rb +6 -0
  59. data/app/models/spree/variant.rb +21 -3
  60. data/app/models/spree/wishlist.rb +9 -0
  61. data/app/presenters/spree/variants/options_presenter.rb +34 -2
  62. data/app/services/spree/cart/add_item.rb +2 -0
  63. data/app/services/spree/cart/destroy.rb +14 -4
  64. data/app/services/spree/seeds/all.rb +3 -0
  65. data/app/services/spree/seeds/payment_methods.rb +18 -0
  66. data/app/services/spree/seeds/stock_locations.rb +1 -1
  67. data/app/services/spree/seeds/zones.rb +19 -19
  68. data/config/locales/en.yml +2 -0
  69. data/db/migrate/20240623172111_add_deleted_at_to_spree_stock_locations.rb +6 -0
  70. data/db/migrate/20240725124530_add_refunder_to_spree_refunds.rb +6 -0
  71. data/lib/spree/core/controller_helpers/order.rb +5 -5
  72. data/lib/spree/core/dependencies.rb +2 -1
  73. data/lib/spree/core/preferences/preferable.rb +4 -2
  74. data/lib/spree/core/preferences/preferable_class_methods.rb +3 -2
  75. data/lib/spree/core/version.rb +1 -1
  76. data/lib/spree/core/webhooks.rb +15 -7
  77. data/lib/spree/core.rb +1 -0
  78. data/lib/spree/money.rb +1 -1
  79. data/lib/spree/testing_support/authorization_helpers.rb +2 -2
  80. data/lib/spree/testing_support/common_rake.rb +1 -1
  81. data/spree_core.gemspec +1 -0
  82. metadata +31 -4
@@ -27,9 +27,7 @@ module Spree
27
27
  include Spree::TranslatableResourceSlug
28
28
  include Spree::MemoizedData
29
29
  include Spree::Metadata
30
- if defined?(Spree::Webhooks::HasWebhooks)
31
- include Spree::Webhooks::HasWebhooks
32
- end
30
+ include Spree::Product::Webhooks
33
31
  if defined?(Spree::VendorConcern)
34
32
  include Spree::VendorConcern
35
33
  end
@@ -181,17 +179,17 @@ module Spree
181
179
  event :activate do
182
180
  transition to: :active
183
181
  end
184
- after_transition to: :active, do: :after_activate
182
+ after_transition to: :active, do: [:after_activate, :send_product_activated_webhook]
185
183
 
186
184
  event :archive do
187
185
  transition to: :archived
188
186
  end
189
- after_transition to: :archived, do: :after_archive
187
+ after_transition to: :archived, do: [:after_archive, :send_product_archived_webhook]
190
188
 
191
189
  event :draft do
192
190
  transition to: :draft
193
191
  end
194
- after_transition to: :draft, do: :after_draft
192
+ after_transition to: :draft, do: [:after_draft, :send_product_drafted_webhook]
195
193
  end
196
194
 
197
195
  # Can't use short form block syntax due to https://github.com/Netflix/fast_jsonapi/issues/259
@@ -584,15 +582,15 @@ module Spree
584
582
  end
585
583
 
586
584
  def after_activate
587
- # this method is prepended in api/ to queue Webhooks requests
585
+ # Implement your logic here
588
586
  end
589
587
 
590
588
  def after_archive
591
- # this method is prepended in api/ to queue Webhooks requests
589
+ # Implement your logic here
592
590
  end
593
591
 
594
592
  def after_draft
595
- # this method is prepended in api/ to queue Webhooks requests
593
+ # Implement your logic here
596
594
  end
597
595
  end
598
596
  end
@@ -13,6 +13,19 @@ module Spree
13
13
  def compute_amount(shipment)
14
14
  shipment.cost * -1
15
15
  end
16
+
17
+ # we need to persist 0 amount adjustment
18
+ def create_adjustment(order, adjustable, included = false)
19
+ amount = compute_amount(adjustable)
20
+
21
+ adjustments.new(
22
+ adjustable: adjustable,
23
+ amount: amount,
24
+ included: included,
25
+ label: label,
26
+ order: order
27
+ ).save
28
+ end
16
29
  end
17
30
  end
18
31
  end
@@ -10,7 +10,12 @@ module Spree
10
10
 
11
11
  def eligible?(order, options = {})
12
12
  @user = order.try(:user) || options[:user]
13
- @email = order.email
13
+ @email = if options[:email].present?
14
+ order.email = options[:email]
15
+ order.email
16
+ elsif order.email.present?
17
+ order.email
18
+ end
14
19
  @store = order.store
15
20
 
16
21
  if user || email
@@ -128,10 +128,10 @@ module Spree
128
128
  end
129
129
 
130
130
  # called anytime order.update_with_updater! happens
131
- def eligible?(promotable)
131
+ def eligible?(promotable, options = {})
132
132
  return false if expired? || usage_limit_exceeded?(promotable) || blacklisted?(promotable)
133
133
 
134
- !!eligible_rules(promotable, {})
134
+ !!eligible_rules(promotable, options)
135
135
  end
136
136
 
137
137
  # eligible_rules returns an array of promotion rules where eligible? is true for the promotable
@@ -1,12 +1,13 @@
1
1
  module Spree
2
2
  module PromotionHandler
3
3
  class Coupon
4
- attr_reader :order, :store
4
+ attr_reader :order, :store, :options
5
5
  attr_accessor :error, :success, :status_code
6
6
 
7
- def initialize(order)
7
+ def initialize(order, options = {})
8
8
  @order = order
9
9
  @store = order.store
10
+ @options = options
10
11
  end
11
12
 
12
13
  def apply
@@ -13,6 +13,7 @@ module Spree
13
13
  belongs_to :reimbursement, optional: true
14
14
  end
15
15
  belongs_to :reason, class_name: 'Spree::RefundReason', foreign_key: :refund_reason_id
16
+ belongs_to :refunder, class_name: "::#{Spree.admin_user_class}", optional: true
16
17
 
17
18
  has_many :log_entries, as: :source
18
19
 
@@ -31,8 +32,10 @@ module Spree
31
32
 
32
33
  attr_reader :response
33
34
 
35
+ delegate :order, :currency, to: :payment
36
+
34
37
  def money
35
- Spree::Money.new(amount, currency: payment.currency)
38
+ Spree::Money.new(amount, currency: currency)
36
39
  end
37
40
  alias display_amount money
38
41
 
@@ -46,6 +49,15 @@ module Spree
46
49
  payment.payment_method.name
47
50
  end
48
51
 
52
+ # return items for the refund
53
+ #
54
+ # @return [Array<Spree::ReturnItem>]
55
+ def return_items
56
+ return [] unless reimbursement.present?
57
+
58
+ reimbursement.customer_return&.return_items || reimbursement.return_items
59
+ end
60
+
49
61
  private
50
62
 
51
63
  # attempts to perform the refund.
@@ -53,7 +65,7 @@ module Spree
53
65
  def perform!
54
66
  return true if transaction_id.present?
55
67
 
56
- credit_cents = Spree::Money.new(amount.to_f, currency: payment.currency).amount_in_cents
68
+ credit_cents = Spree::Money.new(amount.to_f, currency: currency).amount_in_cents
57
69
 
58
70
  @response = process!(credit_cents)
59
71
 
@@ -0,0 +1,11 @@
1
+ module Spree
2
+ class Reimbursement < Spree::Base
3
+ module Emails
4
+ def send_reimbursement_email
5
+ # you can overwrite this method in your application / extension to send out the confirmation email
6
+ # or use `spree_emails` gem
7
+ # YourEmailVendor.deliver_reimbursement_email(id) # `id` = ID of the Reimbursement being sent, you can also pass the entire object using `self`
8
+ end
9
+ end
10
+ end
11
+ end
@@ -5,6 +5,7 @@ module Spree
5
5
  if defined?(Spree::Webhooks::HasWebhooks)
6
6
  include Spree::Webhooks::HasWebhooks
7
7
  end
8
+ include Spree::Reimbursement::Emails
8
9
 
9
10
  class IncompleteReimbursementError < StandardError; end
10
11
 
@@ -141,12 +142,6 @@ module Spree
141
142
  end
142
143
  end
143
144
 
144
- def send_reimbursement_email
145
- # you can overwrite this method in your application / extension to send out the confirmation email
146
- # or use `spree_emails` gem
147
- # YourEmailVendor.deliver_reimbursement_email(id) # `id` = ID of the Reimbursement being sent, you can also pass the entire object using `self`
148
- end
149
-
150
145
  # If there are multiple different reimbursement types for a single
151
146
  # reimbursement we open ourselves to a one-cent rounding error for every
152
147
  # type over the first one. This is due to how we round #unpaid_amount and
@@ -1,6 +1,6 @@
1
1
  module Spree
2
2
  class RoleUser < Spree::Base
3
3
  belongs_to :role, class_name: 'Spree::Role'
4
- belongs_to :user, class_name: "::#{Spree.user_class}"
4
+ belongs_to :user, class_name: Spree.admin_user_class.to_s
5
5
  end
6
6
  end
@@ -0,0 +1,11 @@
1
+ module Spree
2
+ class Shipment < Spree::Base
3
+ module Emails
4
+ def send_shipped_email
5
+ # you can overwrite this method in your application / extension to send out the confirmation email
6
+ # or use `spree_emails` gem
7
+ # YourEmailVendor.deliver_shipment_notification_email(@shipment.id)
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ module Spree
2
+ class Shipment < Spree::Base
3
+ module Webhooks
4
+ extend ActiveSupport::Concern
5
+
6
+ def send_shipment_shipped_webhook
7
+ # Implement your logic here
8
+ end
9
+ end
10
+ end
11
+ end
@@ -6,18 +6,20 @@ module Spree
6
6
  include Spree::NumberIdentifier
7
7
  include Spree::NumberAsParam
8
8
  include Spree::Metadata
9
- if defined?(Spree::Webhooks::HasWebhooks)
10
- include Spree::Webhooks::HasWebhooks
11
- end
12
9
  if defined?(Spree::Security::Shipments)
13
10
  include Spree::Security::Shipments
14
11
  end
12
+ if defined?(Spree::VendorConcern)
13
+ include Spree::VendorConcern
14
+ end
15
+ include Spree::Shipment::Emails
16
+ include Spree::Shipment::Webhooks
15
17
 
16
18
  with_options inverse_of: :shipments do
17
19
  belongs_to :address, class_name: 'Spree::Address'
18
20
  belongs_to :order, class_name: 'Spree::Order', touch: true
19
21
  end
20
- belongs_to :stock_location, class_name: 'Spree::StockLocation'
22
+ belongs_to :stock_location, -> { with_deleted }, class_name: 'Spree::StockLocation'
21
23
 
22
24
  with_options dependent: :delete_all do
23
25
  has_many :adjustments, as: :adjustable
@@ -26,6 +28,7 @@ module Spree
26
28
  has_many :state_changes, as: :stateful
27
29
  end
28
30
  has_many :shipping_methods, through: :shipping_rates
31
+ has_many :variants, through: :inventory_units
29
32
  has_one :selected_shipping_rate, -> { where(selected: true).order(:cost) }, class_name: Spree::ShippingRate.to_s
30
33
 
31
34
  after_save :update_adjustments
@@ -47,8 +50,18 @@ module Spree
47
50
  # sort by most recent shipped_at, falling back to created_at. add "id desc" to make specs that involve this scope more deterministic.
48
51
  scope :reverse_chronological, -> { order(Arel.sql('coalesce(spree_shipments.shipped_at, spree_shipments.created_at) desc'), id: :desc) }
49
52
  scope :valid, -> { where.not(state: :canceled) }
53
+ scope :canceled, -> { with_state('canceled') }
54
+ scope :not_canceled, -> { where.not(state: 'canceled') }
55
+ scope :shipped_but_canceled, -> { canceled.where.not(shipped_at: nil) }
56
+ # This scope will select the shipping_method_id from the shipments' selected shipping rate
57
+ scope :with_selected_shipping_method, lambda {
58
+ joins(:selected_shipping_rate).
59
+ where(Spree::ShippingRate.arel_table[:shipping_method_id].not_eq(nil)).
60
+ select(Spree::ShippingRate.arel_table[:shipping_method_id])
61
+ }
50
62
 
51
63
  delegate :store, :currency, to: :order
64
+ delegate :amount_in_cents, to: :display_cost
52
65
 
53
66
  # shipment state machine (see http://github.com/pluginaweek/state_machine/tree/master for details)
54
67
  state_machine initial: :pending, use_transactions: false do
@@ -66,7 +79,7 @@ module Spree
66
79
  event :ship do
67
80
  transition from: %i(ready canceled), to: :shipped
68
81
  end
69
- after_transition to: :shipped, do: :after_ship
82
+ after_transition to: :shipped, do: [:after_ship, :send_shipment_shipped_webhook]
70
83
 
71
84
  event :cancel do
72
85
  transition to: :canceled, from: %i(pending ready)
@@ -93,9 +106,20 @@ module Spree
93
106
  self.whitelisted_ransackable_attributes = ['number']
94
107
 
95
108
  extend DisplayMoney
96
- money_methods :cost, :discounted_cost, :final_price, :item_cost
109
+ money_methods :cost, :discounted_cost, :final_price, :item_cost, :additional_tax_total, :included_tax_total, :tax_total
97
110
  alias display_amount display_cost
98
111
 
112
+ # Returns the shipment number and shipping method name
113
+ #
114
+ # @return [String]
115
+ def name
116
+ [number, shipping_method&.name].compact.join(' ').strip
117
+ end
118
+
119
+ def amount
120
+ cost
121
+ end
122
+
99
123
  def add_shipping_method(shipping_method, selected = false)
100
124
  shipping_rates.create(shipping_method: shipping_method, selected: selected, cost: cost)
101
125
  end
@@ -108,17 +132,44 @@ module Spree
108
132
  manifest.each { |item| manifest_unstock(item) }
109
133
  end
110
134
 
135
+ # Returns true if the shipment has any backordered inventory units
136
+ #
137
+ # @return [Boolean]
111
138
  def backordered?
112
139
  inventory_units.any?(&:backordered?)
113
140
  end
114
141
 
142
+ # Returns true if the shipment is tracked
143
+ #
144
+ # @return [Boolean]
145
+ def tracked?
146
+ tracking.present? || tracking_url.present?
147
+ end
148
+
149
+ # Returns true if the shipment is shippable
150
+ #
151
+ # @return [Boolean]
152
+ def shippable?
153
+ can_ship? && tracked?
154
+ end
155
+
156
+ # Returns true if not all of the shipment's line items are fully shipped
157
+ #
158
+ # @return [Boolean]
159
+ def partial?
160
+ manifest.any? do |manifest_item|
161
+ line_item = manifest_item.line_item
162
+ line_item.quantity > manifest_item.quantity
163
+ end
164
+ end
165
+
115
166
  # Determines the appropriate +state+ according to the following logic:
116
167
  #
117
168
  # pending unless order is complete and +order.payment_state+ is +paid+
118
169
  # shipped if already shipped (ie. does not change the state)
119
170
  # ready all other cases
120
171
  def determine_state(order)
121
- return 'canceled' if order.canceled?
172
+ return 'canceled' if canceled? || order.canceled?
122
173
  return 'pending' unless order.can_ship?
123
174
  return 'pending' if inventory_units.any? &:backordered?
124
175
  return 'shipped' if shipped?
@@ -1,5 +1,7 @@
1
1
  module Spree
2
2
  class ShipmentHandler
3
+ include Spree::Shipment::Emails
4
+
3
5
  class << self
4
6
  def factory(shipment)
5
7
  # Do we have a specialized shipping-method-specific handler? e.g:
@@ -27,12 +29,6 @@ module Spree
27
29
 
28
30
  protected
29
31
 
30
- def send_shipped_email
31
- # you can overwrite this method in your application / extension to send out the confirmation email
32
- # or use `spree_emails` gem
33
- # YourEmailVendor.deliver_shipment_notification_email(@shipment.id)
34
- end
35
-
36
32
  def update_order_shipment_state
37
33
  order = @shipment.order
38
34
 
@@ -18,6 +18,8 @@ module Spree
18
18
 
19
19
  default_scope { where(deleted_at: nil) }
20
20
 
21
+ scope :with_calculator, ->(calculator) { joins(:calculator).where(calculator: { type: calculator.to_s }) }
22
+
21
23
  has_many :shipping_method_categories, dependent: :destroy
22
24
  has_many :shipping_categories, through: :shipping_method_categories
23
25
  has_many :shipping_rates, inverse_of: :shipping_method
@@ -33,6 +35,10 @@ module Spree
33
35
 
34
36
  validate :at_least_one_shipping_category
35
37
 
38
+ scope :available, -> { where(display_on: [:both]) }
39
+ scope :available_on_front_end, -> { where(display_on: [:front_end, :both]) }
40
+ scope :available_on_back_end, -> { where(display_on: [:back_end, :both]) }
41
+
36
42
  def include?(address)
37
43
  return false unless address
38
44
 
@@ -1,6 +1,8 @@
1
1
  module Spree
2
2
  class ShippingMethodZone < Spree::Base
3
- belongs_to :shipping_method
4
- belongs_to :zone
3
+ belongs_to :shipping_method, -> { with_deleted }, inverse_of: :shipping_method_zones, class_name: 'Spree::ShippingMethod'
4
+ belongs_to :zone, inverse_of: :shipping_method_zones, class_name: 'Spree::Zone'
5
+
6
+ validates :shipping_method, uniqueness: { scope: :zone }
5
7
  end
6
8
  end
@@ -14,7 +14,7 @@ module Spree
14
14
  def display_price
15
15
  price = display_base_price.to_s
16
16
 
17
- return price if tax_rate.nil? || tax_amount.zero?
17
+ return price if tax_rate.nil? || tax_amount.zero? || !tax_rate.show_rate_in_label
18
18
 
19
19
  Spree.t(
20
20
  tax_rate.included_in_price? ? :including_tax : :excluding_tax,
@@ -34,6 +34,10 @@ module Spree
34
34
  contents.detect { |item| !!item.try(:inventory_unit).try(:order) }.try(:inventory_unit).try(:order)
35
35
  end
36
36
 
37
+ def item_total
38
+ contents.sum(&:amount)
39
+ end
40
+
37
41
  def weight
38
42
  contents.sum(&:weight)
39
43
  end
@@ -10,7 +10,11 @@ module Spree
10
10
 
11
11
  def total_on_hand
12
12
  @total_on_hand ||= if variant.should_track_inventory?
13
- stock_items.sum(:count_on_hand)
13
+ if association_loaded?
14
+ stock_items.sum(&:count_on_hand)
15
+ else
16
+ stock_items.sum(:count_on_hand)
17
+ end
14
18
  else
15
19
  BigDecimal::INFINITY
16
20
  end
@@ -30,10 +34,24 @@ module Spree
30
34
 
31
35
  private
32
36
 
33
- def scope_to_location(collection)
34
- return collection.with_active_stock_location if stock_location.blank?
37
+ def association_loaded?
38
+ variant.association(:stock_items).loaded? && variant.association(:stock_locations).loaded?
39
+ end
35
40
 
36
- collection.where(stock_location: stock_location)
41
+ def scope_to_location(collection)
42
+ if stock_location.blank?
43
+ if association_loaded?
44
+ return collection.select { |si| si.stock_location&.active? }
45
+ else
46
+ return collection.with_active_stock_location
47
+ end
48
+ end
49
+
50
+ if association_loaded?
51
+ collection.select { |si| si.stock_location_id == stock_location.id }
52
+ else
53
+ collection.where(stock_location: stock_location)
54
+ end
37
55
  end
38
56
  end
39
57
  end
@@ -0,0 +1,6 @@
1
+ module Spree
2
+ class StockItem < Spree::Base
3
+ module Webhooks
4
+ end
5
+ end
6
+ end
@@ -3,9 +3,7 @@ module Spree
3
3
  acts_as_paranoid
4
4
 
5
5
  include Spree::Metadata
6
- if defined?(Spree::Webhooks::HasWebhooks)
7
- include Spree::Webhooks::HasWebhooks
8
- end
6
+ include Spree::StockItem::Webhooks
9
7
 
10
8
  with_options inverse_of: :stock_items do
11
9
  belongs_to :stock_location, class_name: 'Spree::StockLocation'
@@ -11,6 +11,8 @@ module Spree
11
11
  include Spree::VendorConcern
12
12
  end
13
13
 
14
+ acts_as_paranoid
15
+
14
16
  has_many :shipments
15
17
  has_many :stock_items, dependent: :delete_all, inverse_of: :stock_location
16
18
  has_many :variants, through: :stock_items
@@ -122,6 +124,19 @@ module Spree
122
124
  end
123
125
  end
124
126
 
127
+ def address
128
+ Spree::Address.new(
129
+ address1: address1,
130
+ address2: address2,
131
+ city: city,
132
+ state: state,
133
+ state_name: state_name,
134
+ country: country,
135
+ zipcode: zipcode,
136
+ phone: phone
137
+ )
138
+ end
139
+
125
140
  private
126
141
 
127
142
  def create_stock_items
@@ -0,0 +1,6 @@
1
+ module Spree
2
+ class StockMovement < Spree::Base
3
+ module Webhooks
4
+ end
5
+ end
6
+ end
@@ -5,9 +5,7 @@ module Spree
5
5
  min: -2**31
6
6
  }.freeze
7
7
 
8
- if defined?(Spree::Webhooks::HasWebhooks)
9
- include Spree::Webhooks::HasWebhooks
10
- end
8
+ include Spree::StockMovement::Webhooks
11
9
 
12
10
  belongs_to :stock_item, class_name: 'Spree::StockItem', inverse_of: :stock_movements
13
11
  belongs_to :originator, polymorphic: true
@@ -110,11 +110,7 @@ module Spree
110
110
  after_commit :clear_cache
111
111
 
112
112
  def self.current(url = nil)
113
- Spree::Deprecation.warn(<<-DEPRECATION, caller)
114
- `Spree::Store.current` is deprecated and will be removed in Spree 5.0
115
- Please use `Spree::Stores::FindCurrent.new(url: "https://example.com").execute` instead
116
- DEPRECATION
117
- Stores::FindCurrent.new(url: url).execute
113
+ Spree::Dependencies.current_store_finder.constantize.new(url: url).execute
118
114
  end
119
115
 
120
116
  # FIXME: we need to drop `or_initialize` in v5
@@ -19,13 +19,16 @@ module Spree
19
19
  DEFAULT_CREATED_BY_EMAIL = 'spree@example.com'.freeze
20
20
 
21
21
  belongs_to :user, class_name: "::#{Spree.user_class}", foreign_key: 'user_id'
22
- belongs_to :category, class_name: 'Spree::StoreCreditCategory'
23
- belongs_to :created_by, class_name: Spree.admin_user_class.to_s, foreign_key: 'created_by_id'
24
- belongs_to :credit_type, class_name: 'Spree::StoreCreditType', foreign_key: 'type_id'
22
+ belongs_to :category, class_name: 'Spree::StoreCreditCategory', optional: true
23
+ belongs_to :created_by, class_name: "::#{Spree.admin_user_class}", foreign_key: 'created_by_id', optional: true
24
+ belongs_to :credit_type, class_name: 'Spree::StoreCreditType', foreign_key: 'type_id', optional: true
25
25
  belongs_to :store, class_name: 'Spree::Store'
26
+
26
27
  has_many :store_credit_events, class_name: 'Spree::StoreCreditEvent'
28
+ has_many :payments, as: :source, class_name: 'Spree::Payment'
29
+ has_many :orders, through: :payments, class_name: 'Spree::Order'
27
30
 
28
- validates :user, :category, :credit_type, :created_by, :currency, :store, presence: true
31
+ validates :currency, :store, presence: true
29
32
  validates :amount, numericality: { greater_than: 0 }
30
33
  validates :amount_used, numericality: { greater_than_or_equal_to: 0 }
31
34
  validate :amount_used_less_than_or_equal_to_amount
@@ -36,7 +39,10 @@ module Spree
36
39
 
37
40
  scope :order_by_priority, -> { includes(:credit_type).order('spree_store_credit_types.priority ASC') }
38
41
 
39
- before_validation :associate_credit_type
42
+ scope :not_authorized, -> { where(amount_authorized: 0) }
43
+ scope :not_used, -> { where(amount_authorized: 0) }
44
+ scope :available, -> { not_authorized.not_used }
45
+
40
46
  after_save :store_event
41
47
  before_destroy :validate_no_amount_used
42
48
 
@@ -249,12 +255,5 @@ module Spree
249
255
  throw(:abort)
250
256
  end
251
257
  end
252
-
253
- def associate_credit_type
254
- unless type_id
255
- credit_type_name = category.try(:non_expiring?) ? 'Non-expiring' : 'Expiring'
256
- self.credit_type = Spree::StoreCreditType.find_or_create_by(name: credit_type_name)
257
- end
258
- end
259
258
  end
260
259
  end
@@ -1,11 +1,5 @@
1
1
  module Spree
2
2
  class StoreFaviconImage < Asset
3
- if Spree.public_storage_service_name
4
- has_one_attached :attachment, service: Spree.public_storage_service_name
5
- else
6
- has_one_attached :attachment
7
- end
8
-
9
3
  VALID_CONTENT_TYPES = ['image/png', 'image/x-icon', 'image/vnd.microsoft.icon'].freeze
10
4
 
11
5
  validates :attachment,
@@ -1,9 +1,4 @@
1
1
  module Spree
2
2
  class StoreLogo < Asset
3
- if Spree.public_storage_service_name
4
- has_one_attached :attachment, service: Spree.public_storage_service_name
5
- else
6
- has_one_attached :attachment
7
- end
8
3
  end
9
4
  end
@@ -1,11 +1,5 @@
1
1
  module Spree
2
2
  class StoreMailerLogo < Asset
3
- if Spree.public_storage_service_name
4
- has_one_attached :attachment, service: Spree.public_storage_service_name
5
- else
6
- has_one_attached :attachment
7
- end
8
-
9
3
  VALID_CONTENT_TYPES = ['image/png', 'image/jpg', 'image/jpeg'].freeze
10
4
 
11
5
  validates :attachment, content_type: VALID_CONTENT_TYPES
@@ -115,11 +115,13 @@ module Spree
115
115
 
116
116
  def amount_for_label
117
117
  return '' unless show_rate_in_label?
118
+ return '' if amount.zero?
118
119
 
119
120
  ' ' + ActiveSupport::NumberHelper::NumberToPercentageConverter.convert(
120
121
  amount * 100,
121
122
  locale: I18n.locale,
122
- strip_insignificant_zeros: true
123
+ strip_insignificant_zeros: true,
124
+ precision: 2
123
125
  )
124
126
  end
125
127
  end
@@ -5,12 +5,6 @@ module Spree
5
5
  extend ActiveSupport::Concern
6
6
 
7
7
  included do
8
- if Spree.public_storage_service_name
9
- has_one_attached :attachment, service: Spree.public_storage_service_name
10
- else
11
- has_one_attached :attachment
12
- end
13
-
14
8
  validates :attachment, content_type: /\Aimage\/.*\z/
15
9
 
16
10
  default_scope { includes(attachment_attachment: :blob) }