Rimuove link al portale Stripe in area cliente, aggiunge flusso admin per PDF fattura e email, blocca checkout senza dati di fatturazione, allinea prezzi a €4,90/€39,90 e €9,90/€69,90, locale italiano e documentazione deploy. Co-authored-by: Cursor <cursoragent@cursor.com>
66 lines
1.7 KiB
Ruby
66 lines
1.7 KiB
Ruby
module Billing
|
|
module Stripe
|
|
# Passa a Free se il periodo pagato è scaduto (es. disdetta o webhook mancato in locale).
|
|
class FinalizeSubscription
|
|
def self.call(club:)
|
|
new(club: club).call
|
|
end
|
|
|
|
def initialize(club:)
|
|
@club = club
|
|
end
|
|
|
|
def call
|
|
sub = @club.subscription
|
|
return false unless sub&.stripe_subscription_id.present?
|
|
return false if sub.free?
|
|
|
|
stripe_sub = ::Stripe::Subscription.retrieve(sub.stripe_subscription_id)
|
|
|
|
if stripe_sub.status.in?(%w[canceled incomplete_expired])
|
|
downgrade!(sub)
|
|
return true
|
|
end
|
|
|
|
period_end = period_end_time(sub, stripe_sub)
|
|
return false if period_end.blank? || period_end > Time.current
|
|
|
|
if sub.cancel_at_period_end? || stripe_sub.cancel_at_period_end
|
|
downgrade!(sub)
|
|
return true
|
|
end
|
|
|
|
false
|
|
rescue ::Stripe::InvalidRequestError => e
|
|
downgrade!(sub) if e.message.include?("No such subscription")
|
|
false
|
|
end
|
|
|
|
private
|
|
|
|
def period_end_time(sub, stripe_sub)
|
|
local = sub.current_period_end
|
|
return local if local.present?
|
|
|
|
start_at, end_at = SubscriptionPeriod.times(stripe_sub)
|
|
end_at
|
|
end
|
|
|
|
def downgrade!(sub)
|
|
Billing::AssignPlan.call(
|
|
club: @club,
|
|
plan_slug: "free",
|
|
status: "active",
|
|
stripe_attrs: {
|
|
stripe_subscription_id: nil,
|
|
current_period_start: nil,
|
|
current_period_end: nil,
|
|
cancel_at_period_end: false,
|
|
billing_interval: nil
|
|
}
|
|
)
|
|
end
|
|
end
|
|
end
|
|
end
|