diff --git a/core/app/models/concerns/spree/state_change_tracking.rb b/core/app/models/concerns/spree/state_change_tracking.rb index 0ce2dcf7a0..ac2b37b84e 100644 --- a/core/app/models/concerns/spree/state_change_tracking.rb +++ b/core/app/models/concerns/spree/state_change_tracking.rb @@ -19,11 +19,11 @@ def enqueue_state_change_tracking previous_state, current_state = saved_changes['state'] # Enqueue the job to track this state change - StateChangeTrackingJob.perform_later( - self, - previous_state, - current_state, - Time.current + Spree::Config.state_change_tracking_class.call( + stateful: self, + previous_state:, + current_state:, + transition_timestamp: Time.current ) end end diff --git a/core/app/models/spree/state_change_tracker.rb b/core/app/models/spree/state_change_tracker.rb new file mode 100644 index 0000000000..8baec40fb7 --- /dev/null +++ b/core/app/models/spree/state_change_tracker.rb @@ -0,0 +1,31 @@ +# frozen_string_literal: true + +module Spree + # Configurable class to enqueue state change tracking jobs + # Configure your custom logic by setting Spree::Config.state_change_tracking_class + # @example Spree::Config.state_change_tracking_class = MyCustomTracker + class StateChangeTracker + # @param stateful [Object] The stateful object to track changes for + # @param previous_state [String] The previous state of the order + # @param current_state [String] The current state of the order + # @param transition_timestamp [Time] When the state transition occurred + # @param stateful_name [String] The element name of the state transition being + # tracked. It defaults to the `stateful` model element name. + def self.call( + stateful:, + previous_state:, + current_state:, + transition_timestamp:, + stateful_name: stateful.class.model_name.element + ) + # Enqueue a background job to track this state change + StateChangeTrackingJob.perform_later( + stateful, + previous_state, + current_state, + transition_timestamp, + stateful_name + ) + end + end +end diff --git a/core/lib/spree/app_configuration.rb b/core/lib/spree/app_configuration.rb index 13b1492548..b10c4c82c4 100644 --- a/core/lib/spree/app_configuration.rb +++ b/core/lib/spree/app_configuration.rb @@ -549,6 +549,13 @@ def payment_canceller product: '680x680>', large: '1200x1200>' } + # Allows to provide your own class for tracking state changes of stateful models + # + # @!attribute [rw] state_change_tracking_class + # @return [Class] a class with the same public interfaces as + # Spree::StateChangeTracker. + class_name_attribute :state_change_tracking_class, default: "Spree::StateChangeTracker" + # Allows providing your own class for prioritizing store credit application # to an order. # diff --git a/core/spec/lib/spree/app_configuration_spec.rb b/core/spec/lib/spree/app_configuration_spec.rb index 67f5220773..64d37c4b13 100644 --- a/core/spec/lib/spree/app_configuration_spec.rb +++ b/core/spec/lib/spree/app_configuration_spec.rb @@ -44,6 +44,10 @@ expect(prefs.variant_price_selector_class).to eq Spree::Variant::PriceSelector end + it "uses state change tracker class by default" do + expect(prefs.state_change_tracking_class).to eq Spree::StateChangeTracker + end + it "uses core's promotion configuration class by default" do expect(prefs.promotions).to be_a Spree::Core::NullPromotionConfiguration end diff --git a/core/spec/models/spree/order_spec.rb b/core/spec/models/spree/order_spec.rb index 539d0d1edd..d75898785c 100644 --- a/core/spec/models/spree/order_spec.rb +++ b/core/spec/models/spree/order_spec.rb @@ -2181,7 +2181,8 @@ def validate(line_item) order, 'cart', 'address', - kind_of(Time) + kind_of(Time), + 'order' ) end @@ -2201,7 +2202,8 @@ def validate(line_item) order, 'cart', 'address', - kind_of(Time) + kind_of(Time), + 'order' ) end end diff --git a/core/spec/models/spree/payment_spec.rb b/core/spec/models/spree/payment_spec.rb index a6ed9c8c20..2715c15651 100644 --- a/core/spec/models/spree/payment_spec.rb +++ b/core/spec/models/spree/payment_spec.rb @@ -1350,7 +1350,8 @@ payment, 'checkout', 'completed', - kind_of(Time) + kind_of(Time), + 'payment' ) end diff --git a/core/spec/models/spree/shipment_spec.rb b/core/spec/models/spree/shipment_spec.rb index 5ab22be47c..485a73e4c2 100644 --- a/core/spec/models/spree/shipment_spec.rb +++ b/core/spec/models/spree/shipment_spec.rb @@ -974,7 +974,8 @@ shipment, 'pending', 'shipped', - kind_of(Time) + kind_of(Time), + 'shipment' ) end diff --git a/core/spec/models/spree/state_change_tracker_spec.rb b/core/spec/models/spree/state_change_tracker_spec.rb new file mode 100644 index 0000000000..246b3e3a71 --- /dev/null +++ b/core/spec/models/spree/state_change_tracker_spec.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +require "rails_helper" + +RSpec.describe Spree::StateChangeTracker, type: :model do + let(:order) { create(:order) } + let(:transition_timestamp) { Time.current } + + describe "#call" do + it "enqueues a StateChangeTrackingJob with correct arguments" do + expect { + described_class.call( + stateful: order, + previous_state: "cart", + current_state: "address", + transition_timestamp: transition_timestamp, + stateful_name: "order" + ) + }.to have_enqueued_job(Spree::StateChangeTrackingJob).with( + order, + "cart", + "address", + transition_timestamp, + "order" + ) + end + end +end