Files
MatchLiveTv/backend/app/helpers/public/billing_helper.rb
Emiliano Frascaro 566104aff4 Billing upgrade/downgrade, inviti in app e diretta YouTube da mobile.
Upgrade Stripe con addebito immediato; downgrade programmato a fine periodo.
UX billing più sobria con box info; icone piani. API inviti e OAuth YouTube
per staff trasmissione; deep link join; scelta partita programmata o nuova.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-02 22:15:27 +02:00

97 lines
3.4 KiB
Ruby

module Public
module BillingHelper
def plan_billing_action(current_slug:, target_plan:, stripe_subscription_active:, current_interval: nil, subscription: nil)
if target_plan.slug == "free"
return { kind: :current, label: "Piano attuale" } if current_slug == "free"
return { kind: :none } if stripe_subscription_active
return { kind: :contact, label: "Per passare al piano Free, contatta il supporto." }
end
unless MatchLiveTv.stripe_enabled?
return { kind: :disabled, label: "Stripe non configurato" }
end
intervals = Billing::Stripe::PriceCatalog.available_intervals(plan_slug: target_plan.slug)
return { kind: :disabled, label: "Prezzi Stripe non configurati" } if intervals.empty?
active_interval = current_interval.presence || Billing::Stripe::PriceCatalog::DEFAULT_INTERVAL
if current_slug == target_plan.slug && stripe_subscription_active && !subscription&.plan_change_pending?
other_intervals = intervals - [active_interval]
if other_intervals.empty?
label = "Piano attuale — #{Billing::Stripe::PriceCatalog.label(plan_slug: target_plan.slug, interval: active_interval)}"
return { kind: :current, label: label }
end
return {
kind: :interval_switch,
plan: target_plan,
intervals: other_intervals,
current_interval: active_interval,
current_slug: current_slug,
subscription: subscription
}
end
if current_slug == "free" || !stripe_subscription_active
{ kind: :checkout_options, plan: target_plan, intervals: intervals, subscription: subscription }
else
{
kind: :change_options,
plan: target_plan,
intervals: intervals,
current_slug: current_slug,
current_interval: active_interval,
subscription: subscription
}
end
end
def plan_interval_checkout_path(club, plan, interval)
public_club_checkout_path(club, plan: plan.slug, interval: interval)
end
def plan_interval_button_label(plan, interval, kind: :checkout, **)
btn_kind = kind == :checkout_options ? :checkout : :change
Billing::Stripe::PlanChangeMessages.button_label(plan: plan, interval: interval, kind: btn_kind)
end
def billing_plan_change_info_lines(subscription: nil)
Billing::Stripe::PlanChangeMessages.billing_info_lines(subscription: subscription)
end
def stripe_subscription_active?(subscription)
subscription&.stripe_subscription_id.present? && subscription.active?
end
def stripe_interval_available?(plan_slug, interval)
Billing::Stripe::PriceCatalog.configured?(plan_slug: plan_slug, interval: interval)
end
def plan_interval_button_class(interval, **)
if interval.to_s == "yearly"
"btn btn-primary plan-interval-btn plan-interval-btn--yearly"
else
"btn btn-outline plan-interval-btn plan-interval-btn--monthly"
end
end
def plan_intervals_for_display(intervals)
Array(intervals).sort_by { |i| i.to_s == "yearly" ? 0 : 1 }
end
def billing_profile_blocks_premium?(club)
club.present? && !club.billing_profile_complete?
end
def billing_profile_incomplete_message(club)
missing = club.billing_profile_errors
return "Completa i dati di fatturazione prima di attivare un piano premium." if missing.empty?
"Mancano: #{missing.join(", ")}."
end
end
end