DoubleEntryLedger.Command.AccountData (double_entry_ledger v0.1.0)
View SourceSchema for account data payload embedded in commands.
This embedded schema captures the minimal set of attributes required to describe an account at the moment a command is issued. It is used to validate and cast incoming payloads.
Summary
Functions
Builds an Ecto.Changeset for AccountData.
Converts an AccountData struct into a plain map with the same fields unless they are nil.
Builds an update changeset for AccountData that only allows modification of certain fields.
Types
@type t() :: %DoubleEntryLedger.Command.AccountData{ address: String.t() | nil, allowed_negative: boolean() | nil, context: map() | nil, currency: DoubleEntryLedger.Utils.Currency.currency_atom() | nil, description: String.t() | nil, name: String.t() | nil, normal_balance: DoubleEntryLedger.Types.credit_and_debit() | nil, type: DoubleEntryLedger.Types.account_type() | nil }
Embedded account data captured with a command payload.
Fields:
- currency: ISO currency code represented as an enum (from Currency.currency_atoms/0)
- name: Human-readable account name
- address: Unique account identifier (e.g. "account:main")
- description: Optional description
- context: Arbitrary metadata map for additional context
- normal_balance: Either :debit or :credit (from Types.credit_and_debit/0)
- type: Account category/type (from Types.account_types/0)
- allowed_negative: Whether the account is allowed to have a negative balance
Functions
@spec changeset(t(), map()) :: Ecto.Changeset.t()
Builds an Ecto.Changeset for AccountData.
Casts: [:currency, :address, :name, :description, :context, :normal_balance, :type, :allowed_negative] Validates required: [:currency, address, :type]
Examples
iex> alias DoubleEntryLedger.Command.AccountData
iex> alias DoubleEntryLedger.Utils.Currency
iex> alias DoubleEntryLedger.Types
iex> attrs = %{
...> currency: hd(Currency.currency_atoms()),
...> address: "account:main",
...> type: hd(Types.account_types())
...> }
iex> changeset = AccountData.changeset(%AccountData{}, attrs)
iex> changeset.valid?
true
iex> alias DoubleEntryLedger.Command.AccountData
iex> changeset = AccountData.changeset(%AccountData{}, %{})
iex> changeset.valid?
false
iex> required = [:currency, :address, :type]
iex> required -- Keyword.keys(changeset.errors)
[]
Converts an AccountData struct into a plain map with the same fields unless they are nil.
The resulting map may include these keys: :currency, :name, :description, :context, :normal_balance, :type, :allowed_negative
Examples
iex> alias DoubleEntryLedger.Command.AccountData
iex> alias DoubleEntryLedger.Utils.Currency
iex> alias DoubleEntryLedger.Types
iex> data = %AccountData{
...> currency: hd(Currency.currency_atoms()),
...> name: "Cash",
...> type: hd(Types.account_types()),
...> address: "account:main"
...> }
iex> map = AccountData.to_map(data)
iex> Map.keys(map) |> Enum.sort()
[:address, :currency, :name, :type]
iex> map.address == data.address and map.currency == data.currency and map.type == data.type and map.name == "Cash"
true
@spec update_changeset(t(), map()) :: Ecto.Changeset.t()
Builds an update changeset for AccountData that only allows modification of certain fields.
Unlike the main changeset, this function only allows updates to fields that are safe to modify after account creation: description and context. Critical fields like currency, name, and type are not allowed to be updated through this changeset.
Casts: [:description, :context] Validates: No additional validations beyond casting
Parameters
account_data- The AccountData struct to updateattrs- Map of attributes to update
Returns
Ecto.Changeset.t()- Changeset with only update-safe fields cast
Examples
iex> alias DoubleEntryLedger.Command.AccountData
iex> existing_data = %AccountData{
...> currency: :USD,
...> address: "account:main",
...> name: "Cash Account",
...> type: :asset,
...> description: "Old description"
...> }
iex> update_attrs = %{
...> description: "Updated description",
...> context: %{department: "finance"}
...> }
iex> changeset = AccountData.update_changeset(existing_data, update_attrs)
iex> changeset.valid?
true
iex> changeset.changes.description
"Updated description"
iex> changeset.changes.context
%{department: "finance"}
iex> alias DoubleEntryLedger.Command.AccountData
iex> existing_data = %AccountData{currency: :USD, name: "Cash", type: :asset}
iex> # Attempting to update restricted fields should have no effect
iex> invalid_update = %{
...> name: "New Name",
...> address: "account:main2",
...> currency: :EUR,
...> type: :liability,
...> description: "Valid update"
...> }
iex> changeset = AccountData.update_changeset(existing_data, invalid_update)
iex> changeset.valid?
true
iex> # description and name should be in changes, not the restricted fields
iex> Keyword.equal?(Map.keys(changeset.changes), [:description, :name])
true
iex> changeset.changes.description
"Valid update"