Bookk.JournalEntry (bookk v1.0.0)

Copy Markdown View Source

A Journal Entry is a set of operations that must be transacted under the same accounting transaction. Those operations describe a change in balance for an account.

Summary

Types

t()

The struct that describe a Journal Entry.

Functions

Checks whether a journal entry is balanced. It is considered balance when the sum of debits is equal the sum of credits.

Calculates a Bookk.JournalEntry represending the diff between two Bookk.JournalEntries where, if the diff journal entry were to be merged with journal entry "a", it would become equal to journal entry "b".

Checks whether a journal entry is empty.

Merges a set or journal entries into one.

Merges two journal entries into one.

Creates a new journal entry from a set of operations.

Creates a new journal entry that reverses all effects from the given journal entry.

Returns the list of operations inside a journal entry.

Types

t()

@type t() :: %Bookk.JournalEntry{operations: [Bookk.Operation.t()]}

The struct that describe a Journal Entry.

Fields

  • operations: the list of operations included in the journal entry.

Functions

balanced?(journal_entry)

@spec balanced?(t()) :: boolean()

Checks whether a journal entry is balanced. It is considered balance when the sum of debits is equal the sum of credits.

Examples

Balanced:

iex> journal_entry = Bookk.JournalEntry.new([
iex>   debit(fixture_account_head(:cash), Decimal.new(10)),
iex>   credit(fixture_account_head(:deposits), Decimal.new(10))
iex> ])
iex>
iex> Bookk.JournalEntry.balanced?(journal_entry)
true

iex> journal_entry = Bookk.JournalEntry.new([
iex>   debit(fixture_account_head(:cash), Decimal.new(10)),
iex>   credit(fixture_account_head(:deposits), Decimal.new(7)),
iex>   credit(fixture_account_head(:deposits), Decimal.new(3))
iex> ])
iex>
iex> Bookk.JournalEntry.balanced?(journal_entry)
true

Unbalanced:

iex> journal_entry = Bookk.JournalEntry.new([
iex>   debit(fixture_account_head(:cash), Decimal.new(10))
iex> ])
iex>
iex> Bookk.JournalEntry.balanced?(journal_entry)
false

iex> journal_entry = Bookk.JournalEntry.new([
iex>   debit(fixture_account_head(:cash), Decimal.new(10)),
iex>   credit(fixture_account_head(:deposits), Decimal.new(7)),
iex>   credit(fixture_account_head(:deposits), Decimal.new(5))
iex> ])
iex>
iex> Bookk.JournalEntry.balanced?(journal_entry)
false

diff(a, b)

@spec diff(a :: t(), b :: t()) :: t()

Calculates a Bookk.JournalEntry represending the diff between two Bookk.JournalEntries where, if the diff journal entry were to be merged with journal entry "a", it would become equal to journal entry "b".

Examples

iex> a = Bookk.JournalEntry.new([
iex>   Bookk.Operation.debit(fixture_account_head(:cash), Decimal.new(25))
iex> ])
iex>
iex> b = Bookk.JournalEntry.new([
iex>   Bookk.Operation.debit(fixture_account_head(:cash), Decimal.new(100)),
iex>   Bookk.Operation.credit(fixture_account_head(:deposits), Decimal.new(100)),
iex> ])
iex>
iex> Bookk.JournalEntry.diff(a, b)
Bookk.JournalEntry.new([
  Bookk.Operation.debit(fixture_account_head(:cash), Decimal.new(75)),
  Bookk.Operation.credit(fixture_account_head(:deposits), Decimal.new(100))
])

empty?(journal_entry)

@spec empty?(t()) :: boolean()

Checks whether a journal entry is empty.

Examples

Is empty when the journal entry has no operations:

iex> Bookk.JournalEntry.empty?(%Bookk.JournalEntry{})
true

Is empty when all operations in the journal entry are empty:

iex> journal_entry = Bookk.JournalEntry.new([
iex>   debit(fixture_account_head(:cash), Decimal.new(0)),
iex>   credit(fixture_account_head(:deposits), Decimal.new(0)),
iex> ])
iex>
iex> Bookk.JournalEntry.empty?(journal_entry)
true

Is not empty when at least one operation in the journal entry isn't empty:

iex> journal_entry = Bookk.JournalEntry.new([
iex>   debit(fixture_account_head(:cash), Decimal.new(10)),
iex> ])
iex>
iex> Bookk.JournalEntry.empty?(journal_entry)
false

get_op(entry, account_head)

@spec get_op(t(), Bookk.AccountHead.t()) :: Bookk.Operation.t()

Get a Bookk.Operation from the given Bookk.JournalEntry by its Bookk.AccountHead.

Examples:

When exists an operation for the given account head, it is returned:

iex> journal_entry = Bookk.JournalEntry.new([
iex>   debit(fixture_account_head(:cash), Decimal.new(25))
iex> ])
iex>
iex> Bookk.JournalEntry.get_op(journal_entry, fixture_account_head(:cash))
%Bookk.Operation{
  direction: :debit,
  account_head: fixture_account_head(:cash),
  amount: Decimal.new(25)
}

