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>
96 lines
3.3 KiB
Ruby
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
|