Files
MatchLiveTv/backend/app/services/billing/request_bank_transfer.rb
T
eminuxandCursor 5bcb4170c7 Mostra il piano attivo dopo il bonifico e allinea il flusso società.
Dopo la conferma admin la card restava su «Paga con bonifico»; la società parte da Free, l'owner è staff trasmissione e le mail non bloccano se manca SMTP.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-19 18:31:39 +02:00

96 lines
3.3 KiB
Ruby

module Billing
class RequestBankTransfer
class Error < StandardError; end
PLAN_SLUGS = %w[premium_light premium_full].freeze
def self.call(club:, user:, plan_slug:, interval:)
new(club: club, user: user, plan_slug: plan_slug, interval: interval).call
end
def initialize(club:, user:, plan_slug:, interval:)
@club = club
@user = user
@plan_slug = plan_slug.to_s
@interval = interval
end
def call
raise Error, "Bonifico non configurato sul server" unless MatchLiveTv.bank_transfer_configured?
raise Error, "Piano non valido" unless @plan_slug.in?(PLAN_SLUGS)
raise Error, "Completa i dati di fatturazione prima di richiedere il bonifico." unless @club.billing_profile_complete?
raise Error, "Il piano è un abbonamento omaggio. Contatta il supporto per passarlo a pagamento." if @club.subscription&.admin_comped?
@interval = Billing::Stripe::PriceCatalog.normalize_interval(@interval)
quote = @club.active_billing_quote
amount_cents, kind = resolve_amount(quote)
existing = @club.billing_transfer_orders.awaiting_payment.first
if existing
if existing.plan_slug == @plan_slug && existing.billing_interval == @interval && existing.amount_cents == amount_cents
MatchLiveTv.deliver_mail(BankTransferMailer.with(order: existing).instructions)
return existing
end
existing.cancel!
end
order = nil
ApplicationRecord.transaction do
payment = @club.billing_payments.create!(
provider: "bank_transfer",
amount_cents: amount_cents,
currency: "eur",
status: "pending",
plan_slug: @plan_slug,
description: payment_description(kind, amount_cents)
)
order = @club.billing_transfer_orders.create!(
billing_club_quote: kind == "commercial_quote" ? quote : nil,
billing_payment: payment,
plan_slug: @plan_slug,
billing_interval: @interval,
amount_cents: amount_cents,
currency: "eur",
kind: kind,
status: "awaiting_payment",
reference_code: generate_reference_code,
requested_by_user: @user
)
end
MatchLiveTv.deliver_mail(BankTransferMailer.with(order: order).instructions)
order
end
private
def resolve_amount(quote)
if quote
unless quote.matches?(@plan_slug, @interval)
raise Error, "Per questa società è attivo un prezzo concordato su #{quote.plan.name} (#{quote.price_label})."
end
return [quote.amount_cents, "commercial_quote"]
end
[Billing::Stripe::PriceCatalog.amount_cents(plan_slug: @plan_slug, interval: @interval), "list_price"]
end
def payment_description(kind, amount_cents)
label = Billing::Stripe::PriceCatalog.format_interval_price(amount_cents, @interval)
suffix = kind == "commercial_quote" ? "prezzo concordato, bonifico" : "bonifico"
"#{Plan[@plan_slug].name}#{label} (#{suffix})"
end
def generate_reference_code
8.times do
code = "MLTV-#{SecureRandom.alphanumeric(6).upcase}"
return code unless TransferOrder.exists?(reference_code: code)
end
raise Error, "Impossibile generare il riferimento del bonifico"
end
end
end