Billing: fatture manuali, profilo obbligatorio e piani Stripe mensile/annuale.
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>
This commit is contained in:
74
backend/app/services/billing/stripe/price_catalog.rb
Normal file
74
backend/app/services/billing/stripe/price_catalog.rb
Normal file
@@ -0,0 +1,74 @@
|
||||
module Billing
|
||||
module Stripe
|
||||
class PriceCatalog
|
||||
INTERVALS = %w[monthly yearly].freeze
|
||||
DEFAULT_INTERVAL = "yearly"
|
||||
|
||||
PRICING = {
|
||||
"premium_light" => { "yearly" => "€39,90/anno", "monthly" => "€4,90/mese" },
|
||||
"premium_full" => { "yearly" => "€69,90/anno", "monthly" => "€9,90/mese" }
|
||||
}.freeze
|
||||
|
||||
class << self
|
||||
def normalize_interval(value)
|
||||
interval = value.to_s.presence || DEFAULT_INTERVAL
|
||||
raise ArgumentError, "Intervallo non valido" unless INTERVALS.include?(interval)
|
||||
|
||||
interval
|
||||
end
|
||||
|
||||
def price_id(plan_slug:, interval:)
|
||||
interval = normalize_interval(interval)
|
||||
id = price_id_for(plan_slug.to_s, interval)
|
||||
raise "Price ID Stripe mancante per #{plan_slug} (#{interval})" if id.blank?
|
||||
|
||||
id
|
||||
end
|
||||
|
||||
def configured?(plan_slug:, interval:)
|
||||
price_id_for(plan_slug.to_s, normalize_interval(interval)).present?
|
||||
end
|
||||
|
||||
def label(plan_slug:, interval:)
|
||||
PRICING.dig(plan_slug.to_s, normalize_interval(interval)) || normalize_interval(interval)
|
||||
end
|
||||
|
||||
def available_intervals(plan_slug:)
|
||||
INTERVALS.select { |interval| configured?(plan_slug: plan_slug, interval: interval) }
|
||||
end
|
||||
|
||||
def infer_from_price_id(price_id)
|
||||
return nil if price_id.blank?
|
||||
|
||||
{
|
||||
MatchLiveTv.stripe_premium_light_monthly_price_id => %w[premium_light monthly],
|
||||
MatchLiveTv.stripe_premium_light_yearly_price_id => %w[premium_light yearly],
|
||||
MatchLiveTv.stripe_premium_full_monthly_price_id => %w[premium_full monthly],
|
||||
MatchLiveTv.stripe_premium_full_yearly_price_id => %w[premium_full yearly]
|
||||
}.each do |configured_id, pair|
|
||||
return pair if configured_id.present? && configured_id == price_id
|
||||
end
|
||||
|
||||
nil
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def price_id_for(plan_slug, interval)
|
||||
case [plan_slug, interval]
|
||||
when %w[premium_light monthly]
|
||||
MatchLiveTv.stripe_premium_light_monthly_price_id
|
||||
when %w[premium_light yearly]
|
||||
MatchLiveTv.stripe_premium_light_yearly_price_id
|
||||
when %w[premium_full monthly]
|
||||
MatchLiveTv.stripe_premium_full_monthly_price_id
|
||||
when %w[premium_full yearly]
|
||||
MatchLiveTv.stripe_premium_full_yearly_price_id
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user