Class: SolidusSubscriptions::Subscription
- Inherits:
-
ApplicationRecord
- Object
- ApplicationRecord
- SolidusSubscriptions::Subscription
- Includes:
- Interval
- Defined in:
- app/models/solidus_subscriptions/subscription.rb
Constant Summary collapse
- PROCESSING_STATES =
[:pending, :failed, :success].freeze
Class Method Summary collapse
Instance Method Summary collapse
- #actionable? ⇒ Boolean
-
#advance_actionable_date ⇒ Date
Advance the actionable date to the next_actionable_date value.
- #billing_address_to_use ⇒ Object
-
#can_be_canceled? ⇒ Boolean
This method determines if a subscription may be canceled.
-
#can_be_deactivated? ⇒ Boolean
This method determines if a subscription can be deactivated.
- #failing_since ⇒ Object
- #maximum_reprocessing_time_reached? ⇒ Boolean
-
#next_actionable_date ⇒ Date
Get the date after the current actionable_date where this subscription will be actionable again.
- #pause(actionable_date: nil) ⇒ Object
- #payment_method_to_use ⇒ Object
- #payment_source_to_use ⇒ Object
-
#processing_state ⇒ String
The state of the last attempt to process an installment associated to this subscription.
- #resume(actionable_date: nil) ⇒ Object
- #shipping_address_to_use ⇒ Object
- #skip(check_skip_limits: true) ⇒ Object
- #state_with_pause ⇒ Object
Methods included from Interval
Class Method Details
.processing_states ⇒ Object
95 96 97 |
# File 'app/models/solidus_subscriptions/subscription.rb', line 95 def self.processing_states PROCESSING_STATES end |
.ransackable_scopes(_auth_object = nil) ⇒ Object
91 92 93 |
# File 'app/models/solidus_subscriptions/subscription.rb', line 91 def self.ransackable_scopes(_auth_object = nil) [:in_processing_state, :with_subscribable] end |
Instance Method Details
#actionable? ⇒ Boolean
305 306 307 |
# File 'app/models/solidus_subscriptions/subscription.rb', line 305 def actionable? actionable_date && actionable_date <= Time.zone.today && ["canceled", "inactive"].exclude?(state) end |
#advance_actionable_date ⇒ Date
Advance the actionable date to the next_actionable_date value. Will modify the record.
subscription will be eligible to be processed.
215 216 217 218 219 220 221 |
# File 'app/models/solidus_subscriptions/subscription.rb', line 215 def advance_actionable_date create_and_emit_event(type: 'subscription_resumed') if paused? update! actionable_date: next_actionable_date, paused: false actionable_date end |
#billing_address_to_use ⇒ Object
275 276 277 |
# File 'app/models/solidus_subscriptions/subscription.rb', line 275 def billing_address_to_use billing_address || user.bill_address end |
#can_be_canceled? ⇒ Boolean
This method determines if a subscription may be canceled. Canceled subcriptions will not be processed. By default subscriptions may always be canceled. If this method is overridden to return false, the subscription will be moved to the :pending_cancellation state until it is canceled again and this condition is true.
USE CASE: Subscriptions can only be canceled more than 10 days before they are processed. Override this method to be:
def can_be_canceled?
return true if actionable_date.nil?
(actionable_date - 10.days.from_now.to_date) > 0
end
If a user cancels this subscription less than 10 days before it will be processed the subscription will be bumped into the :pending_cancellation state instead of being canceled. Subscriptions pending cancellation will still be processed.
159 160 161 162 163 164 |
# File 'app/models/solidus_subscriptions/subscription.rb', line 159 def can_be_canceled? return true if actionable_date.nil? cancel_by = actionable_date - SolidusSubscriptions.configuration.minimum_cancellation_notice cancel_by.future? || cancel_by.today? end |
#can_be_deactivated? ⇒ Boolean
This method determines if a subscription can be deactivated. A deactivated subscription will not be processed. By default a subscription can be deactivated if the end_date defined on the subscription is less than the current date In this case the subscription has been fulfilled and should not be processed again. Subscriptions without an end_date value cannot be deactivated.
192 193 194 |
# File 'app/models/solidus_subscriptions/subscription.rb', line 192 def can_be_deactivated? active? && end_date && actionable_date && actionable_date > end_date end |
#failing_since ⇒ Object
279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 |
# File 'app/models/solidus_subscriptions/subscription.rb', line 279 def failing_since failing_details = installment_details.failed.order('solidus_subscriptions_installment_details.created_at ASC') last_successful_detail = installment_details .succeeded .order('solidus_subscriptions_installment_details.created_at DESC') .first if last_successful_detail failing_details = failing_details.where( 'solidus_subscriptions_installment_details.created_at > ?', last_successful_detail.created_at, ) end first_failing_detail = failing_details.first first_failing_detail&.created_at end |
#maximum_reprocessing_time_reached? ⇒ Boolean
298 299 300 301 302 303 |
# File 'app/models/solidus_subscriptions/subscription.rb', line 298 def maximum_reprocessing_time_reached? return false unless SolidusSubscriptions.configuration.maximum_reprocessing_time return false unless failing_since Time.zone.now > (failing_since + SolidusSubscriptions.configuration.maximum_reprocessing_time) end |
#next_actionable_date ⇒ Date
Get the date after the current actionable_date where this subscription will be actionable again
202 203 204 205 206 207 208 |
# File 'app/models/solidus_subscriptions/subscription.rb', line 202 def next_actionable_date return nil unless active? new_date = actionable_date || Time.zone.today new_date + interval end |
#pause(actionable_date: nil) ⇒ Object
223 224 225 226 227 228 229 230 231 |
# File 'app/models/solidus_subscriptions/subscription.rb', line 223 def pause(actionable_date: nil) check_invalid_pause_states return false if errors.any? return true if paused? result = update! paused: true, actionable_date: actionable_date && tomorrow_or_after(actionable_date) create_and_emit_event(type: 'subscription_paused') if result result end |
#payment_method_to_use ⇒ Object
259 260 261 |
# File 'app/models/solidus_subscriptions/subscription.rb', line 259 def payment_method_to_use payment_method || user.wallet.default_wallet_payment_source&.payment_source&.payment_method end |
#payment_source_to_use ⇒ Object
263 264 265 266 267 268 269 |
# File 'app/models/solidus_subscriptions/subscription.rb', line 263 def payment_source_to_use if payment_method payment_source else user.wallet.default_wallet_payment_source&.payment_source end end |
#processing_state ⇒ String
The state of the last attempt to process an installment associated to this subscription
253 254 255 256 257 |
# File 'app/models/solidus_subscriptions/subscription.rb', line 253 def processing_state return 'pending' if installments.empty? installments.last.fulfilled? ? 'success' : 'failed' end |
#resume(actionable_date: nil) ⇒ Object
233 234 235 236 237 238 239 240 241 |
# File 'app/models/solidus_subscriptions/subscription.rb', line 233 def resume(actionable_date: nil) check_invalid_resume_states return false if errors.any? return true unless paused? result = update! paused: false, actionable_date: tomorrow_or_after(actionable_date) create_and_emit_event(type: 'subscription_resumed') if result result end |
#shipping_address_to_use ⇒ Object
271 272 273 |
# File 'app/models/solidus_subscriptions/subscription.rb', line 271 def shipping_address_to_use shipping_address || user.ship_address end |
#skip(check_skip_limits: true) ⇒ Object
166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 |
# File 'app/models/solidus_subscriptions/subscription.rb', line 166 def skip(check_skip_limits: true) check_invalid_skip_states if check_skip_limits check_successive_skips_exceeded check_total_skips_exceeded end return if errors.any? increment(:skip_count) increment(:successive_skip_count) save! advance_actionable_date.tap do create_and_emit_event(type: 'subscription_skipped') end end |
#state_with_pause ⇒ Object
243 244 245 |
# File 'app/models/solidus_subscriptions/subscription.rb', line 243 def state_with_pause active? && paused? ? 'paused' : state end |