Il piano si attiva solo dopo la conferma admin; Stripe resta a listino se non c'è un prezzo commerciale. Co-authored-by: Cursor <cursoragent@cursor.com>
135 lines
4.3 KiB
Ruby
135 lines
4.3 KiB
Ruby
module Billing
|
|
module Stripe
|
|
class PriceCatalog
|
|
INTERVALS = %w[monthly yearly].freeze
|
|
DEFAULT_INTERVAL = "yearly"
|
|
|
|
# Importi in centesimi (EUR). Il yearly è il prezzo lancio addebitato.
|
|
AMOUNTS = {
|
|
"premium_light" => {
|
|
"yearly" => { charge: 5900, list: 7900, equivalent_monthly: 492 },
|
|
"monthly" => { charge: 790 }
|
|
},
|
|
"premium_full" => {
|
|
"yearly" => { charge: 19_900, list: 24_900, equivalent_monthly: 1658 },
|
|
"monthly" => { charge: 2490 }
|
|
}
|
|
}.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:)
|
|
interval = normalize_interval(interval)
|
|
format_interval_price(charge_cents(plan_slug, interval), interval)
|
|
end
|
|
|
|
def list_label(plan_slug:, interval: "yearly")
|
|
interval = normalize_interval(interval)
|
|
cents = list_cents(plan_slug, interval)
|
|
return nil if cents.blank?
|
|
|
|
format_interval_price(cents, interval)
|
|
end
|
|
|
|
def equivalent_monthly_label(plan_slug:)
|
|
cents = AMOUNTS.dig(plan_slug.to_s, "yearly", :equivalent_monthly)
|
|
return nil if cents.blank?
|
|
|
|
format_interval_price(cents, "monthly")
|
|
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
|
|
|
|
def format_eur(cents)
|
|
cents = cents.to_i
|
|
whole, frac = cents.divmod(100)
|
|
if frac.zero?
|
|
"€#{whole}"
|
|
else
|
|
sep = I18n.locale.to_s == "en" ? "." : ","
|
|
"€#{whole}#{sep}#{frac.to_s.rjust(2, '0')}"
|
|
end
|
|
end
|
|
|
|
def catalog_intervals(plan_slug:)
|
|
INTERVALS.select { |interval| AMOUNTS.dig(plan_slug.to_s, interval, :charge).present? }
|
|
end
|
|
|
|
def amount_cents(plan_slug:, interval:)
|
|
interval = normalize_interval(interval)
|
|
cents = charge_cents(plan_slug, interval)
|
|
raise ArgumentError, "Prezzo listino non disponibile per #{plan_slug} (#{interval})" if cents.blank?
|
|
|
|
cents
|
|
end
|
|
|
|
def format_interval_price(cents, interval)
|
|
return nil if cents.blank?
|
|
|
|
I18n.t("billing.prices.#{interval}", amount: format_eur(cents))
|
|
end
|
|
|
|
private
|
|
|
|
def charge_cents(plan_slug, interval)
|
|
AMOUNTS.dig(plan_slug.to_s, interval, :charge)
|
|
end
|
|
|
|
def list_cents(plan_slug, interval)
|
|
AMOUNTS.dig(plan_slug.to_s, interval, :list)
|
|
end
|
|
|
|
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
|