# `Bookk.JournalEntry`
[🔗](https://github.com/rwillians/bookk/blob/v1.0.0/lib/bookk/journal_entry.ex#L5)

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.

## Related

- `Bookk.Ledger`;
- `Bookk.Operation`;
- `Bookk.AccountHead`.

# `t`

```elixir
@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.

# `balanced?`

```elixir
@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`

```elixir
@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?`

```elixir
@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`

```elixir
@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`

```elixir
@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`

```elixir
@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`

```elixir
@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`

```elixir
@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`

```elixir
@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))
    ]

---

*Consult [api-reference.md](api-reference.md) for complete listing*
