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>
81 lines
2.3 KiB
Ruby
81 lines
2.3 KiB
Ruby
module Billing
|
|
class Payment < ApplicationRecord
|
|
self.table_name = "billing_payments"
|
|
|
|
STATUSES = %w[pending paid failed refunded].freeze
|
|
PROVIDERS = %w[stripe bank_transfer].freeze
|
|
|
|
belongs_to :club
|
|
has_one :invoice, class_name: "Billing::Invoice", foreign_key: :billing_payment_id, dependent: :nullify
|
|
has_one :transfer_order, class_name: "Billing::TransferOrder", foreign_key: :billing_payment_id, dependent: :nullify
|
|
|
|
validates :amount_cents, numericality: { greater_than: 0 }
|
|
validates :currency, presence: true
|
|
validates :status, inclusion: { in: STATUSES }
|
|
validates :provider, inclusion: { in: PROVIDERS }
|
|
validates :stripe_invoice_id, uniqueness: true, allow_nil: true
|
|
|
|
scope :recent, -> { order(paid_at: :desc, created_at: :desc) }
|
|
|
|
# Pagamenti pagati senza PDF fattura caricato (da gestire in admin).
|
|
scope :awaiting_invoice_pdf, lambda {
|
|
where(status: "paid").where(
|
|
<<~SQL.squish,
|
|
NOT EXISTS (
|
|
SELECT 1 FROM billing_invoices bi
|
|
INNER JOIN active_storage_attachments asa
|
|
ON asa.record_type = 'Billing::Invoice'
|
|
AND asa.record_id = bi.id
|
|
AND asa.name = 'pdf'
|
|
WHERE bi.billing_payment_id = billing_payments.id
|
|
)
|
|
SQL
|
|
)
|
|
}
|
|
|
|
scope :with_invoice_pdf, lambda {
|
|
where(status: "paid").where(
|
|
<<~SQL.squish,
|
|
EXISTS (
|
|
SELECT 1 FROM billing_invoices bi
|
|
INNER JOIN active_storage_attachments asa
|
|
ON asa.record_type = 'Billing::Invoice'
|
|
AND asa.record_id = bi.id
|
|
AND asa.name = 'pdf'
|
|
WHERE bi.billing_payment_id = billing_payments.id
|
|
)
|
|
SQL
|
|
)
|
|
}
|
|
|
|
def awaiting_invoice_pdf?
|
|
status == "paid" && !invoice&.pdf&.attached?
|
|
end
|
|
|
|
def amount_euros
|
|
amount_cents / 100.0
|
|
end
|
|
|
|
def formatted_amount
|
|
format("%.2f €", amount_euros)
|
|
end
|
|
|
|
def display_description
|
|
PaymentDescription.for_payment(self)
|
|
end
|
|
|
|
def display_status
|
|
{
|
|
"pending" => "In attesa di bonifico",
|
|
"paid" => "Pagato",
|
|
"failed" => "Non riuscito",
|
|
"refunded" => "Rimborsato"
|
|
}[status] || status
|
|
end
|
|
|
|
def invoice_for_display
|
|
invoice
|
|
end
|
|
end
|
|
end
|