module Billing # Etichette leggibili per lo storico pagamenti (mai testo grezzo Stripe / webhook). class PaymentDescription UGLY = /\A(webhook\s*test|test|x|—|-)\z/i AMOUNT_HINTS = { 500 => %w[premium_light monthly], 4000 => %w[premium_light yearly], 2000 => %w[premium_full monthly], 20_000 => %w[premium_full yearly] }.freeze class << self def for_stripe_invoice(invoice) plan_slug, interval = extract_plan_and_interval(invoice) build(plan_slug: plan_slug, interval: interval, amount_cents: invoice.amount_paid) end def for_payment(payment) stored = payment.description.to_s.strip return stored if stored.present? && !ugly?(stored) build( plan_slug: payment.plan_slug, interval: nil, amount_cents: payment.amount_cents ) end private def build(plan_slug:, interval:, amount_cents:) plan_slug, interval = resolve_plan_interval(plan_slug, interval, amount_cents) return plan_label(plan_slug, interval) if plan_slug.present? if amount_cents.present? && amount_cents.to_i.positive? euros = format("%.2f", amount_cents.to_i / 100.0) return "Pagamento Match Live TV — #{euros} €" end "Abbonamento Match Live TV" end def resolve_plan_interval(plan_slug, interval, amount_cents) plan_slug = plan_slug.presence interval = interval.presence if plan_slug.blank? && amount_cents.present? hint = AMOUNT_HINTS[amount_cents.to_i] plan_slug, interval = hint if hint end if plan_slug.present? && interval.blank? && amount_cents.present? hint = AMOUNT_HINTS[amount_cents.to_i] interval = hint&.last if hint&.first == plan_slug end interval ||= Billing::Stripe::PriceCatalog::DEFAULT_INTERVAL if plan_slug.present? [plan_slug, interval] end def plan_label(plan_slug, interval) plan = Plan[plan_slug] price = Billing::Stripe::PriceCatalog.label(plan_slug: plan_slug, interval: interval) "#{plan.name} — #{price}" rescue KeyError plan_slug.to_s.humanize end def extract_plan_and_interval(invoice) meta = merged_metadata(invoice) plan_slug = meta["plan_slug"].presence interval = normalize_interval(meta["billing_interval"]) line = invoice.lines&.data&.first if line line_meta = line_metadata(line) plan_slug ||= line_meta["plan_slug"] interval ||= normalize_interval(line_meta["billing_interval"]) price_id = line_price_id(line) from_price = Billing::Stripe::PriceCatalog.infer_from_price_id(price_id) plan_slug ||= from_price&.first interval ||= from_price&.last end plan_slug = normalize_plan_slug(plan_slug) [plan_slug, interval] end def merged_metadata(invoice) Billing::Stripe::InvoiceMetadata.merged(invoice) end def line_metadata(line) meta = Billing::Stripe::InvoicePaymentRefs.safe_get(line, :metadata) meta.to_h.stringify_keys rescue NoMethodError {} end def line_price_id(line) pricing = Billing::Stripe::InvoicePaymentRefs.safe_get(line, :pricing) details = Billing::Stripe::InvoicePaymentRefs.safe_get(pricing, :price_details) Billing::Stripe::InvoicePaymentRefs.safe_get(details, :price) end def normalize_interval(value) return nil if value.blank? Billing::Stripe::PriceCatalog.normalize_interval(value) rescue ArgumentError nil end def normalize_plan_slug(slug) return nil if slug.blank? slug = slug.to_s slug = "premium_full" if slug == "premium" slug.presence_in(%w[premium_light premium_full]) end def ugly?(text) UGLY.match?(text.to_s.strip) end end end end