Class: Pay::Subscription
- Inherits:
-
ApplicationRecord
- Object
- ApplicationRecord
- Pay::Subscription
- Defined in:
- app/models/pay/subscription.rb
Constant Summary collapse
- STATUSES =
%w[incomplete incomplete_expired trialing active past_due canceled unpaid paused]
Class Method Summary collapse
Instance Method Summary collapse
-
#active? ⇒ Boolean
If you cancel during a trial, you should still retain access until the end of the trial Otherwise a subscription is active unless it has ended or is currently paused Check the subscription status so we don’t accidentally consider “incomplete”, “unpaid”, or other statuses as active.
- #canceled? ⇒ Boolean
- #cancelled? ⇒ Boolean
- #change_quantity(quantity, **options) ⇒ Object
- #ended? ⇒ Boolean
- #generic_trial? ⇒ Boolean
- #has_incomplete_payment? ⇒ Boolean
- #has_trial? ⇒ Boolean
- #incomplete? ⇒ Boolean
- #latest_payment ⇒ Object
- #no_prorate ⇒ Object
-
#on_trial? ⇒ Boolean
Does not include the last second of the trial.
- #past_due? ⇒ Boolean
- #payment_processor ⇒ Object
- #processor_subscription(**options) ⇒ Object
- #resume ⇒ Object
- #skip_trial ⇒ Object
- #swap(plan, **options) ⇒ Object
- #swap_and_invoice(plan) ⇒ Object
- #sync!(**options) ⇒ Object
- #trial_ended? ⇒ Boolean
- #unpaid? ⇒ Boolean
Class Method Details
.find_by_processor_and_id(processor, processor_id) ⇒ Object
[View source]
54 55 56 |
# File 'app/models/pay/subscription.rb', line 54 def self.find_by_processor_and_id(processor, processor_id) joins(:customer).find_by(processor_id: processor_id, pay_customers: {processor: processor}) end |
.pay_processor_for(name) ⇒ Object
[View source]
58 59 60 |
# File 'app/models/pay/subscription.rb', line 58 def self.pay_processor_for(name) "Pay::#{name.to_s.classify}::Subscription".constantize end |
Instance Method Details
#active? ⇒ Boolean
If you cancel during a trial, you should still retain access until the end of the trial Otherwise a subscription is active unless it has ended or is currently paused Check the subscription status so we don’t accidentally consider “incomplete”, “unpaid”, or other statuses as active
111 112 113 114 |
# File 'app/models/pay/subscription.rb', line 111 def active? ["trialing", "active"].include?(status) && (!(canceled? || paused?) || on_trial? || on_grace_period?) end |
#canceled? ⇒ Boolean
96 97 98 |
# File 'app/models/pay/subscription.rb', line 96 def canceled? ends_at? end |
#cancelled? ⇒ Boolean
100 101 102 |
# File 'app/models/pay/subscription.rb', line 100 def cancelled? canceled? end |
#change_quantity(quantity, **options) ⇒ Object
[View source]
132 133 134 135 |
# File 'app/models/pay/subscription.rb', line 132 def change_quantity(quantity, **) payment_processor.change_quantity(quantity, **) update(quantity: quantity) end |
#ended? ⇒ Boolean
104 105 106 |
# File 'app/models/pay/subscription.rb', line 104 def ended? ends_at? && ends_at <= Time.current end |
#generic_trial? ⇒ Boolean
79 80 81 |
# File 'app/models/pay/subscription.rb', line 79 def generic_trial? fake_processor? && trial_ends_at? end |
#has_incomplete_payment? ⇒ Boolean
128 129 130 |
# File 'app/models/pay/subscription.rb', line 128 def has_incomplete_payment? past_due? || incomplete? end |
#has_trial? ⇒ Boolean
83 84 85 |
# File 'app/models/pay/subscription.rb', line 83 def has_trial? trial_ends_at? end |
#incomplete? ⇒ Boolean
124 125 126 |
# File 'app/models/pay/subscription.rb', line 124 def incomplete? status == "incomplete" end |
#latest_payment ⇒ Object
[View source]
157 158 159 |
# File 'app/models/pay/subscription.rb', line 157 def latest_payment processor_subscription(expand: ["latest_invoice.payment_intent"]).latest_invoice.payment_intent end |
#no_prorate ⇒ Object
[View source]
71 72 73 |
# File 'app/models/pay/subscription.rb', line 71 def no_prorate self.prorate = false end |
#on_trial? ⇒ Boolean
Does not include the last second of the trial
88 89 90 |
# File 'app/models/pay/subscription.rb', line 88 def on_trial? trial_ends_at? && trial_ends_at > Time.current end |
#past_due? ⇒ Boolean
116 117 118 |
# File 'app/models/pay/subscription.rb', line 116 def past_due? status == "past_due" end |
#payment_processor ⇒ Object
[View source]
62 63 64 |
# File 'app/models/pay/subscription.rb', line 62 def payment_processor @payment_processor ||= self.class.pay_processor_for(customer.processor).new(self) end |
#processor_subscription(**options) ⇒ Object
[View source]
153 154 155 |
# File 'app/models/pay/subscription.rb', line 153 def processor_subscription(**) payment_processor.subscription(**) end |
#resume ⇒ Object
[View source]
137 138 139 140 141 |
# File 'app/models/pay/subscription.rb', line 137 def resume payment_processor.resume update(ends_at: nil, status: :active) self end |
#skip_trial ⇒ Object
[View source]
75 76 77 |
# File 'app/models/pay/subscription.rb', line 75 def skip_trial self.trial_ends_at = nil end |
#swap(plan, **options) ⇒ Object
143 144 145 146 |
# File 'app/models/pay/subscription.rb', line 143 def swap(plan, **) raise ArgumentError, "plan must be a string. Got `#{plan.inspect}` instead." unless plan.is_a?(String) payment_processor.swap(plan, **) end |
#swap_and_invoice(plan) ⇒ Object
[View source]
148 149 150 151 |
# File 'app/models/pay/subscription.rb', line 148 def swap_and_invoice(plan) swap(plan) customer.invoice!(subscription: processor_id) end |
#sync!(**options) ⇒ Object
[View source]
66 67 68 69 |
# File 'app/models/pay/subscription.rb', line 66 def sync!(**) self.class.pay_processor_for(customer.processor).sync(processor_id, **) reload end |
#trial_ended? ⇒ Boolean
92 93 94 |
# File 'app/models/pay/subscription.rb', line 92 def trial_ended? trial_ends_at? && trial_ends_at <= Time.current end |
#unpaid? ⇒ Boolean
120 121 122 |
# File 'app/models/pay/subscription.rb', line 120 def unpaid? status == "unpaid" end |