Packages

phoenix_kit

1.7.18
1.7.208 1.7.207 1.7.206 1.7.205 1.7.204 1.7.203 1.7.202 1.7.201 1.7.200 1.7.199 1.7.198 1.7.197 1.7.196 1.7.194 1.7.193 1.7.192 1.7.191 1.7.190 1.7.189 1.7.187 1.7.186 1.7.185 1.7.184 1.7.183 1.7.182 1.7.181 1.7.180 1.7.179 1.7.178 1.7.177 1.7.176 1.7.175 1.7.174 1.7.173 1.7.172 1.7.171 1.7.170 1.7.169 1.7.168 1.7.167 1.7.166 1.7.165 1.7.164 1.7.162 1.7.161 1.7.160 1.7.159 1.7.157 1.7.156 1.7.155 1.7.154 1.7.153 1.7.152 1.7.151 1.7.150 1.7.149 1.7.146 1.7.145 1.7.144 1.7.143 1.7.138 1.7.133 1.7.132 1.7.131 1.7.130 1.7.128 1.7.126 1.7.125 1.7.121 1.7.120 1.7.119 1.7.118 1.7.117 1.7.116 1.7.115 1.7.114 1.7.113 1.7.112 1.7.111 1.7.110 1.7.109 1.7.108 1.7.107 1.7.106 1.7.105 1.7.104 1.7.103 1.7.102 1.7.101 1.7.100 1.7.99 1.7.98 1.7.97 1.7.96 1.7.95 1.7.94 1.7.93 1.7.92 1.7.91 1.7.90 1.7.89 1.7.88 1.7.87 1.7.86 1.7.85 1.7.84 1.7.83 1.7.82 1.7.81 1.7.80 1.7.79 1.7.78 1.7.77 1.7.76 1.7.75 1.7.74 1.7.71 1.7.70 1.7.69 1.7.66 1.7.65 1.7.64 1.7.63 1.7.62 1.7.61 1.7.59 1.7.58 1.7.57 1.7.56 1.7.55 1.7.54 1.7.53 1.7.52 1.7.51 1.7.49 1.7.44 1.7.43 1.7.42 1.7.41 1.7.39 1.7.38 1.7.37 1.7.36 1.7.34 1.7.33 1.7.31 1.7.30 1.7.29 1.7.28 1.7.27 1.7.26 1.7.25 1.7.24 1.7.23 1.7.22 1.7.21 1.7.20 1.7.19 1.7.18 1.7.17 1.7.16 1.7.15 1.7.14 1.7.13 1.7.12 1.7.11 1.7.10 1.7.9 1.7.8 1.7.7 1.7.6 1.7.5 1.7.4 1.7.3 1.7.2 1.7.1 1.7.0 1.6.20 1.6.19 1.6.18 1.6.17 1.6.16 1.6.15 1.6.14 1.6.13 1.6.12 1.6.11 1.6.10 1.6.9 1.6.8 1.6.7 1.6.6 1.6.5 1.6.4 1.6.3 1.5.2 1.5.1 1.5.0 1.4.9 1.4.8 1.4.7 1.4.6 1.4.5 1.4.4 1.4.3 1.4.2 1.4.1 1.4.0 1.3.2 1.3.1 1.3.0 1.2.10 1.2.9 1.2.8 1.2.7 1.2.5 1.2.4 1.2.2 1.2.1 1.2.0 1.1.0 1.0.0

A foundation for building Elixir Phoenix apps — SaaS, social networks, ERP systems, marketplaces, and more

Current section

Files

Jump to
phoenix_kit lib phoenix_kit billing transaction.ex
Raw

lib/phoenix_kit/billing/transaction.ex

defmodule PhoenixKit.Billing.Transaction do
@moduledoc """
Schema for payment transactions.
Transactions record actual payments and refunds for invoices.
- Positive amount = payment
- Negative amount = refund
Transactions are created when:
- Admin marks invoice as paid (creates payment transaction)
- Admin issues a refund (creates refund transaction)
There are no pending/failed statuses - a transaction is only recorded
when the payment/refund has actually occurred.
"""
use Ecto.Schema
import Ecto.Changeset
alias PhoenixKit.Billing.Invoice
alias PhoenixKit.Users.Auth.User
@payment_methods ~w(bank stripe paypal razorpay)
schema "phoenix_kit_transactions" do
field :uuid, Ecto.UUID
field :transaction_number, :string
field :amount, :decimal
field :currency, :string, default: "EUR"
field :payment_method, :string, default: "bank"
field :description, :string
field :metadata, :map, default: %{}
# For future payment provider integrations
field :provider_transaction_id, :string
field :provider_data, :map, default: %{}
belongs_to :invoice, Invoice
belongs_to :user, User
timestamps(type: :utc_datetime_usec)
end
@doc """
Creates a changeset for a transaction.
"""
def changeset(transaction, attrs) do
transaction
|> cast(attrs, [
:transaction_number,
:amount,
:currency,
:payment_method,
:description,
:metadata,
:provider_transaction_id,
:provider_data,
:invoice_id,
:user_id
])
|> validate_required([
:transaction_number,
:amount,
:currency,
:payment_method,
:invoice_id,
:user_id
])
|> validate_inclusion(:payment_method, @payment_methods)
|> validate_number(:amount, not_equal_to: 0)
|> unique_constraint(:transaction_number)
|> foreign_key_constraint(:invoice_id)
|> foreign_key_constraint(:user_id)
|> maybe_generate_uuid()
end
defp maybe_generate_uuid(changeset) do
case get_field(changeset, :uuid) do
nil -> put_change(changeset, :uuid, UUIDv7.generate())
_ -> changeset
end
end
@doc """
Returns true if this transaction is a payment (positive amount).
"""
def payment?(%__MODULE__{amount: amount}) do
Decimal.positive?(amount)
end
@doc """
Returns true if this transaction is a refund (negative amount).
"""
def refund?(%__MODULE__{amount: amount}) do
Decimal.negative?(amount)
end
@doc """
Returns the transaction type as a string.
"""
def type(%__MODULE__{} = transaction) do
if payment?(transaction), do: "payment", else: "refund"
end
@doc """
Returns the absolute amount (always positive).
"""
def absolute_amount(%__MODULE__{amount: amount}) do
Decimal.abs(amount)
end
@doc """
Returns the list of valid payment methods.
"""
def payment_methods, do: @payment_methods
end