solidus_core 4.5.1 → 4.6.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.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/app/jobs/spree/base_job.rb +12 -0
- data/app/jobs/spree/state_change_tracking_job.rb +32 -0
- data/app/models/concerns/spree/state_change_tracking.rb +26 -0
- data/app/models/concerns/spree/user_address_book.rb +24 -6
- data/app/models/concerns/spree/user_methods.rb +52 -14
- data/app/models/concerns/spree/user_reporting.rb +1 -1
- data/app/models/spree/address.rb +8 -2
- data/app/models/spree/adjustment_reason.rb +1 -1
- data/app/models/spree/calculator.rb +0 -2
- data/app/models/spree/carton.rb +7 -0
- data/app/models/spree/classification.rb +3 -3
- data/app/models/spree/core/state_machines/order/class_methods.rb +0 -16
- data/app/models/spree/core/state_machines/order.rb +1 -0
- data/app/models/spree/core/state_machines/payment.rb +1 -8
- data/app/models/spree/core/state_machines/shipment.rb +1 -8
- data/app/models/spree/country.rb +16 -5
- data/app/models/spree/customer_return.rb +1 -2
- data/app/models/spree/fulfilment_changer.rb +38 -11
- data/app/models/spree/inventory_unit.rb +1 -1
- data/app/models/spree/line_item.rb +3 -2
- data/app/models/spree/order.rb +5 -7
- data/app/models/spree/order_cancellations.rb +17 -20
- data/app/models/spree/order_shipping.rb +2 -9
- data/app/models/spree/order_taxation.rb +3 -2
- data/app/models/spree/order_updater.rb +11 -7
- data/app/models/spree/payment_method.rb +0 -1
- data/app/models/spree/product.rb +6 -5
- data/app/models/spree/product_option_type.rb +2 -2
- data/app/models/spree/product_property.rb +2 -2
- data/app/models/spree/role_user.rb +3 -3
- data/app/models/spree/shipment.rb +26 -12
- data/app/models/spree/shipping_category.rb +2 -2
- data/app/models/spree/shipping_method_category.rb +2 -2
- data/app/models/spree/state.rb +7 -4
- data/app/models/spree/stock/quantifier.rb +33 -9
- data/app/models/spree/stock_item.rb +1 -1
- data/app/models/spree/stock_location.rb +3 -2
- data/app/models/spree/store.rb +6 -0
- data/app/models/spree/store_credit.rb +3 -3
- data/app/models/spree/store_credit_event.rb +1 -1
- data/app/models/spree/tax_category.rb +1 -1
- data/app/models/spree/taxon.rb +0 -3
- data/app/models/spree/taxonomy.rb +2 -2
- data/app/models/spree/user_address.rb +4 -4
- data/app/models/spree/variant.rb +1 -1
- data/app/models/spree/variant_property_rule.rb +1 -1
- data/app/models/spree/variant_property_rule_condition.rb +1 -1
- data/app/models/spree/wallet_payment_source.rb +2 -2
- data/app/subscribers/spree/carton_shipped_mailer_subscriber.rb +30 -0
- data/app/subscribers/spree/order_cancel_mailer_subscriber.rb +21 -0
- data/app/subscribers/spree/order_confirmation_mailer_subscriber.rb +23 -0
- data/app/subscribers/spree/order_inventory_cancellation_mailer_subscriber.rb +27 -0
- data/app/subscribers/spree/order_mailer_subscriber.rb +8 -26
- data/app/subscribers/spree/reimbursement_mailer_subscriber.rb +20 -0
- data/config/locales/en.yml +9 -0
- data/db/migrate/20160101010000_solidus_one_four.rb +92 -0
- data/db/migrate/20180416083007_add_apply_to_all_to_variant_property_rule.rb +1 -1
- data/db/migrate/20250129061658_add_metadata_to_spree_resources.rb +1 -1
- data/db/migrate/20250214094207_add_reverse_charge_status_to_store.rb +8 -0
- data/db/migrate/20250225051308_add_vat_id_email_and_reverse_charge_status_to_addresses.rb +10 -0
- data/db/migrate/20250508145917_add_email_to_stock_locations.rb +5 -0
- data/db/migrate/20250530102541_add_addressbook_foreign_key.rb +29 -0
- data/db/migrate/20250604072105_add_fk_products_variant_property_rules.rb +30 -0
- data/db/migrate/20250604072555_add_fk_to_product_properties.rb +52 -0
- data/db/migrate/20250604072948_add_fk_to_product_option_types.rb +52 -0
- data/db/migrate/20250604073219_add_fk_to_classifications.rb +52 -0
- data/db/migrate/20250605105424_add_shipping_category_foreign_keys.rb +73 -0
- data/db/migrate/20250626112117_add_foreign_key_to_spree_role_users.rb +30 -0
- data/db/migrate/20250628094037_change_countries_iso_to_unique.rb +9 -0
- data/db/migrate/20250708120317_add_adjustment_reason_foreign_keys.rb +30 -0
- data/db/migrate/20250709073151_add_country_foreign_keys.rb +75 -0
- data/db/migrate/20250709084513_add_state_foreign_keys.rb +30 -0
- data/db/migrate/20250726220709_add_fk_to_customer_return.rb +30 -0
- data/lib/generators/solidus/install/app_templates/frontend/starter.rb +1 -1
- data/lib/generators/spree/dummy/dummy_generator.rb +2 -1
- data/lib/generators/spree/dummy/templates/rails/{manifest.js → manifest.js.tt} +2 -0
- data/lib/spree/app_configuration.rb +8 -0
- data/lib/spree/core/engine.rb +7 -2
- data/lib/spree/core/environment.rb +1 -0
- data/lib/spree/core/version.rb +6 -10
- data/lib/spree/core.rb +2 -0
- data/lib/spree/permitted_attributes.rb +2 -1
- data/lib/spree/preferences/preferable.rb +1 -5
- data/lib/spree/testing_support/capybara_driver.rb +9 -0
- data/lib/spree/testing_support/common_rake.rb +6 -3
- data/lib/spree/testing_support/dummy_app/migrations.rb +2 -2
- data/lib/spree/testing_support/dummy_app/rake_tasks.rb +0 -6
- data/lib/spree/testing_support/dummy_app.rb +7 -0
- data/lib/spree/testing_support/factories/zone_factory.rb +4 -0
- data/lib/spree/testing_support/job_helpers.rb +6 -15
- data/lib/spree/testing_support/translations.rb +2 -2
- data/lib/spree/zero.rb +3 -0
- data/solidus_core.gemspec +6 -2
- metadata +56 -5
- /data/{lib → app/models/concerns}/spree/preferences/persistable.rb +0 -0
@@ -56,6 +56,7 @@ class Spree::OrderShipping
|
|
56
56
|
inventory_units:,
|
57
57
|
shipped_at:,
|
58
58
|
external_number:,
|
59
|
+
suppress_email: suppress_mailer,
|
59
60
|
tracking: tracking_number
|
60
61
|
)
|
61
62
|
end
|
@@ -68,18 +69,10 @@ class Spree::OrderShipping
|
|
68
69
|
end
|
69
70
|
end
|
70
71
|
|
71
|
-
send_shipment_emails(carton) if stock_location.fulfillable? && !suppress_mailer # e.g. digital gift cards that aren't actually shipped
|
72
72
|
@order.shipments.reload
|
73
73
|
@order.recalculate
|
74
74
|
|
75
|
+
Spree::Bus.publish(:carton_shipped, carton:)
|
75
76
|
carton
|
76
77
|
end
|
77
|
-
|
78
|
-
private
|
79
|
-
|
80
|
-
def send_shipment_emails(carton)
|
81
|
-
carton.orders.each do |order|
|
82
|
-
Spree::Config.carton_shipped_email_class.shipped_email(order:, carton:).deliver_later
|
83
|
-
end
|
84
|
-
end
|
85
78
|
end
|
@@ -57,7 +57,7 @@ module Spree
|
|
57
57
|
|
58
58
|
# Remove any tax adjustments tied to rates which no longer match.
|
59
59
|
unmatched_adjustments = tax_adjustments - active_adjustments
|
60
|
-
|
60
|
+
unmatched_adjustments.each(&:mark_for_destruction)
|
61
61
|
end
|
62
62
|
|
63
63
|
# Update or create a new tax adjustment on an item.
|
@@ -77,7 +77,8 @@ module Spree
|
|
77
77
|
label: tax_item.label,
|
78
78
|
included: tax_item.included_in_price
|
79
79
|
)
|
80
|
-
|
80
|
+
|
81
|
+
tax_adjustment.amount = tax_item.amount
|
81
82
|
tax_adjustment
|
82
83
|
end
|
83
84
|
end
|
@@ -157,9 +157,12 @@ module Spree
|
|
157
157
|
recalculate_adjustments
|
158
158
|
|
159
159
|
all_items = line_items + shipments
|
160
|
-
|
160
|
+
# Ignore any adjustments that have been marked for destruction in our
|
161
|
+
# calculations. They'll get removed when/if we persist the order.
|
162
|
+
valid_adjustments = adjustments.reject(&:marked_for_destruction?)
|
163
|
+
order_tax_adjustments = valid_adjustments.select(&:tax?)
|
161
164
|
|
162
|
-
order.adjustment_total = all_items.sum(&:adjustment_total) +
|
165
|
+
order.adjustment_total = all_items.sum(&:adjustment_total) + valid_adjustments.sum(&:amount)
|
163
166
|
order.included_tax_total = all_items.sum(&:included_tax_total) + order_tax_adjustments.select(&:included?).sum(&:amount)
|
164
167
|
order.additional_tax_total = all_items.sum(&:additional_tax_total) + order_tax_adjustments.reject(&:included?).sum(&:amount)
|
165
168
|
|
@@ -185,11 +188,12 @@ module Spree
|
|
185
188
|
yield
|
186
189
|
new_state = order.public_send(state)
|
187
190
|
if old_state != new_state
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
191
|
+
StateChangeTrackingJob.perform_later(
|
192
|
+
order,
|
193
|
+
old_state,
|
194
|
+
new_state,
|
195
|
+
Time.current,
|
196
|
+
name
|
193
197
|
)
|
194
198
|
end
|
195
199
|
end
|
data/app/models/spree/product.rb
CHANGED
@@ -23,7 +23,7 @@ module Spree
|
|
23
23
|
|
24
24
|
has_many :product_properties, dependent: :destroy, inverse_of: :product
|
25
25
|
has_many :properties, through: :product_properties
|
26
|
-
has_many :variant_property_rules
|
26
|
+
has_many :variant_property_rules, dependent: :destroy
|
27
27
|
has_many :variant_property_rule_values, through: :variant_property_rules, source: :values
|
28
28
|
has_many :variant_property_rule_conditions, through: :variant_property_rules, source: :conditions
|
29
29
|
|
@@ -31,19 +31,21 @@ module Spree
|
|
31
31
|
has_many :taxons, through: :classifications, before_remove: :remove_taxon
|
32
32
|
|
33
33
|
belongs_to :tax_category, class_name: 'Spree::TaxCategory', optional: true
|
34
|
-
belongs_to :shipping_category, class_name: 'Spree::ShippingCategory', inverse_of: :products
|
34
|
+
belongs_to :shipping_category, class_name: 'Spree::ShippingCategory', inverse_of: :products
|
35
35
|
belongs_to :primary_taxon, class_name: 'Spree::Taxon', optional: true
|
36
36
|
|
37
37
|
has_one :master,
|
38
38
|
-> { where(is_master: true).with_discarded },
|
39
39
|
inverse_of: :product,
|
40
40
|
class_name: 'Spree::Variant',
|
41
|
-
autosave: true
|
41
|
+
autosave: true,
|
42
|
+
dependent: false
|
42
43
|
|
43
44
|
has_many :variants,
|
44
45
|
-> { where(is_master: false).order(:position) },
|
45
46
|
inverse_of: :product,
|
46
|
-
class_name: 'Spree::Variant'
|
47
|
+
class_name: 'Spree::Variant',
|
48
|
+
dependent: false
|
47
49
|
|
48
50
|
has_many :variants_including_master,
|
49
51
|
-> { order(:position) },
|
@@ -122,7 +124,6 @@ module Spree
|
|
122
124
|
validates :meta_title, length: { maximum: 255 }
|
123
125
|
validates :name, presence: true
|
124
126
|
validates :price, presence: true, if: proc { Spree::Config[:require_master_price] }
|
125
|
-
validates :shipping_category_id, presence: true
|
126
127
|
validates :slug, presence: true, uniqueness: { allow_blank: true, case_sensitive: true }
|
127
128
|
|
128
129
|
attr_accessor :option_values_hash
|
@@ -2,8 +2,8 @@
|
|
2
2
|
|
3
3
|
module Spree
|
4
4
|
class ProductOptionType < Spree::Base
|
5
|
-
belongs_to :product, class_name: 'Spree::Product', inverse_of: :product_option_types, touch: true
|
6
|
-
belongs_to :option_type, class_name: 'Spree::OptionType', inverse_of: :product_option_types
|
5
|
+
belongs_to :product, class_name: 'Spree::Product', inverse_of: :product_option_types, touch: true
|
6
|
+
belongs_to :option_type, class_name: 'Spree::OptionType', inverse_of: :product_option_types
|
7
7
|
acts_as_list scope: :product
|
8
8
|
end
|
9
9
|
end
|
@@ -6,8 +6,8 @@ module Spree
|
|
6
6
|
|
7
7
|
acts_as_list scope: :product
|
8
8
|
|
9
|
-
belongs_to :product, touch: true, class_name: 'Spree::Product', inverse_of: :product_properties
|
10
|
-
belongs_to :property, class_name: 'Spree::Property', inverse_of: :product_properties
|
9
|
+
belongs_to :product, touch: true, class_name: 'Spree::Product', inverse_of: :product_properties
|
10
|
+
belongs_to :property, class_name: 'Spree::Property', inverse_of: :product_properties
|
11
11
|
|
12
12
|
self.allowed_ransackable_attributes = ['value']
|
13
13
|
end
|
@@ -3,12 +3,12 @@
|
|
3
3
|
module Spree
|
4
4
|
class RoleUser < Spree::Base
|
5
5
|
self.table_name = "spree_roles_users"
|
6
|
-
belongs_to :role, class_name: "Spree::Role"
|
7
|
-
belongs_to :user, class_name: Spree::UserClassHandle.new
|
6
|
+
belongs_to :role, class_name: "Spree::Role"
|
7
|
+
belongs_to :user, class_name: Spree::UserClassHandle.new
|
8
8
|
|
9
9
|
after_create :auto_generate_spree_api_key
|
10
10
|
|
11
|
-
|
11
|
+
validates :role_id, uniqueness: { scope: :user_id }
|
12
12
|
|
13
13
|
private
|
14
14
|
|
@@ -200,15 +200,11 @@ module Spree
|
|
200
200
|
end
|
201
201
|
end
|
202
202
|
|
203
|
-
# Determines the appropriate +state+ according to the following logic:
|
204
|
-
#
|
205
|
-
# canceled if order is canceled
|
206
|
-
# pending unless order is complete and +order.payment_state+ is +paid+
|
207
|
-
# shipped if already shipped (ie. does not change the state)
|
208
|
-
# ready all other cases
|
209
203
|
def determine_state(order)
|
210
|
-
|
204
|
+
Spree.deprecator.warn "Use Spree::Shipment#recalculate_state instead"
|
205
|
+
|
211
206
|
return 'shipped' if shipped?
|
207
|
+
return 'canceled' if order.canceled? || inventory_units.all?(&:canceled?)
|
212
208
|
return 'pending' unless order.can_ship?
|
213
209
|
if can_transition_from_pending_to_ready?
|
214
210
|
'ready'
|
@@ -217,6 +213,27 @@ module Spree
|
|
217
213
|
end
|
218
214
|
end
|
219
215
|
|
216
|
+
# Assigns the appropriate +state+ according to the following logic:
|
217
|
+
#
|
218
|
+
# canceled if order is canceled
|
219
|
+
# pending unless order is complete and +order.payment_state+ is +paid+
|
220
|
+
# shipped if already shipped (ie. does not change the state)
|
221
|
+
# ready all other cases
|
222
|
+
def recalculate_state
|
223
|
+
self.state =
|
224
|
+
if shipped?
|
225
|
+
"shipped"
|
226
|
+
elsif order.canceled? || inventory_units.all?(&:canceled?)
|
227
|
+
"canceled"
|
228
|
+
elsif !order.can_ship?
|
229
|
+
"pending"
|
230
|
+
elsif can_transition_from_pending_to_ready?
|
231
|
+
"ready"
|
232
|
+
else
|
233
|
+
"pending"
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
220
237
|
def set_up_inventory(state, variant, _order, line_item)
|
221
238
|
inventory_units.create(
|
222
239
|
state:,
|
@@ -292,12 +309,9 @@ module Spree
|
|
292
309
|
# called.
|
293
310
|
def update_state
|
294
311
|
old_state = state
|
295
|
-
new_state =
|
312
|
+
new_state = recalculate_state
|
296
313
|
if new_state != old_state
|
297
|
-
update_columns
|
298
|
-
state: new_state,
|
299
|
-
updated_at: Time.current
|
300
|
-
)
|
314
|
+
update_columns state: new_state, updated_at: Time.current
|
301
315
|
after_ship if new_state == 'shipped'
|
302
316
|
end
|
303
317
|
end
|
@@ -5,8 +5,8 @@ module Spree
|
|
5
5
|
self.allowed_ransackable_attributes = %w[name]
|
6
6
|
|
7
7
|
validates :name, presence: true
|
8
|
-
has_many :products, inverse_of: :shipping_category
|
9
|
-
has_many :shipping_method_categories, inverse_of: :shipping_category
|
8
|
+
has_many :products, inverse_of: :shipping_category, dependent: :restrict_with_error
|
9
|
+
has_many :shipping_method_categories, inverse_of: :shipping_category, dependent: :destroy
|
10
10
|
has_many :shipping_methods, through: :shipping_method_categories
|
11
11
|
end
|
12
12
|
end
|
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
module Spree
|
4
4
|
class ShippingMethodCategory < Spree::Base
|
5
|
-
belongs_to :shipping_method, class_name: 'Spree::ShippingMethod'
|
6
|
-
belongs_to :shipping_category, class_name: 'Spree::ShippingCategory', inverse_of: :shipping_method_categories
|
5
|
+
belongs_to :shipping_method, class_name: 'Spree::ShippingMethod'
|
6
|
+
belongs_to :shipping_category, class_name: 'Spree::ShippingCategory', inverse_of: :shipping_method_categories
|
7
7
|
end
|
8
8
|
end
|
data/app/models/spree/state.rb
CHANGED
@@ -2,10 +2,10 @@
|
|
2
2
|
|
3
3
|
module Spree
|
4
4
|
class State < Spree::Base
|
5
|
-
belongs_to :country, class_name: 'Spree::Country'
|
6
|
-
has_many :addresses, dependent: :nullify
|
5
|
+
belongs_to :country, class_name: 'Spree::Country'
|
6
|
+
has_many :addresses, dependent: :nullify, inverse_of: :state
|
7
7
|
|
8
|
-
validates :
|
8
|
+
validates :name, presence: true
|
9
9
|
|
10
10
|
scope :with_name_or_abbr, ->(name_or_abbr) do
|
11
11
|
where(
|
@@ -15,6 +15,7 @@ module Spree
|
|
15
15
|
)
|
16
16
|
end
|
17
17
|
|
18
|
+
self.allowed_ransackable_associations = %w[country]
|
18
19
|
self.allowed_ransackable_attributes = %w[name]
|
19
20
|
|
20
21
|
# table of { country.id => [ state.id , state.name ] }, arrays sorted by name
|
@@ -36,7 +37,9 @@ module Spree
|
|
36
37
|
end
|
37
38
|
|
38
39
|
def state_with_country
|
39
|
-
"#{
|
40
|
+
Rails.cache.fetch("#{cache_key_with_version}/state_with_country") do
|
41
|
+
"#{name} (#{country})"
|
42
|
+
end
|
40
43
|
end
|
41
44
|
end
|
42
45
|
end
|
@@ -11,14 +11,8 @@ module Spree
|
|
11
11
|
# If unspecified it will check inventory in all available StockLocations
|
12
12
|
def initialize(variant, stock_location_or_id = nil)
|
13
13
|
@variant = variant
|
14
|
-
@
|
15
|
-
|
16
|
-
stock_item.stock_location == stock_location_or_id ||
|
17
|
-
stock_item.stock_location_id == stock_location_or_id
|
18
|
-
else
|
19
|
-
stock_item.stock_location.active?
|
20
|
-
end
|
21
|
-
end
|
14
|
+
@stock_location_or_id = stock_location_or_id
|
15
|
+
@stock_items = variant_stock_items
|
22
16
|
end
|
23
17
|
|
24
18
|
# Returns the total number of inventory units on hand for the variant.
|
@@ -26,7 +20,7 @@ module Spree
|
|
26
20
|
# @return [Fixnum] number of inventory units on hand, or infinity if
|
27
21
|
# inventory is not tracked on the variant.
|
28
22
|
def total_on_hand
|
29
|
-
if
|
23
|
+
if variant.should_track_inventory?
|
30
24
|
stock_items.sum(&:count_on_hand)
|
31
25
|
else
|
32
26
|
Float::INFINITY
|
@@ -48,6 +42,36 @@ module Spree
|
|
48
42
|
def can_supply?(required)
|
49
43
|
total_on_hand >= required || backorderable?
|
50
44
|
end
|
45
|
+
|
46
|
+
def positive_stock
|
47
|
+
return unless stock_location
|
48
|
+
|
49
|
+
on_hand = stock_location.count_on_hand(variant)
|
50
|
+
on_hand.positive? ? on_hand : 0
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
attr_reader :variant, :stock_location_or_id
|
56
|
+
|
57
|
+
def stock_location
|
58
|
+
@stock_location ||= if stock_location_or_id.is_a?(Spree::StockLocation)
|
59
|
+
stock_location_or_id
|
60
|
+
else
|
61
|
+
Spree::StockLocation.find_by(id: stock_location_or_id)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def variant_stock_items
|
66
|
+
variant.stock_items.select do |stock_item|
|
67
|
+
if stock_location_or_id
|
68
|
+
stock_item.stock_location == stock_location_or_id ||
|
69
|
+
stock_item.stock_location_id == stock_location_or_id
|
70
|
+
else
|
71
|
+
stock_item.stock_location.active?
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
51
75
|
end
|
52
76
|
end
|
53
77
|
end
|
@@ -106,7 +106,7 @@ module Spree
|
|
106
106
|
def should_touch_variant?
|
107
107
|
# the variant_id changes from nil when a new stock location is added
|
108
108
|
inventory_cache_threshold &&
|
109
|
-
|
109
|
+
saved_change_to_count_on_hand&.any? { |cache| cache < inventory_cache_threshold } ||
|
110
110
|
saved_change_to_variant_id?
|
111
111
|
end
|
112
112
|
|
@@ -15,6 +15,7 @@ module Spree
|
|
15
15
|
has_many :stock_movements, through: :stock_items
|
16
16
|
has_many :user_stock_locations, dependent: :delete_all
|
17
17
|
has_many :users, through: :user_stock_locations
|
18
|
+
has_many :customer_returns, inverse_of: :stock_location, dependent: :restrict_with_error
|
18
19
|
|
19
20
|
belongs_to :state, class_name: 'Spree::State', optional: true
|
20
21
|
belongs_to :country, class_name: 'Spree::Country', optional: true
|
@@ -22,8 +23,8 @@ module Spree
|
|
22
23
|
has_many :shipping_method_stock_locations, dependent: :destroy
|
23
24
|
has_many :shipping_methods, through: :shipping_method_stock_locations
|
24
25
|
|
25
|
-
|
26
|
-
|
26
|
+
validates :name, presence: true
|
27
|
+
validates :code, uniqueness: { allow_blank: true, case_sensitive: false }
|
27
28
|
|
28
29
|
scope :active, -> { where(active: true) }
|
29
30
|
scope :order_default, -> { order(default: :desc, position: :asc) }
|
data/app/models/spree/store.rb
CHANGED
@@ -27,6 +27,12 @@ module Spree
|
|
27
27
|
before_save :ensure_default_exists_and_is_unique
|
28
28
|
before_destroy :validate_not_default
|
29
29
|
|
30
|
+
enum :reverse_charge_status, {
|
31
|
+
disabled: 0,
|
32
|
+
enabled: 1,
|
33
|
+
not_validated: 2
|
34
|
+
}, prefix: true
|
35
|
+
|
30
36
|
def available_locales
|
31
37
|
locales = super()
|
32
38
|
if locales
|
@@ -18,9 +18,9 @@ class Spree::StoreCredit < Spree::PaymentSource
|
|
18
18
|
belongs_to :credit_type, class_name: 'Spree::StoreCreditType', foreign_key: 'type_id', optional: true
|
19
19
|
has_many :store_credit_events
|
20
20
|
|
21
|
-
|
22
|
-
|
23
|
-
|
21
|
+
validates :user_id, :category_id, :type_id, :created_by_id, :currency, presence: true
|
22
|
+
validates :amount, numericality: { greater_than: 0 }
|
23
|
+
validates :amount_used, numericality: { greater_than_or_equal_to: 0 }
|
24
24
|
validate :amount_used_less_than_or_equal_to_amount
|
25
25
|
validate :amount_authorized_less_than_or_equal_to_amount
|
26
26
|
|
@@ -9,7 +9,7 @@ module Spree
|
|
9
9
|
belongs_to :originator, polymorphic: true, optional: true
|
10
10
|
belongs_to :store_credit_reason, class_name: 'Spree::StoreCreditReason', inverse_of: :store_credit_events, optional: true
|
11
11
|
|
12
|
-
|
12
|
+
validates :store_credit_reason, presence: { if: :action_requires_reason? }
|
13
13
|
|
14
14
|
NON_EXPOSED_ACTIONS = [Spree::StoreCredit::ELIGIBLE_ACTION, Spree::StoreCredit::AUTHORIZE_ACTION]
|
15
15
|
|
@@ -11,7 +11,7 @@ module Spree
|
|
11
11
|
end
|
12
12
|
|
13
13
|
validates :name, presence: true
|
14
|
-
|
14
|
+
validates :name, uniqueness: { case_sensitive: true, unless: :deleted_at }
|
15
15
|
|
16
16
|
has_many :tax_rate_tax_categories,
|
17
17
|
class_name: 'Spree::TaxRateTaxCategory',
|
data/app/models/spree/taxon.rb
CHANGED
@@ -13,9 +13,6 @@ module Spree
|
|
13
13
|
has_many :classifications, -> { order(:position) }, dependent: :delete_all, inverse_of: :taxon
|
14
14
|
has_many :products, through: :classifications
|
15
15
|
|
16
|
-
has_many :promotion_rule_taxons
|
17
|
-
has_many :promotion_rules, through: :promotion_rule_taxons
|
18
|
-
|
19
16
|
before_save :set_permalink
|
20
17
|
after_update :update_child_permalinks, if: :saved_change_to_permalink?
|
21
18
|
|
@@ -7,8 +7,8 @@ module Spree
|
|
7
7
|
validates :name, presence: true
|
8
8
|
validates :name, uniqueness: true
|
9
9
|
|
10
|
-
has_many :taxons, inverse_of: :taxonomy
|
11
|
-
has_one :root, -> { where parent_id: nil }, class_name: "Spree::Taxon", dependent: :destroy
|
10
|
+
has_many :taxons, inverse_of: :taxonomy, dependent: false
|
11
|
+
has_one :root, -> { where parent_id: nil }, class_name: "Spree::Taxon", dependent: :destroy, inverse_of: false
|
12
12
|
|
13
13
|
after_save :set_name
|
14
14
|
|
@@ -2,11 +2,11 @@
|
|
2
2
|
|
3
3
|
module Spree
|
4
4
|
class UserAddress < Spree::Base
|
5
|
-
belongs_to :user, class_name: UserClassHandle.new, foreign_key: "user_id",
|
6
|
-
belongs_to :address, class_name: "Spree::Address"
|
5
|
+
belongs_to :user, class_name: UserClassHandle.new, foreign_key: "user_id", inverse_of: :user_addresses
|
6
|
+
belongs_to :address, class_name: "Spree::Address"
|
7
7
|
|
8
|
-
|
9
|
-
|
8
|
+
validates :address_id, uniqueness: { scope: :user_id }
|
9
|
+
validates :user_id, uniqueness: { conditions: -> { default_shipping }, message: :default_address_exists, if: :default? }
|
10
10
|
|
11
11
|
scope :with_address_values, ->(address_attributes) do
|
12
12
|
joins(:address).merge(
|
data/app/models/spree/variant.rb
CHANGED
@@ -74,7 +74,7 @@ module Spree
|
|
74
74
|
|
75
75
|
validates :cost_price, numericality: { greater_than_or_equal_to: 0, allow_nil: true }
|
76
76
|
validates :price, numericality: { greater_than_or_equal_to: 0, allow_nil: true }
|
77
|
-
|
77
|
+
validates :sku, uniqueness: { allow_blank: true, case_sensitive: true, conditions: -> { where(deleted_at: nil) }, if: :enforce_unique_sku? }
|
78
78
|
|
79
79
|
after_create :create_stock_items
|
80
80
|
after_create :set_master_out_of_stock, unless: :is_master?
|
@@ -13,7 +13,7 @@
|
|
13
13
|
# targeted by the rule, the properties will automatically apply to the variant.
|
14
14
|
module Spree
|
15
15
|
class VariantPropertyRule < Spree::Base
|
16
|
-
belongs_to :product, touch: true
|
16
|
+
belongs_to :product, touch: true
|
17
17
|
|
18
18
|
has_many :values, class_name: 'Spree::VariantPropertyRuleValue', dependent: :destroy
|
19
19
|
has_many :properties, through: :values
|
@@ -5,6 +5,6 @@ module Spree
|
|
5
5
|
belongs_to :option_value, optional: true
|
6
6
|
belongs_to :variant_property_rule, touch: true, optional: true
|
7
7
|
|
8
|
-
|
8
|
+
validates :option_value_id, uniqueness: { scope: :variant_property_rule_id }
|
9
9
|
end
|
10
10
|
end
|
@@ -5,8 +5,8 @@ module Spree
|
|
5
5
|
belongs_to :user, class_name: Spree::UserClassHandle.new, foreign_key: 'user_id', inverse_of: :wallet_payment_sources, optional: true
|
6
6
|
belongs_to :payment_source, polymorphic: true, inverse_of: :wallet_payment_sources, optional: true
|
7
7
|
|
8
|
-
|
9
|
-
|
8
|
+
validates :user, presence: true
|
9
|
+
validates :payment_source, presence: true
|
10
10
|
validates :user_id, uniqueness: {
|
11
11
|
scope: [:payment_source_type, :payment_source_id],
|
12
12
|
message: :payment_source_already_exists
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Spree
|
4
|
+
# Mailing after {Spree::Carton} is created.
|
5
|
+
class CartonShippedMailerSubscriber
|
6
|
+
include Omnes::Subscriber
|
7
|
+
|
8
|
+
handle :carton_shipped,
|
9
|
+
with: :send_carton_shipped_emails,
|
10
|
+
id: :spree_carton_mailer_send_carton_shipped_email
|
11
|
+
|
12
|
+
# Sends carton shipped emails to users.
|
13
|
+
#
|
14
|
+
# @param event [Omnes::UnstructuredEvent]
|
15
|
+
def send_carton_shipped_emails(event)
|
16
|
+
carton = event[:carton]
|
17
|
+
|
18
|
+
return if carton.suppress_email
|
19
|
+
|
20
|
+
# Do not send emails for unfulfillable cartons (i.e. for digital goods).
|
21
|
+
return unless carton.stock_location.fulfillable?
|
22
|
+
|
23
|
+
carton.orders.each do |order|
|
24
|
+
Spree::Config.carton_shipped_email_class
|
25
|
+
.shipped_email(order:, carton:)
|
26
|
+
.deliver_later
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Spree
|
4
|
+
# Mailing after {Spree::Order} is cancelled.
|
5
|
+
class OrderCancelMailerSubscriber
|
6
|
+
include Omnes::Subscriber
|
7
|
+
|
8
|
+
handle :order_canceled,
|
9
|
+
with: :send_cancel_email,
|
10
|
+
id: :spree_order_mailer_send_cancel_email
|
11
|
+
|
12
|
+
# Sends cancellation email to the user.
|
13
|
+
#
|
14
|
+
# @param event [Omnes::UnstructuredEvent]
|
15
|
+
def send_cancel_email(event)
|
16
|
+
order = event[:order]
|
17
|
+
|
18
|
+
Spree::Config.order_mailer_class.cancel_email(order).deliver_later
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Spree
|
4
|
+
# Mailing after {Spree::Order} is confirmed.
|
5
|
+
class OrderConfirmationMailerSubscriber
|
6
|
+
include Omnes::Subscriber
|
7
|
+
|
8
|
+
handle :order_finalized,
|
9
|
+
with: :send_confirmation_email,
|
10
|
+
id: :spree_order_mailer_send_confirmation_email
|
11
|
+
|
12
|
+
# Sends confirmation email to the user.
|
13
|
+
#
|
14
|
+
# @param event [Omnes::UnstructuredEvent]
|
15
|
+
def send_confirmation_email(event)
|
16
|
+
order = event[:order]
|
17
|
+
unless order.confirmation_delivered?
|
18
|
+
Spree::Config.order_mailer_class.confirm_email(order).deliver_later
|
19
|
+
order.update_column(:confirmation_delivered, true)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Spree
|
4
|
+
# Mailing after inventory units have been cancelled from a {Spree::Order}
|
5
|
+
class OrderInventoryCancellationMailerSubscriber
|
6
|
+
include Omnes::Subscriber
|
7
|
+
|
8
|
+
handle :order_short_shipped,
|
9
|
+
with: :send_inventory_cancellation_email,
|
10
|
+
id: :spree_order_mailer_send_inventory_cancellation_email
|
11
|
+
|
12
|
+
# Sends inventory cancellation email to the user.
|
13
|
+
#
|
14
|
+
# @param event [Omnes::UnstructuredEvent]
|
15
|
+
def send_inventory_cancellation_email(event)
|
16
|
+
return unless Spree::OrderCancellations.send_cancellation_mailer
|
17
|
+
|
18
|
+
order = event[:order]
|
19
|
+
inventory_units = event[:inventory_units]
|
20
|
+
|
21
|
+
Spree::Config
|
22
|
+
.order_mailer_class
|
23
|
+
.inventory_cancellation_email(order, inventory_units.to_a)
|
24
|
+
.deliver_later
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|