module Billing module Stripe # Allinea piano locale quando scatta un downgrade programmato (o dopo sync Stripe). class ApplyPendingPlan def self.call(club:) new(club: club).call end def initialize(club:) @club = club @sub = club.subscription end def call return false unless @sub&.pending_plan_id.present? pending_slug = @sub.pending_plan.slug interval = @sub.pending_billing_interval.presence || @sub.billing_interval if @sub.stripe_subscription_id.present? stripe_sub = ::Stripe::Subscription.retrieve(@sub.stripe_subscription_id) current_price_id = stripe_sub.items.data.first.price.id expected_price_id = PriceCatalog.price_id(plan_slug: pending_slug, interval: interval) return false unless current_price_id == expected_price_id inferred = PriceCatalog.infer_from_price_id(current_price_id) if inferred pending_slug, interval = inferred end period_start, period_end = SubscriptionPeriod.times(stripe_sub) Billing::AssignPlan.call( club: @club, plan_slug: pending_slug, status: map_status(stripe_sub.status), stripe_attrs: { stripe_customer_id: stripe_sub.customer, stripe_subscription_id: stripe_sub.id, current_period_start: period_start, current_period_end: period_end, cancel_at_period_end: stripe_sub.cancel_at_period_end, billing_interval: interval, pending_plan_id: nil, pending_billing_interval: nil, stripe_schedule_id: nil } ) else Billing::AssignPlan.call( club: @club, plan_slug: pending_slug, stripe_attrs: { billing_interval: interval, pending_plan_id: nil, pending_billing_interval: nil, stripe_schedule_id: nil } ) end true end private def map_status(stripe_status) case stripe_status when "trialing" then "trialing" when "active" then "active" when "past_due", "unpaid" then "past_due" when "canceled", "incomplete_expired" then "canceled" else "incomplete" end end end end end