Aggiunge pagamento con bonifico e importo concordato per società.
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>
This commit is contained in:
@@ -0,0 +1,95 @@
|
||||
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
|
||||
BankTransferMailer.with(order: existing).instructions.deliver_now
|
||||
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
|
||||
|
||||
BankTransferMailer.with(order: order).instructions.deliver_now
|
||||
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
|
||||
Reference in New Issue
Block a user