Packages
monzo_client
1.0.0
A complete, production-grade Elixir client for the Monzo API: OAuth2, Accounts, Balance, Pots, Transactions, Feed Items, Attachments, Transaction Receipts, and Webhooks. Zero required dependencies.
Current section
Files
Jump to
Current section
Files
lib/monzo/transaction.ex
defmodule Monzo.Transaction do
@moduledoc """
A single ledger entry on a Monzo account.
The `merchant` field is polymorphic on the wire: it's a bare merchant id
string unless expanded via `expand: [:merchant]`, in which case it's a
full object. This struct always splits that into two separate fields:
`merchant_id` (always present when a merchant exists) and `merchant`
(only populated when expanded).
"""
alias Monzo.Internal.Time, as: InternalTime
@type decline_reason ::
:insufficient_funds | :card_inactive | :card_blocked | :invalid_cvc | :other | nil
@type t :: %__MODULE__{
id: String.t(),
amount: integer(),
created: DateTime.t() | nil,
currency: String.t(),
description: String.t(),
metadata: %{optional(String.t()) => String.t()},
notes: String.t(),
is_load: boolean(),
settled: DateTime.t() | nil,
category: String.t() | nil,
decline_reason: decline_reason(),
account_id: String.t() | nil,
merchant_id: String.t() | nil,
merchant: Monzo.Merchant.t() | nil
}
defstruct [
:id,
:amount,
:created,
:currency,
:description,
:notes,
:settled,
:category,
:decline_reason,
:account_id,
:merchant_id,
:merchant,
metadata: %{},
is_load: false
]
@doc false
@spec from_json(map()) :: t()
def from_json(json) do
{merchant_id, merchant} = parse_merchant(json["merchant"])
%__MODULE__{
id: json["id"],
amount: json["amount"],
created: InternalTime.parse(json["created"]),
currency: json["currency"],
description: json["description"],
metadata: json["metadata"] || %{},
notes: json["notes"] || "",
is_load: json["is_load"] || false,
settled: InternalTime.parse(json["settled"]),
category: json["category"],
decline_reason: parse_decline_reason(json["decline_reason"]),
account_id: json["account_id"],
merchant_id: merchant_id,
merchant: merchant
}
end
defp parse_merchant(nil), do: {nil, nil}
defp parse_merchant(id) when is_binary(id), do: {id, nil}
defp parse_merchant(%{} = merchant_json) do
merchant = Monzo.Merchant.from_json(merchant_json)
{merchant.id, merchant}
end
defp parse_decline_reason(nil), do: nil
defp parse_decline_reason("INSUFFICIENT_FUNDS"), do: :insufficient_funds
defp parse_decline_reason("CARD_INACTIVE"), do: :card_inactive
defp parse_decline_reason("CARD_BLOCKED"), do: :card_blocked
defp parse_decline_reason("INVALID_CVC"), do: :invalid_cvc
defp parse_decline_reason(_other), do: :other
@doc "Returns the RFC3339 cursor value used for pagination (the transaction's `created` timestamp)."
@spec cursor_value(t()) :: String.t() | nil
def cursor_value(%__MODULE__{created: nil}), do: nil
def cursor_value(%__MODULE__{created: created}), do: DateTime.to_iso8601(created)
end