Class: CoreMerchant::Subscription
- Inherits:
-
ActiveRecord::Base
- Object
- ActiveRecord::Base
- CoreMerchant::Subscription
- Includes:
- Concerns::SubscriptionEventAssociation, Concerns::SubscriptionNotifications, Concerns::SubscriptionStateMachine
- Defined in:
- lib/core_merchant/subscription.rb
Overview
Represents a subscription in CoreMerchant. This class manages the lifecycle of a customer’s subscription to a specific plan.
**Subscriptions can transition through various statuses**:
-
pending: Subscription created but not yet started -
trial: In a trial period -
active: Currently active and paid -
past_due: Payment failed but in grace period -
pending_cancellation: Will be canceled at period end -
processing_renewal: Renewal in progress -
processing_payment: Payment processing -
canceled: Canceled by user or due to payment failure -
expired: Subscription period ended -
paused: Temporarily halted, not yet implemented -
pending_change: Plan change scheduled for next renewal, not yet implemented
**Key features**:
-
Supports immediate and end-of-period cancellations
-
Allows plan changes, effective immediately or at next renewal
-
Handles subscription pausing and resuming
-
Manages trial periods
-
Supports variable pricing for renewals
Attributes:
-
customer: Polymorphic association to the customer -
subscription_plan: The current plan for this subscription -
status: Current status of the subscription (see enum definition) -
start_date: When the subscription started -
end_date: When the subscription ended (or will end) -
trial_end_date: End date of the trial period (if applicable) -
canceled_at: When the subscription was canceled -
current_period_start: Start of the current billing period -
current_period_end: End of the current billing period -
pause_start_date: When the subscription was paused -
pause_end_date: When the paused subscription will resume -
current_period_price_cents: Price for the current period -
next_renewal_price_cents: Price for the next renewal (if different from plan) -
cancellation_reason: Reason for cancellation (if applicable)
Usage:
```ruby
subscription = CoreMerchant::Subscription.create(customer: user, subscription_plan: plan, status: :active)
subscription.start
subscription.cancel(reason: "Too expensive", at_period_end: true)
```
Constant Summary
Constants included from Concerns::SubscriptionEventAssociation
Concerns::SubscriptionEventAssociation::EVENT_TYPES
Constants included from Concerns::SubscriptionStateMachine
Concerns::SubscriptionStateMachine::POSSIBLE_TRANSITIONS
Instance Method Summary collapse
-
#cancel(reason:, at_period_end: true) ⇒ Object
Cancels the subscription.
-
#days_remaining_in_current_period ⇒ Object
Returns the days remaining in the current period.
- #days_remaining_in_grace_period ⇒ Object
- #due_for_renewal? ⇒ Boolean
- #expired_or_canceled? ⇒ Boolean
-
#grace_period ⇒ Object
Returns the number of days as a grace period for past-due subscriptions.
- #grace_period_end_date ⇒ Object
- #grace_period_exceeded? ⇒ Boolean
- #in_grace_period? ⇒ Boolean
- #ongoing? ⇒ Boolean
- #processing? ⇒ Boolean
- #renewable? ⇒ Boolean
-
#start ⇒ Object
Starts the subscription.
-
#start_new_period ⇒ Object
Starts a new period for the subscription.
Instance Method Details
#cancel(reason:, at_period_end: true) ⇒ Object
Cancels the subscription. Parameters:
-
reason: Reason for cancellation -
at_period_end: If true, the subscription will be canceled at the end of the current period. Otherwise, the subscription will be canceled immediately. Default istrue.
101 102 103 |
# File 'lib/core_merchant/subscription.rb', line 101 def cancel(reason:, at_period_end: true) CoreMerchant.subscription_manager.cancel_subscription(self, reason: reason, at_period_end: at_period_end) end |
#days_remaining_in_current_period ⇒ Object
Returns the days remaining in the current period. Use to show the user how many days are left before the next renewal or to refund pro-rated amounts for early cancellations.
120 121 122 |
# File 'lib/core_merchant/subscription.rb', line 120 def days_remaining_in_current_period (current_period_end.to_date - Time.current.to_date).to_i end |
#days_remaining_in_grace_period ⇒ Object
138 139 140 141 142 |
# File 'lib/core_merchant/subscription.rb', line 138 def days_remaining_in_grace_period return 0 unless due_for_renewal? (grace_period_end_date.to_date - Time.current.to_date).to_i end |
#due_for_renewal? ⇒ Boolean
148 149 150 |
# File 'lib/core_merchant/subscription.rb', line 148 def due_for_renewal? renewable? && current_period_end <= Time.current end |
#expired_or_canceled? ⇒ Boolean
152 153 154 |
# File 'lib/core_merchant/subscription.rb', line 152 def expired_or_canceled? expired? || canceled? end |
#grace_period ⇒ Object
Returns the number of days as a grace period for past-due subscriptions. By default, this is 3 days.
126 127 128 |
# File 'lib/core_merchant/subscription.rb', line 126 def grace_period 3.days end |
#grace_period_end_date ⇒ Object
130 131 132 |
# File 'lib/core_merchant/subscription.rb', line 130 def grace_period_end_date current_period_end + grace_period end |
#grace_period_exceeded? ⇒ Boolean
144 145 146 |
# File 'lib/core_merchant/subscription.rb', line 144 def grace_period_exceeded? due_for_renewal? && Time.current > grace_period_end_date end |
#in_grace_period? ⇒ Boolean
134 135 136 |
# File 'lib/core_merchant/subscription.rb', line 134 def in_grace_period? due_for_renewal? && Time.current <= grace_period_end_date end |
#ongoing? ⇒ Boolean
160 161 162 |
# File 'lib/core_merchant/subscription.rb', line 160 def ongoing? active? || trial? || past_due? || processing_renewal? || processing_payment? || pending_cancellation? end |
#processing? ⇒ Boolean
156 157 158 |
# File 'lib/core_merchant/subscription.rb', line 156 def processing? processing_renewal? || processing_payment? end |
#renewable? ⇒ Boolean
164 165 166 |
# File 'lib/core_merchant/subscription.rb', line 164 def renewable? active? || trial? || past_due? || processing? end |
#start ⇒ Object
Starts the subscription. Sets the current period start and end dates based on the plan’s duration.
91 92 93 |
# File 'lib/core_merchant/subscription.rb', line 91 def start CoreMerchant.subscription_manager.start_subscription(self) end |
#start_new_period ⇒ Object
Starts a new period for the subscription. This is called by SubscriptionManager when a subscription renewal is successful.
107 108 109 110 111 112 113 114 115 |
# File 'lib/core_merchant/subscription.rb', line 107 def start_new_period new_period_start = current_period_end || start_date new_period_end = new_period_start + subscription_plan.duration_in_date update!( current_period_start: new_period_start.to_date, current_period_end: new_period_end.to_date ) end |