lib/openagents/forum/tip_receipt.ex

main at 58e6347eeb72 · 1 KB

defmodule OpenAgents.Forum.TipReceipt do
  @moduledoc """
  The append-only record of what happened to one tip.

  A settled receipt carries the payment hash, which is what lets the recipient
  find the same payment in their own wallet. A database trigger refuses updates
  and deletes, and one receipt kind per intent means a retried settlement
  cannot append a second one.
  """

  use Ecto.Schema
  import Ecto.Changeset

  alias OpenAgents.Forum.TipIntent

  @kinds ["settled", "failed", "refunded"]

  @primary_key {:id, :binary_id, autogenerate: true}
  schema "forum_tip_receipts" do
    field :kind, :string
    field :amount_sats, :integer
    field :fee_sats, :integer, default: 0
    field :payment_hash, :string
    field :failure_code, :string
    field :occurred_at, :utc_datetime_usec

    belongs_to :intent, TipIntent, type: :binary_id

    timestamps(type: :utc_datetime_usec, updated_at: false)
  end

  def kinds, do: @kinds

  def changeset(receipt, attrs) do
    receipt
    |> cast(attrs, [
      :intent_id,
      :kind,
      :amount_sats,
      :fee_sats,
      :payment_hash,
      :failure_code,
      :occurred_at
    ])
    |> validate_required([:intent_id, :kind, :amount_sats, :occurred_at])
    |> validate_inclusion(:kind, @kinds)
    |> validate_length(:payment_hash, max: 128)
    |> validate_length(:failure_code, max: 64)
    |> unique_constraint([:intent_id, :kind])
  end
end