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
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f616e30c09a8f81468fd2f3d646b4ba5624ad26af29aae44985622adf3db57b8
|
4
|
+
data.tar.gz: 982dc95e2dc4518445e5dd6d133354cd283663028902c55ad4850af1e18ea4cd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9a4cd294113878e692b12af0214b7200522d4ce583a2d515e7d848c342fe787d64dd78c9b9a9b6de02fdf7b2c47a5bab7e3a5054cb0d76935851c7935d3b79d3
|
7
|
+
data.tar.gz: aa69ad3e6b7616a701675aca113da85e7b9472f6f95ffe2bc42ea1fa1115ceffdcb1c710482e8d4a509616d1a6c5c0036a157dd92405f6937eea261fbdc38c77
|
data/README.md
CHANGED
@@ -0,0 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Spree
|
4
|
+
# Base class for all Solidus background jobs
|
5
|
+
class BaseJob < ActiveJob::Base # rubocop:disable Rails/ApplicationJob
|
6
|
+
# Automatically retry jobs that encountered a deadlock
|
7
|
+
retry_on ActiveRecord::Deadlocked
|
8
|
+
|
9
|
+
# Most jobs are safe to ignore if the underlying records are no longer available
|
10
|
+
discard_on ActiveJob::DeserializationError
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Spree
|
4
|
+
# Background job to track state changes asynchronously
|
5
|
+
# This avoids performance impact during checkout and prevents
|
6
|
+
# callback-related issues with recent versions of the state_machines gem.
|
7
|
+
class StateChangeTrackingJob < BaseJob
|
8
|
+
# @param stateful [GlobalId] The stateful object to track changes for
|
9
|
+
# @param previous_state [String] The previous state of the order
|
10
|
+
# @param current_state [String] The current state of the order
|
11
|
+
# @param transition_timestamp [Time] When the state transition occurred
|
12
|
+
# @param name [String] The element name of the state transition being
|
13
|
+
# tracked. It defaults to the `stateful` model element name.
|
14
|
+
def perform(
|
15
|
+
stateful,
|
16
|
+
previous_state,
|
17
|
+
current_state,
|
18
|
+
transition_timestamp,
|
19
|
+
name = stateful.class.model_name.element
|
20
|
+
)
|
21
|
+
Spree::StateChange.create!(
|
22
|
+
name: name,
|
23
|
+
stateful: stateful,
|
24
|
+
previous_state: previous_state,
|
25
|
+
next_state: current_state,
|
26
|
+
created_at: transition_timestamp,
|
27
|
+
updated_at: transition_timestamp,
|
28
|
+
user_id: stateful.try(:user_id) || stateful.try(:order)&.user_id
|
29
|
+
)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Spree
|
4
|
+
module StateChangeTracking
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
included do
|
8
|
+
after_update :enqueue_state_change_tracking, if: :saved_change_to_state?
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
# Enqueue background job to track state changes asynchronously
|
14
|
+
def enqueue_state_change_tracking
|
15
|
+
previous_state, current_state = saved_changes['state']
|
16
|
+
|
17
|
+
# Enqueue the job to track this state change
|
18
|
+
StateChangeTrackingJob.perform_later(
|
19
|
+
self,
|
20
|
+
previous_state,
|
21
|
+
current_state,
|
22
|
+
Time.current
|
23
|
+
)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -5,7 +5,7 @@ module Spree
|
|
5
5
|
extend ActiveSupport::Concern
|
6
6
|
|
7
7
|
included do
|
8
|
-
has_many :user_addresses, foreign_key: "user_id", class_name: "Spree::UserAddress" do
|
8
|
+
has_many :user_addresses, foreign_key: "user_id", class_name: "Spree::UserAddress", inverse_of: :user, dependent: :destroy do
|
9
9
|
def find_first_by_address_values(address_attrs)
|
10
10
|
detect { |ua| ua.address == Spree::Address.new(address_attrs) }
|
11
11
|
end
|
@@ -32,11 +32,29 @@ module Spree
|
|
32
32
|
|
33
33
|
has_many :addresses, through: :user_addresses
|
34
34
|
|
35
|
-
has_one :default_user_bill_address,
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
35
|
+
has_one :default_user_bill_address,
|
36
|
+
->{ default_billing },
|
37
|
+
class_name: 'Spree::UserAddress',
|
38
|
+
foreign_key: 'user_id',
|
39
|
+
inverse_of: false,
|
40
|
+
dependent: false
|
41
|
+
has_one :bill_address,
|
42
|
+
through: :default_user_bill_address,
|
43
|
+
source: :address,
|
44
|
+
inverse_of: false,
|
45
|
+
dependent: false
|
46
|
+
|
47
|
+
has_one :default_user_ship_address,
|
48
|
+
->{ default_shipping },
|
49
|
+
class_name: 'Spree::UserAddress',
|
50
|
+
foreign_key: 'user_id',
|
51
|
+
inverse_of: false,
|
52
|
+
dependent: false
|
53
|
+
has_one :ship_address,
|
54
|
+
through: :default_user_ship_address,
|
55
|
+
source: :address,
|
56
|
+
inverse_of: false,
|
57
|
+
dependent: false
|
40
58
|
|
41
59
|
accepts_nested_attributes_for :ship_address
|
42
60
|
accepts_nested_attributes_for :bill_address
|
@@ -11,20 +11,58 @@ module Spree
|
|
11
11
|
included do
|
12
12
|
extend Spree::DisplayMoney
|
13
13
|
|
14
|
-
has_many :role_users,
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
14
|
+
has_many :role_users,
|
15
|
+
foreign_key: "user_id",
|
16
|
+
class_name: "Spree::RoleUser",
|
17
|
+
dependent: :destroy,
|
18
|
+
inverse_of: :user
|
19
|
+
has_many :spree_roles,
|
20
|
+
through: :role_users,
|
21
|
+
source: :role,
|
22
|
+
class_name: "Spree::Role",
|
23
|
+
inverse_of: :users
|
24
|
+
|
25
|
+
has_many :user_stock_locations,
|
26
|
+
foreign_key: "user_id",
|
27
|
+
class_name: "Spree::UserStockLocation",
|
28
|
+
inverse_of: :user,
|
29
|
+
dependent: :destroy
|
30
|
+
has_many :stock_locations,
|
31
|
+
through: :user_stock_locations,
|
32
|
+
inverse_of: :users
|
33
|
+
|
34
|
+
has_many :spree_orders,
|
35
|
+
foreign_key: "user_id",
|
36
|
+
class_name: "Spree::Order",
|
37
|
+
inverse_of: :user,
|
38
|
+
dependent: false
|
39
|
+
has_many :orders,
|
40
|
+
foreign_key: "user_id",
|
41
|
+
class_name: "Spree::Order",
|
42
|
+
inverse_of: :user,
|
43
|
+
dependent: false
|
44
|
+
|
45
|
+
has_many :store_credits,
|
46
|
+
-> { includes(:credit_type) },
|
47
|
+
foreign_key: "user_id",
|
48
|
+
class_name: "Spree::StoreCredit",
|
49
|
+
dependent: :nullify,
|
50
|
+
inverse_of: :user
|
51
|
+
has_many :store_credit_events,
|
52
|
+
through: :store_credits,
|
53
|
+
inverse_of: false
|
54
|
+
|
55
|
+
has_many :credit_cards,
|
56
|
+
class_name: "Spree::CreditCard",
|
57
|
+
foreign_key: :user_id,
|
58
|
+
dependent: :nullify,
|
59
|
+
inverse_of: :user
|
60
|
+
|
61
|
+
has_many :wallet_payment_sources,
|
62
|
+
foreign_key: 'user_id',
|
63
|
+
class_name: 'Spree::WalletPaymentSource',
|
64
|
+
inverse_of: :user,
|
65
|
+
dependent: :destroy
|
28
66
|
|
29
67
|
after_create :auto_generate_spree_api_key
|
30
68
|
before_destroy :check_for_deletion
|
data/app/models/spree/address.rb
CHANGED
@@ -11,10 +11,10 @@ module Spree
|
|
11
11
|
mattr_accessor :state_validator_class
|
12
12
|
self.state_validator_class = Spree::Address::StateValidator
|
13
13
|
|
14
|
-
belongs_to :country, class_name: "Spree::Country"
|
14
|
+
belongs_to :country, class_name: "Spree::Country"
|
15
15
|
belongs_to :state, class_name: "Spree::State", optional: true
|
16
16
|
|
17
|
-
validates :address1, :city, :
|
17
|
+
validates :address1, :city, :name, presence: true
|
18
18
|
validates :zipcode, presence: true, if: :require_zipcode?
|
19
19
|
validates :phone, presence: true, if: :require_phone?
|
20
20
|
|
@@ -28,6 +28,12 @@ module Spree
|
|
28
28
|
|
29
29
|
self.allowed_ransackable_attributes = %w[name]
|
30
30
|
|
31
|
+
enum :reverse_charge_status, {
|
32
|
+
disabled: 0,
|
33
|
+
enabled: 1,
|
34
|
+
not_validated: 2
|
35
|
+
}, prefix: true
|
36
|
+
|
31
37
|
unless ActiveRecord::Relation.method_defined? :with_values # Rails 7.1+
|
32
38
|
scope :with_values, ->(attributes) do
|
33
39
|
where(value_attributes(attributes))
|
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
module Spree
|
4
4
|
class AdjustmentReason < Spree::Base
|
5
|
-
has_many :adjustments, inverse_of: :adjustment_reason
|
5
|
+
has_many :adjustments, inverse_of: :adjustment_reason, dependent: :restrict_with_error
|
6
6
|
|
7
7
|
validates :name, presence: true, uniqueness: { case_sensitive: false, allow_blank: true }
|
8
8
|
validates :code, presence: true, uniqueness: { case_sensitive: false, allow_blank: true }
|
data/app/models/spree/carton.rb
CHANGED
@@ -15,6 +15,13 @@ class Spree::Carton < Spree::Base
|
|
15
15
|
validates :inventory_units, presence: true
|
16
16
|
validates :shipped_at, presence: true
|
17
17
|
|
18
|
+
# This accessor is used by the `Spree::CartonShippedMailerSubscriber`
|
19
|
+
# on carton creation to either send or suppress the associated
|
20
|
+
# carton shipped email.
|
21
|
+
#
|
22
|
+
# @return [boolean, NilClass] Whether the email should be suppressed.
|
23
|
+
attr_accessor :suppress_email
|
24
|
+
|
18
25
|
make_permalink field: :number, length: 11, prefix: 'C'
|
19
26
|
|
20
27
|
scope :trackable, -> { where("tracking IS NOT NULL AND tracking != ''") }
|
@@ -4,10 +4,10 @@ module Spree
|
|
4
4
|
class Classification < Spree::Base
|
5
5
|
self.table_name = 'spree_products_taxons'
|
6
6
|
acts_as_list scope: :taxon
|
7
|
-
belongs_to :product, class_name: "Spree::Product", inverse_of: :classifications, touch: true
|
8
|
-
belongs_to :taxon, class_name: "Spree::Taxon", inverse_of: :classifications, touch: true
|
7
|
+
belongs_to :product, class_name: "Spree::Product", inverse_of: :classifications, touch: true
|
8
|
+
belongs_to :taxon, class_name: "Spree::Taxon", inverse_of: :classifications, touch: true
|
9
9
|
|
10
10
|
# For https://github.com/spree/spree/issues/3494
|
11
|
-
|
11
|
+
validates :taxon_id, uniqueness: { scope: :product_id, message: :already_linked }
|
12
12
|
end
|
13
13
|
end
|
@@ -38,22 +38,6 @@ module Spree
|
|
38
38
|
state_machine :state, initial: :cart, use_transactions: false do
|
39
39
|
klass.next_event_transitions.each { |state| transition(state.merge(on: :next)) }
|
40
40
|
|
41
|
-
# Persist the state on the order
|
42
|
-
after_transition do |order, transition|
|
43
|
-
# Hard to say if this is really necessary, it was introduced in this commit:
|
44
|
-
# https://github.com/mamhoff/solidus/commit/fa1d66c42e4c04ee7cd1c20d87e4cdb74a226d3d
|
45
|
-
# But it seems to be harmless, so we'll keep it for now.
|
46
|
-
order.state = order.state # rubocop:disable Lint/SelfAssignment
|
47
|
-
|
48
|
-
order.state_changes.create(
|
49
|
-
previous_state: transition.from,
|
50
|
-
next_state: transition.to,
|
51
|
-
name: 'order',
|
52
|
-
user_id: order.user_id
|
53
|
-
)
|
54
|
-
order.save
|
55
|
-
end
|
56
|
-
|
57
41
|
event :cancel do
|
58
42
|
transition to: :canceled, if: :allow_cancel?, from: :complete
|
59
43
|
end
|
@@ -15,6 +15,7 @@ module Spree
|
|
15
15
|
#
|
16
16
|
module Payment
|
17
17
|
extend ActiveSupport::Concern
|
18
|
+
include StateChangeTracking
|
18
19
|
|
19
20
|
included do
|
20
21
|
state_machine initial: :checkout do
|
@@ -45,14 +46,6 @@ module Spree
|
|
45
46
|
event :invalidate do
|
46
47
|
transition from: [:checkout], to: :invalid
|
47
48
|
end
|
48
|
-
|
49
|
-
after_transition do |payment, transition|
|
50
|
-
payment.state_changes.create!(
|
51
|
-
previous_state: transition.from,
|
52
|
-
next_state: transition.to,
|
53
|
-
name: 'payment'
|
54
|
-
)
|
55
|
-
end
|
56
49
|
end
|
57
50
|
end
|
58
51
|
end
|
@@ -15,6 +15,7 @@ module Spree
|
|
15
15
|
#
|
16
16
|
module Shipment
|
17
17
|
extend ActiveSupport::Concern
|
18
|
+
include StateChangeTracking
|
18
19
|
|
19
20
|
included do
|
20
21
|
state_machine initial: :pending, use_transactions: false do
|
@@ -42,14 +43,6 @@ module Spree
|
|
42
43
|
transition from: :canceled, to: :pending
|
43
44
|
end
|
44
45
|
after_transition from: :canceled, to: [:pending, :ready, :shipped], do: :after_resume
|
45
|
-
|
46
|
-
after_transition do |shipment, transition|
|
47
|
-
shipment.state_changes.create!(
|
48
|
-
previous_state: transition.from,
|
49
|
-
next_state: transition.to,
|
50
|
-
name: 'shipment'
|
51
|
-
)
|
52
|
-
end
|
53
46
|
end
|
54
47
|
end
|
55
48
|
end
|
data/app/models/spree/country.rb
CHANGED
@@ -2,11 +2,22 @@
|
|
2
2
|
|
3
3
|
module Spree
|
4
4
|
class Country < Spree::Base
|
5
|
-
has_many :states,
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
5
|
+
has_many :states,
|
6
|
+
-> { order(:name) },
|
7
|
+
dependent: :destroy,
|
8
|
+
inverse_of: :country
|
9
|
+
has_many :addresses,
|
10
|
+
dependent: :restrict_with_error,
|
11
|
+
inverse_of: :country
|
12
|
+
has_many :prices,
|
13
|
+
class_name: "Spree::Price",
|
14
|
+
foreign_key: "country_iso",
|
15
|
+
primary_key: "iso",
|
16
|
+
dependent: :restrict_with_error,
|
17
|
+
inverse_of: :country
|
18
|
+
|
19
|
+
validates :name, :iso_name, :iso, presence: true
|
20
|
+
validates :iso, uniqueness: true
|
10
21
|
|
11
22
|
self.allowed_ransackable_attributes = %w[name]
|
12
23
|
|
@@ -4,7 +4,7 @@ module Spree
|
|
4
4
|
class CustomerReturn < Spree::Base
|
5
5
|
include Metadata
|
6
6
|
|
7
|
-
belongs_to :stock_location
|
7
|
+
belongs_to :stock_location
|
8
8
|
|
9
9
|
has_many :return_items, inverse_of: :customer_return
|
10
10
|
has_many :return_authorizations, through: :return_items
|
@@ -14,7 +14,6 @@ module Spree
|
|
14
14
|
before_create :generate_number
|
15
15
|
|
16
16
|
validates :return_items, presence: true
|
17
|
-
validates :stock_location, presence: true
|
18
17
|
validate :return_items_belong_to_same_order
|
19
18
|
|
20
19
|
accepts_nested_attributes_for :return_items
|
@@ -86,15 +86,21 @@ module Spree
|
|
86
86
|
# we can take from the desired location, we could end up with some items being backordered.
|
87
87
|
def run_tracking_inventory
|
88
88
|
# Retrieve how many on hand items we can take from desired stock location
|
89
|
-
available_quantity =
|
90
|
-
|
89
|
+
available_quantity = get_available_quantity
|
91
90
|
new_on_hand_quantity = [available_quantity, quantity].min
|
92
|
-
|
91
|
+
backordered_quantity = get_backordered_quantity(available_quantity, new_on_hand_quantity)
|
92
|
+
|
93
|
+
# Determine how many backordered and on_hand items we'll need to move. We
|
94
|
+
# don't want to move more than what's being asked. And we can't move a
|
95
|
+
# negative amount, which is why we need to perform our min/max logic here.
|
96
|
+
backordered_quantity_to_move = [backordered_quantity, quantity].min
|
97
|
+
on_hand_quantity_to_move = [quantity - backordered_quantity_to_move, 0].max
|
93
98
|
|
94
99
|
ActiveRecord::Base.transaction do
|
95
100
|
if handle_stock_counts?
|
96
101
|
# We only run this query if we need it.
|
97
102
|
current_on_hand_quantity = [current_shipment.inventory_units.pre_shipment.size, quantity].min
|
103
|
+
unstock_quantity = desired_shipment.stock_location.backorderable?(variant) ? quantity : new_on_hand_quantity
|
98
104
|
|
99
105
|
# Restock things we will not fulfil from the current shipment anymore
|
100
106
|
current_stock_location.restock(variant, current_on_hand_quantity, current_shipment)
|
@@ -105,19 +111,21 @@ module Spree
|
|
105
111
|
# These two statements are the heart of this class. We change the number
|
106
112
|
# of inventory units requested from one shipment to the other.
|
107
113
|
# We order by state, because `'backordered' < 'on_hand'`.
|
114
|
+
# We start to move the new actual backordered quantity, so the remaining
|
115
|
+
# quantity can be set to on_hand state.
|
108
116
|
current_shipment.
|
109
117
|
inventory_units.
|
110
118
|
where(variant:).
|
111
119
|
order(state: :asc).
|
112
|
-
limit(
|
113
|
-
update_all(shipment_id: desired_shipment.id, state: :
|
120
|
+
limit(backordered_quantity_to_move).
|
121
|
+
update_all(shipment_id: desired_shipment.id, state: :backordered)
|
114
122
|
|
115
123
|
current_shipment.
|
116
124
|
inventory_units.
|
117
125
|
where(variant:).
|
118
126
|
order(state: :asc).
|
119
|
-
limit(
|
120
|
-
update_all(shipment_id: desired_shipment.id, state: :
|
127
|
+
limit(on_hand_quantity_to_move).
|
128
|
+
update_all(shipment_id: desired_shipment.id, state: :on_hand)
|
121
129
|
end
|
122
130
|
end
|
123
131
|
|
@@ -141,11 +149,22 @@ module Spree
|
|
141
149
|
current_shipment.order.completed? && current_stock_location != desired_stock_location
|
142
150
|
end
|
143
151
|
|
144
|
-
def
|
152
|
+
def get_available_quantity
|
145
153
|
if current_stock_location != desired_stock_location
|
146
|
-
|
154
|
+
desired_location_quantifier.positive_stock
|
147
155
|
else
|
148
|
-
|
156
|
+
sl_availability = current_location_quantifier.positive_stock
|
157
|
+
shipment_availability = current_shipment.inventory_units.where(variant: variant).on_hand.count
|
158
|
+
sl_availability + shipment_availability
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
def get_backordered_quantity(available_quantity, new_on_hand_quantity)
|
163
|
+
if current_stock_location != desired_stock_location
|
164
|
+
quantity - new_on_hand_quantity
|
165
|
+
else
|
166
|
+
shipment_quantity = current_shipment.inventory_units.where(variant: variant).size
|
167
|
+
shipment_quantity - available_quantity
|
149
168
|
end
|
150
169
|
end
|
151
170
|
|
@@ -156,11 +175,19 @@ module Spree
|
|
156
175
|
end
|
157
176
|
|
158
177
|
def enough_stock_at_desired_location
|
159
|
-
unless
|
178
|
+
unless desired_location_quantifier.can_supply?(quantity)
|
160
179
|
errors.add(:desired_shipment, :not_enough_stock_at_desired_location)
|
161
180
|
end
|
162
181
|
end
|
163
182
|
|
183
|
+
def desired_location_quantifier
|
184
|
+
@desired_location_quantifier ||= Spree::Stock::Quantifier.new(variant, desired_stock_location)
|
185
|
+
end
|
186
|
+
|
187
|
+
def current_location_quantifier
|
188
|
+
@current_location_quantifier ||= Spree::Stock::Quantifier.new(variant, current_stock_location)
|
189
|
+
end
|
190
|
+
|
164
191
|
def desired_shipment_different_from_current
|
165
192
|
if desired_shipment.id == current_shipment.id
|
166
193
|
errors.add(:desired_shipment, :can_not_transfer_within_same_shipment)
|
@@ -24,7 +24,7 @@ module Spree
|
|
24
24
|
raise "The order association has been removed from InventoryUnit. The order is now determined from the shipment."
|
25
25
|
end
|
26
26
|
|
27
|
-
|
27
|
+
validates :shipment, :line_item, :variant, presence: true
|
28
28
|
|
29
29
|
before_destroy :ensure_can_destroy
|
30
30
|
|
@@ -18,11 +18,11 @@ module Spree
|
|
18
18
|
|
19
19
|
has_one :product, through: :variant
|
20
20
|
|
21
|
-
has_many :adjustments, as: :adjustable, inverse_of: :adjustable, dependent: :destroy
|
21
|
+
has_many :adjustments, as: :adjustable, inverse_of: :adjustable, dependent: :destroy, autosave: true
|
22
22
|
has_many :inventory_units, inverse_of: :line_item
|
23
23
|
|
24
24
|
before_validation :normalize_quantity
|
25
|
-
|
25
|
+
after_initialize :set_required_attributes
|
26
26
|
|
27
27
|
validates :variant, presence: true
|
28
28
|
validates :quantity, numericality: {
|
@@ -159,6 +159,7 @@ module Spree
|
|
159
159
|
# Sets tax category, price-related attributes from
|
160
160
|
# its variant if they are nil and a variant is present.
|
161
161
|
def set_required_attributes
|
162
|
+
return if persisted?
|
162
163
|
return unless variant
|
163
164
|
self.tax_category ||= variant.tax_category
|
164
165
|
set_pricing_attributes
|
data/app/models/spree/order.rb
CHANGED
@@ -52,7 +52,8 @@ module Spree
|
|
52
52
|
:total_available_store_credit,
|
53
53
|
:item_total_before_tax,
|
54
54
|
:shipment_total_before_tax,
|
55
|
-
:item_total_excluding_vat
|
55
|
+
:item_total_excluding_vat,
|
56
|
+
:promo_total
|
56
57
|
)
|
57
58
|
alias :display_ship_total :display_shipment_total
|
58
59
|
|
@@ -101,7 +102,7 @@ module Spree
|
|
101
102
|
has_many :cartons, -> { distinct }, through: :inventory_units
|
102
103
|
|
103
104
|
# Adjustments and promotions
|
104
|
-
has_many :adjustments, -> { order(:created_at) }, as: :adjustable, inverse_of: :adjustable, dependent: :destroy
|
105
|
+
has_many :adjustments, -> { order(:created_at) }, as: :adjustable, inverse_of: :adjustable, dependent: :destroy, autosave: true
|
105
106
|
has_many :line_item_adjustments, through: :line_items, source: :adjustments
|
106
107
|
has_many :shipment_adjustments, through: :shipments, source: :adjustments
|
107
108
|
has_many :all_adjustments,
|
@@ -844,9 +845,10 @@ module Spree
|
|
844
845
|
cancel_shipments!
|
845
846
|
cancel_payments!
|
846
847
|
|
847
|
-
send_cancel_email
|
848
848
|
update_column(:canceled_at, Time.current)
|
849
849
|
recalculate
|
850
|
+
|
851
|
+
Spree::Bus.publish :order_canceled, order: self
|
850
852
|
end
|
851
853
|
|
852
854
|
def cancel_shipments!
|
@@ -862,10 +864,6 @@ module Spree
|
|
862
864
|
end
|
863
865
|
end
|
864
866
|
|
865
|
-
def send_cancel_email
|
866
|
-
Spree::Config.order_mailer_class.cancel_email(self).deliver_later
|
867
|
-
end
|
868
|
-
|
869
867
|
def after_resume
|
870
868
|
shipments.each(&:resume!)
|
871
869
|
end
|
@@ -9,9 +9,22 @@ class Spree::OrderCancellations
|
|
9
9
|
# #call(unit_cancels)
|
10
10
|
class_attribute :short_ship_tax_notifier
|
11
11
|
|
12
|
-
|
13
|
-
|
14
|
-
|
12
|
+
class << self
|
13
|
+
def send_cancellation_mailer=(value)
|
14
|
+
@send_cancellation_mailer = value
|
15
|
+
|
16
|
+
unless value
|
17
|
+
Spree.deprecator.warn "Using the `:send_cancellation_mailer` class " \
|
18
|
+
"attribute is deprecated in favor of including or omitting the " \
|
19
|
+
"`Spree::OrderInventoryCancellationMailerSubscriber` from " \
|
20
|
+
"`Spree::Config.environment.subscribers` in an initializer."
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def send_cancellation_mailer
|
25
|
+
@send_cancellation_mailer || @send_cancellation_mailer.nil?
|
26
|
+
end
|
27
|
+
end
|
15
28
|
|
16
29
|
def initialize(order)
|
17
30
|
@order = order
|
@@ -38,9 +51,6 @@ class Spree::OrderCancellations
|
|
38
51
|
inventory_units.each do |iu|
|
39
52
|
unit_cancels << short_ship_unit(iu, created_by:)
|
40
53
|
end
|
41
|
-
|
42
|
-
update_shipped_shipments(inventory_units)
|
43
|
-
Spree::Config.order_mailer_class.inventory_cancellation_email(@order, inventory_units.to_a).deliver_later if Spree::OrderCancellations.send_cancellation_mailer
|
44
54
|
end
|
45
55
|
|
46
56
|
@order.recalculate
|
@@ -50,6 +60,7 @@ class Spree::OrderCancellations
|
|
50
60
|
end
|
51
61
|
end
|
52
62
|
|
63
|
+
Spree::Bus.publish(:order_short_shipped, order: @order, inventory_units:)
|
53
64
|
unit_cancels
|
54
65
|
end
|
55
66
|
|
@@ -109,18 +120,4 @@ class Spree::OrderCancellations
|
|
109
120
|
|
110
121
|
unit_cancel
|
111
122
|
end
|
112
|
-
|
113
|
-
# if any shipments are now fully shipped then mark them as such
|
114
|
-
def update_shipped_shipments(inventory_units)
|
115
|
-
shipments = Spree::Shipment.
|
116
|
-
includes(:inventory_units).
|
117
|
-
where(id: inventory_units.map(&:shipment_id)).
|
118
|
-
to_a
|
119
|
-
|
120
|
-
shipments.each do |shipment|
|
121
|
-
if shipment.inventory_units.all? { |iu| iu.shipped? || iu.canceled? }
|
122
|
-
shipment.update!(state: 'shipped', shipped_at: Time.current)
|
123
|
-
end
|
124
|
-
end
|
125
|
-
end
|
126
123
|
end
|