Class: Pay::LemonSqueezy::Subscription
- Inherits:
-
Subscription
- Object
- Subscription
- Pay::LemonSqueezy::Subscription
- Extended by:
- Sync
- Defined in:
- app/models/pay/lemon_squeezy/subscription.rb
Constant Summary collapse
- STATUSES =
Lemon Squeezy statuses that Pay spells differently
{"on_trial" => "trialing", "cancelled" => "canceled"}.freeze
Class Method Summary collapse
Instance Method Summary collapse
- #api_record(**options) ⇒ Object
- #cancel(**options) ⇒ Object
- #cancel_now!(**options) ⇒ Object
- #change_quantity(quantity, **options) ⇒ Object
- #pause(**options) ⇒ Object
- #paused? ⇒ Boolean
- #portal_url ⇒ Object
- #resumable? ⇒ Boolean
- #resume ⇒ Object
-
#swap(plan, **options) ⇒ Object
Lemon Squeezy requires both the Product ID and Variant ID.
- #update_url ⇒ Object
Methods included from Sync
find_pay_customer, pay_processor, sync_with_retries
Class Method Details
.sync(subscription_id, object: nil, name: Pay.default_product_name) ⇒ Object
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
# File 'app/models/pay/lemon_squeezy/subscription.rb', line 9 def self.sync(subscription_id, object: nil, name: Pay.default_product_name) sync_with_retries do subscription = object || ::LemonSqueezy::Subscription.retrieve(id: subscription_id) return unless (pay_customer = find_pay_customer(subscription.customer_id)) attributes = { current_period_end: subscription.renews_at, ends_at: (subscription.ends_at ? Time.parse(subscription.ends_at) : nil), pause_resumes_at: (subscription.pause&.resumes_at ? Time.parse(subscription.pause.resumes_at) : nil), status: STATUSES.fetch(subscription.status, subscription.status), processor_plan: subscription.first_subscription_item.price_id, quantity: subscription.first_subscription_item.quantity, created_at: (subscription.created_at ? Time.parse(subscription.created_at) : nil), updated_at: (subscription.updated_at ? Time.parse(subscription.updated_at) : nil) } case attributes[:status] when "canceled" # Remove payment methods since customer cannot be reused after cancelling pay_customer.payment_methods.destroy_all when "trialing" attributes[:trial_ends_at] = Time.parse(subscription.trial_ends_at) when "active", "past_due" attributes[:trial_ends_at] = nil attributes[:pause_resumes_at] = nil attributes[:ends_at] = nil end # Update or create the subscription if (pay_subscription = find_by(customer: pay_customer, processor_id: subscription.id)) pay_subscription.with_lock { pay_subscription.update!(attributes) } pay_subscription else create!(attributes.merge(customer: pay_customer, name: name, processor_id: subscription.id)) end end end |
Instance Method Details
#api_record(**options) ⇒ Object
47 48 49 50 51 |
# File 'app/models/pay/lemon_squeezy/subscription.rb', line 47 def api_record(**) @api_record ||= ::LemonSqueezy::Subscription.retrieve(id: processor_id) rescue ::LemonSqueezy::Error => e raise Pay::LemonSqueezy::Error, e end |
#cancel(**options) ⇒ Object
61 62 63 64 65 66 67 |
# File 'app/models/pay/lemon_squeezy/subscription.rb', line 61 def cancel(**) return if canceled? response = ::LemonSqueezy::Subscription.cancel(id: processor_id) update(status: response.status, ends_at: response.ends_at) rescue ::LemonSqueezy::Error => e raise Pay::LemonSqueezy::Error, e end |
#cancel_now!(**options) ⇒ Object
69 70 71 |
# File 'app/models/pay/lemon_squeezy/subscription.rb', line 69 def cancel_now!(**) raise Pay::NotSupportedError, "Lemon Squeezy does not support cancelling immediately through the API" end |
#change_quantity(quantity, **options) ⇒ Object
73 74 75 76 77 78 79 |
# File 'app/models/pay/lemon_squeezy/subscription.rb', line 73 def change_quantity(quantity, **) subscription_item = api_record.first_subscription_item ::LemonSqueezy::SubscriptionItem.update(id: subscription_item.id, quantity: quantity) update(quantity: quantity) rescue ::LemonSqueezy::Error => e raise Pay::LemonSqueezy::Error, e end |
#pause(**options) ⇒ Object
85 86 87 88 89 90 |
# File 'app/models/pay/lemon_squeezy/subscription.rb', line 85 def pause(**) response = ::LemonSqueezy::Subscription.pause(id: processor_id, **) update!(status: :paused, pause_resumes_at: response.pause&.resumes_at) rescue ::LemonSqueezy::Error => e raise Pay::LemonSqueezy::Error, e end |
#paused? ⇒ Boolean
81 82 83 |
# File 'app/models/pay/lemon_squeezy/subscription.rb', line 81 def paused? status == "paused" end |
#portal_url ⇒ Object
53 54 55 |
# File 'app/models/pay/lemon_squeezy/subscription.rb', line 53 def portal_url api_record.urls.customer_portal end |
#resumable? ⇒ Boolean
92 93 94 |
# File 'app/models/pay/lemon_squeezy/subscription.rb', line 92 def resumable? paused? || canceled? end |
#resume ⇒ Object
96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
# File 'app/models/pay/lemon_squeezy/subscription.rb', line 96 def resume unless resumable? raise Error, "You can only resume paused or cancelled subscriptions" end if paused? ::LemonSqueezy::Subscription.unpause(id: processor_id) else ::LemonSqueezy::Subscription.uncancel(id: processor_id) end update(ends_at: nil, status: :active, pause_resumes_at: nil) rescue ::LemonSqueezy::Error => e raise Pay::LemonSqueezy::Error, e end |
#swap(plan, **options) ⇒ Object
Lemon Squeezy requires both the Product ID and Variant ID. The Variant ID will be saved as the processor_plan
114 115 116 117 118 119 120 121 |
# File 'app/models/pay/lemon_squeezy/subscription.rb', line 114 def swap(plan, **) raise Error, "A plan_id is required to swap a subscription" unless plan raise Error, "A variant_id is required to swap a subscription" unless [:variant_id] ::LemonSqueezy::Subscription.change_plan id: processor_id, plan_id: plan, variant_id: [:variant_id] update(processor_plan: [:variant_id], ends_at: nil, status: :active) end |
#update_url ⇒ Object
57 58 59 |
# File 'app/models/pay/lemon_squeezy/subscription.rb', line 57 def update_url api_record.urls.update_payment_method end |