An interledger entry is a collection of journal entries affecting
multiple ledgers that must be transacted under the same accounting
transaction. It's somewhat analogous to an Ecto.Multi holding
multiple operations or a git commit that affect multiple files.
Related
Summary
Functions
Raises Bookk.UnbalancedError if the interledger entry is
unbalanced, otherwise returns the entry.
Checks whether the interledger entry is balanced. It is balance if all of its journal entries are balanced.
Compacts the interledger entry by merging all journal entries that target the same ledger into a single journal entry.
Calculates a Bookk.InterledgerEntry represending the diff between
two Bookk.InterledgerEntry where, if the diff interledger entry
were to be merged with interledger entry "a", it would become equal
to interledger entry "b".
Checks whether an interledger entry is empty. It is empty when it has now journal entries or when all its journal entries are empty.
Get the journal entries for a given ledger id.
Merges a set of interledger entries into one.
Merges two interledger entries into one.
Creates a new interledger entry from a list of ledger + journal entry tuple.
Produces a new interledger entry that is equaly opposite of the given interledger entry, meaning its capable of reverting all the changes that the given entry causes.
Given an interledger entry, it returns all its journal entries in the form of a list of tuples where the first element is the ledger's name and the second element is a list of journal entries that are meant to be posted to such ledger.
Types
@type t() :: %Bookk.InterledgerEntry{ entries_by_ledger_id: %{ required(ledger_id :: String.t()) => Bookk.JournalEntry.t() } }
The struct that represents an interledger entry.
Fields
An interledger entry is composed of:
entries_by_ledger_id: the map of journal entries that are included in the interledger entry, grouped by the name of the ledger against which they should be posted.
Functions
Raises Bookk.UnbalancedError if the interledger entry is
unbalanced, otherwise returns the entry.
iex> interledger_entry = Bookk.InterledgerEntry.new([
iex> {"acme", Bookk.JournalEntry.new([
iex> debit(fixture_account_head(:cash), Decimal.new(30))
iex> ])},
iex> ])
iex>
iex> Bookk.InterledgerEntry.balanced!(interledger_entry)
** (Bookk.UnbalancedError) The interledger entry is unbalanced!
iex> interledger_entry = Bookk.InterledgerEntry.new([
iex> {"acme", Bookk.JournalEntry.new([
iex> debit(fixture_account_head(:cash), Decimal.new(30)),
iex> credit(fixture_account_head(:deposits), Decimal.new(30))
iex> ])},
iex> ])
iex>
iex> Bookk.InterledgerEntry.balanced!(interledger_entry)
Bookk.InterledgerEntry.new([
{"acme", Bookk.JournalEntry.new([
debit(fixture_account_head(:cash), Decimal.new(30)),
credit(fixture_account_head(:deposits), Decimal.new(30))
])}
])
Checks whether the interledger entry is balanced. It is balance if all of its journal entries are balanced.
Examples
Balanced entry:
iex> interledger_entry = Bookk.InterledgerEntry.new([
iex> {"acme", Bookk.JournalEntry.new([
iex> debit(fixture_account_head(:cash), Decimal.new(30)),
iex> credit(fixture_account_head(:deposits), Decimal.new(30))
iex> ])}
iex> ])
iex>
iex> Bookk.InterledgerEntry.balanced?(interledger_entry)
trueUnbalanced entry:
iex> interledger_entry = Bookk.InterledgerEntry.new([
iex> {"acme", Bookk.JournalEntry.new([
iex> debit(fixture_account_head(:cash), Decimal.new(30))
iex> ])},
iex> ])
iex>
iex> Bookk.InterledgerEntry.balanced?(interledger_entry)
false
Compacts the interledger entry by merging all journal entries that target the same ledger into a single journal entry.
Examples
iex> interledger_entry = Bookk.InterledgerEntry.new([
iex> {"acme", Bookk.JournalEntry.new([
iex> debit(fixture_account_head(:cash), Decimal.new(10)),
iex> credit(fixture_account_head(:deposits), Decimal.new(10))
iex> ])},
iex> {"acme", Bookk.JournalEntry.new([
iex> debit(fixture_account_head(:cash), Decimal.new(10)),
iex> credit(fixture_account_head(:deposits), Decimal.new(10))
iex> ])}
iex> ])
iex>
iex> Bookk.InterledgerEntry.compact(interledger_entry)
Bookk.InterledgerEntry.new([
{"acme", Bookk.JournalEntry.new([
debit(fixture_account_head(:cash), Decimal.new(20)),
credit(fixture_account_head(:deposits), Decimal.new(20))
])}
])
Calculates a Bookk.InterledgerEntry represending the diff between
two Bookk.InterledgerEntry where, if the diff interledger entry
were to be merged with interledger entry "a", it would become equal
to interledger entry "b".
Examples
iex> a = Bookk.InterledgerEntry.new([
iex> {"acme", Bookk.JournalEntry.new([
iex> debit(fixture_account_head(:cash), Decimal.new(50)),
iex> credit(fixture_account_head(:deposits), Decimal.new(50)),
iex> ])},
iex> {"acme", Bookk.JournalEntry.new([
iex> debit(fixture_account_head(:cash), Decimal.new(25)),
iex> credit(fixture_account_head(:deposits), Decimal.new(25)),
iex> ])},
iex> ])
iex>
iex> b = Bookk.InterledgerEntry.new([
iex> {"acme", Bookk.JournalEntry.new([
iex> debit(fixture_account_head(:cash), Decimal.new(100)),
iex> credit(fixture_account_head(:deposits), Decimal.new(100)),
iex> ])},
iex> {"acme", Bookk.JournalEntry.new([
iex> debit(fixture_account_head(:cash), Decimal.new(50)),
iex> credit(fixture_account_head(:deposits), Decimal.new(50)),
iex> ])},
iex> ])
iex>
iex> Bookk.InterledgerEntry.diff(a, b)
Bookk.InterledgerEntry.new([
{"acme", Bookk.JournalEntry.new([
debit(fixture_account_head(:cash), Decimal.new(75)),
credit(fixture_account_head(:deposits), Decimal.new(75)),
])}
])
Checks whether an interledger entry is empty. It is empty when it has now journal entries or when all its journal entries are empty.
See Bookk.JournalEntry.empty?/1 to learn more about empty journal
entries.
Examples
Is empty when there's no entries:
iex> Bookk.InterledgerEntry.empty?(%Bookk.InterledgerEntry{})
trueIs empty when all entries are empty:
iex> interledger = Bookk.InterledgerEntry.new([
iex> {"acme", Bookk.JournalEntry.new([
iex> debit(fixture_account_head(:cash), Decimal.new(0))
iex> ])}
iex> ])
iex>
iex> Bookk.InterledgerEntry.empty?(interledger)
trueIs not empty when at least one entry isn't empty:
iex> interledger = Bookk.InterledgerEntry.new([
iex> {"acme", Bookk.JournalEntry.new([
iex> debit(fixture_account_head(:cash), Decimal.new(1))
iex> ])}
iex> ])
iex>
iex> Bookk.InterledgerEntry.empty?(interledger)
false
@spec get_journal_entries(t(), ledger_id :: String.t()) :: [Bookk.JournalEntry.t()]
Get the journal entries for a given ledger id.
Examples
When exists journal entries for the given ledger id:
iex> interledger_entry = Bookk.InterledgerEntry.new([
iex> {"acme", Bookk.JournalEntry.new([
iex> debit(fixture_account_head(:cash), Decimal.new(50)),
iex> credit(fixture_account_head({:unspent_cash, {:user, "12345"}}), Decimal.new(50))
iex> ])}
iex> ])
iex>
iex> Bookk.InterledgerEntry.get_journal_entries(interledger_entry, "acme")
[
Bookk.JournalEntry.new([
debit(fixture_account_head(:cash), Decimal.new(50)),
credit(fixture_account_head({:unspent_cash, {:user, "12345"}}), Decimal.new(50))
])
]Returns an empty array when there's no journal entries for the given ledger id:
iex> Bookk.InterledgerEntry.new([])
iex> |> Bookk.InterledgerEntry.get_journal_entries("acme")
[]
Merges a set of interledger entries into one.
Examples
iex> a = Bookk.InterledgerEntry.new([
iex> {"acme", Bookk.JournalEntry.new([
iex> debit(fixture_account_head(:cash), Decimal.new(10)),
iex> credit(fixture_account_head(:deposits), Decimal.new(10))
iex> ])}
iex> ])
iex>
iex> b = Bookk.InterledgerEntry.new([
iex> {"acme", Bookk.JournalEntry.new([
iex> debit(fixture_account_head(:cash), Decimal.new(10)),
iex> credit(fixture_account_head(:deposits), Decimal.new(10))
iex> ])}
iex> ])
iex>
iex> Bookk.InterledgerEntry.merge([a, b])
Bookk.InterledgerEntry.new([
{"acme", Bookk.JournalEntry.new([
debit(fixture_account_head(:cash), Decimal.new(10)),
credit(fixture_account_head(:deposits), Decimal.new(10))
])},
{"acme", Bookk.JournalEntry.new([
debit(fixture_account_head(:cash), Decimal.new(10)),
credit(fixture_account_head(:deposits), Decimal.new(10))
])}
])
Merges two interledger entries into one.
Examples
iex> a = Bookk.InterledgerEntry.new([
iex> {"acme", Bookk.JournalEntry.new([
iex> debit(fixture_account_head(:cash), Decimal.new(10)),
iex> credit(fixture_account_head(:deposits), Decimal.new(10))
iex> ])}
iex> ])
iex>
iex> b = Bookk.InterledgerEntry.new([
iex> {"acme", Bookk.JournalEntry.new([
iex> debit(fixture_account_head(:cash), Decimal.new(10)),
iex> credit(fixture_account_head(:deposits), Decimal.new(10))
iex> ])}
iex> ])
iex>
iex> Bookk.InterledgerEntry.merge(a, b)
Bookk.InterledgerEntry.new([
{"acme", Bookk.JournalEntry.new([
debit(fixture_account_head(:cash), Decimal.new(10)),
credit(fixture_account_head(:deposits), Decimal.new(10))
])},
{"acme", Bookk.JournalEntry.new([
debit(fixture_account_head(:cash), Decimal.new(10)),
credit(fixture_account_head(:deposits), Decimal.new(10))
])}
])
@spec new([entry]) :: t() when entry: {ledger_id :: String.t(), Bookk.JournalEntry.t()}
Creates a new interledger entry from a list of ledger + journal entry tuple.
Examples
iex> Bookk.InterledgerEntry.new([
iex> {"acme", Bookk.JournalEntry.new([
iex> debit(fixture_account_head(:cash), Decimal.new(50)),
iex> credit(fixture_account_head({:unspent_cash, {:user, "12345"}}), Decimal.new(50))
iex> ])},
iex> {"user(12345)", Bookk.JournalEntry.new([
iex> debit(fixture_account_head(:cash), Decimal.new(50)),
iex> credit(fixture_account_head(:deposits), Decimal.new(50))
iex> ])}
iex> ])
%Bookk.InterledgerEntry{
entries_by_ledger_id: %{
"acme" => [
Bookk.JournalEntry.new([
debit(fixture_account_head(:cash), Decimal.new(50)),
credit(fixture_account_head({:unspent_cash, {:user, "12345"}}), Decimal.new(50))
])
],
"user(12345)" => [
Bookk.JournalEntry.new([
debit(fixture_account_head(:cash), Decimal.new(50)),
credit(fixture_account_head(:deposits), Decimal.new(50))
])
]
}
}
Produces a new interledger entry that is equaly opposite of the given interledger entry, meaning its capable of reverting all the changes that the given entry causes.
Examples
Reverses all of its journal entries:
iex> interledger = Bookk.InterledgerEntry.new([
iex> {"acme", Bookk.JournalEntry.new([
iex> debit(fixture_account_head(:cash), Decimal.new(10)),
iex> credit(fixture_account_head(:deposits), Decimal.new(10))
iex> ])}
iex> ])
iex>
iex> Bookk.InterledgerEntry.reverse(interledger)
Bookk.InterledgerEntry.new([
{"acme", Bookk.JournalEntry.new([
debit(fixture_account_head(:deposits), Decimal.new(10)),
credit(fixture_account_head(:cash), Decimal.new(10))
])}
])
@spec to_journal_entries(t()) :: [{ledger_id :: String.t(), Bookk.JournalEntry.t()}]
Given an interledger entry, it returns all its journal entries in the form of a list of tuples where the first element is the ledger's name and the second element is a list of journal entries that are meant to be posted to such ledger.
Examples
Returns a list of tuple where the first element is the ledger name and the second element is a journal entry:
iex> interledger = Bookk.InterledgerEntry.new([
iex> {"acme", Bookk.JournalEntry.new([
iex> debit(fixture_account_head(:cash), Decimal.new(50)),
iex> credit(fixture_account_head({:unspent_cash, {:user, "12345"}}), Decimal.new(50))
iex> ])},
iex> {"user(12345)", Bookk.JournalEntry.new([
iex> debit(fixture_account_head(:cash), Decimal.new(50)),
iex> credit(fixture_account_head(:deposits), Decimal.new(50))
iex> ])},
iex> ])
iex>
iex> Bookk.InterledgerEntry.to_journal_entries(interledger)
[
{"acme", Bookk.JournalEntry.new([
debit(fixture_account_head(:cash), Decimal.new(50)),
credit(fixture_account_head({:unspent_cash, {:user, "12345"}}), Decimal.new(50))
])},
{"user(12345)", Bookk.JournalEntry.new([
debit(fixture_account_head(:cash), Decimal.new(50)),
credit(fixture_account_head(:deposits), Decimal.new(50))
])}
]