module Public module BillingHelper def plan_billing_action(current_slug:, target_plan:, stripe_subscription_active:, current_interval: nil, subscription: nil, club: nil) if target_plan.slug == "free" return { kind: :current, label: I18n.t("billing.actions.current_plan") } if current_slug == "free" return { kind: :none } if stripe_subscription_active return { kind: :contact, label: I18n.t("billing.actions.contact_for_free") } end quote = club&.active_billing_quote if quote if quote.plan_slug == target_plan.slug return { kind: :quoted, plan: target_plan, quote: quote, intervals: [quote.billing_interval] } end return { kind: :quoted_other, label: I18n.t("billing.bank_transfer.quoted_other") } end intervals = bank_transfer_intervals_for(target_plan) unless MatchLiveTv.stripe_enabled? if MatchLiveTv.bank_transfer_configured? return { kind: :bank_only, plan: target_plan, intervals: intervals } end return { kind: :disabled, label: I18n.t("billing.actions.stripe_not_configured") } end stripe_intervals = Billing::Stripe::PriceCatalog.available_intervals(plan_slug: target_plan.slug) if stripe_intervals.empty? if MatchLiveTv.bank_transfer_configured? return { kind: :bank_only, plan: target_plan, intervals: intervals } end return { kind: :disabled, label: I18n.t("billing.actions.stripe_prices_not_configured") } end 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 = stripe_intervals - [active_interval] if other_intervals.empty? label = "#{I18n.t('billing.actions.current_plan')} — #{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: stripe_intervals.presence || intervals, subscription: subscription } else { kind: :change_options, plan: target_plan, intervals: stripe_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 plan_cta_name(plan) I18n.t("pages.plans.cta_name.#{plan.slug}", default: plan.name) 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 I18n.t("billing.actions.profile_incomplete_default") if missing.empty? I18n.t("billing.actions.profile_missing", fields: missing.join(", ")) end def bank_transfer_intervals_for(plan) Billing::Stripe::PriceCatalog.catalog_intervals(plan_slug: plan.slug) end def bank_transfer_price_label(plan, interval, quote: nil) if quote&.matches?(plan.slug, interval) quote.price_label else Billing::Stripe::PriceCatalog.format_interval_price( Billing::Stripe::PriceCatalog.amount_cents(plan_slug: plan.slug, interval: interval), interval ) end end def show_bank_transfer_for?(club:, plan:, interval:, quote: nil, pending_transfer: nil) return false unless club.present? && plan.slug != "free" return false unless MatchLiveTv.bank_transfer_configured? return false if quote && !quote.matches?(plan.slug, interval) return false if pending_transfer&.awaiting_payment? true end end end