When there's no operations for the given account head, then a new empty operation is returned:

iex> Bookk.JournalEntry.new([])
iex> |> Bookk.JournalEntry.get_op(fixture_account_head(:cash))
%Bookk.Operation{
  direction: :debit,
  account_head: fixture_account_head(:cash),
  amount: Decimal.new(0)
}

merge(list)

@spec merge([t()]) :: t()

Merges a set or journal entries into one.

Examples

iex> cash = fixture_account_head(:cash)
iex> deposits = fixture_account_head(:deposits)
iex>
iex> a = Bookk.JournalEntry.new([
iex>   debit(cash, Decimal.new(80)),
iex>   debit(cash, Decimal.new(20)),
iex>   credit(deposits, Decimal.new(100))
iex> ])
iex>
iex> b = Bookk.JournalEntry.new([
iex>   debit(cash, Decimal.new(80)),
iex>   debit(cash, Decimal.new(20)),
iex>   credit(deposits, Decimal.new(100))
iex> ])
iex>
iex> Bookk.JournalEntry.merge([a, b])
Bookk.JournalEntry.new([
  debit(fixture_account_head(:cash), Decimal.new(200)),
  credit(fixture_account_head(:deposits), Decimal.new(200))
])

merge(a, b)

@spec merge(t(), t()) :: t()

Merges two journal entries into one.

Examples

iex> a = Bookk.JournalEntry.new([
iex>   debit(fixture_account_head(:cash), Decimal.new(80)),
iex>   debit(fixture_account_head(:cash), Decimal.new(20)),
iex>   credit(fixture_account_head(:deposits), Decimal.new(100))
iex> ])
iex>
iex> b = Bookk.JournalEntry.new([
iex>   debit(fixture_account_head(:cash), Decimal.new(80)),
iex>   debit(fixture_account_head(:cash), Decimal.new(20)),
iex>   credit(fixture_account_head(:deposits), Decimal.new(100))
iex> ])
iex>
iex> Bookk.JournalEntry.merge(a, b)
%Bookk.JournalEntry{
  operations: [
    debit(fixture_account_head(:cash), Decimal.new(200)),
    credit(fixture_account_head(:deposits), Decimal.new(200))
  ]
}

new(ops)

@spec new([Bookk.Operation.t()]) :: t()

Creates a new journal entry from a set of operations.

Examples

If there're multiple operations touching the same account, they will be merged into a single operation:

iex> Bookk.JournalEntry.new([
iex>   debit(fixture_account_head(:cash), Decimal.new(80)),
iex>   debit(fixture_account_head(:cash), Decimal.new(20)),
iex>   credit(fixture_account_head(:deposits), Decimal.new(100))
iex> ])
%Bookk.JournalEntry{
  operations: [
    debit(fixture_account_head(:cash), Decimal.new(100)),
    credit(fixture_account_head(:deposits), Decimal.new(100))
  ]
}

Empty operations will be dropped:

iex> Bookk.JournalEntry.new([
iex>   debit(fixture_account_head(:cash), Decimal.new(80)),
iex>   debit(fixture_account_head(:cash), Decimal.new(20)),
iex>   credit(fixture_account_head(:deposits), Decimal.new(100)),
iex>   credit(fixture_account_head({:unspent_cash, {:user, "12345"}}), Decimal.new(0))
iex> ])
%Bookk.JournalEntry{
  operations: [
    debit(fixture_account_head(:cash), Decimal.new(100)),
    credit(fixture_account_head(:deposits), Decimal.new(100))
  ]
}

reverse(entry)

@spec reverse(t()) :: t()

Creates a new journal entry that reverses all effects from the given journal entry.

Examples

Reverses all operations in the journal entry:

iex> journal_entry = Bookk.JournalEntry.new([
iex>   debit(fixture_account_head(:cash), Decimal.new(10)),
iex>   credit(fixture_account_head(:deposits), Decimal.new(10))
iex> ])
iex>
iex> Bookk.JournalEntry.reverse(journal_entry)
Bookk.JournalEntry.new([
  debit(fixture_account_head(:deposits), Decimal.new(10)),
  credit(fixture_account_head(:cash), Decimal.new(10))
])

to_operations(journal_entry)

@spec to_operations(t()) :: [Bookk.Operation.t()]

Returns the list of operations inside a journal entry.

Examples

Returns the journal entry's list of operations:

iex> journal_entry = Bookk.JournalEntry.new([
iex>   debit(fixture_account_head(:cash), Decimal.new(50)),
iex>   credit(fixture_account_head(:deposits), Decimal.new(50))
iex> ])
iex>
iex> Bookk.JournalEntry.to_operations(journal_entry)
[
  debit(fixture_account_head(:cash), Decimal.new(50)),
  credit(fixture_account_head(:deposits), Decimal.new(50))
]