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

DSL notation for describing an interledger entries
(`Bookk.InterledgerEntry`).

## Related

- `Bookk.ChartOfAccounts`;
- `Bookk.InterledgerEntry`;
- `Bookk.NaiveState`.

# `journalize`
*macro* 

DSL notation for describing an interledger entries
(`Bookk.InterledgerEntry`).

## Options

- `using` (required): your chart of accounts module;
- `compact`: whether the resulting interledger entry should be
  compacted, where postings to the same account are merged,
  guaranteeing a single post per account. Defaults to `false`.
- `on_unbalanced`: either `:nothing` or `:raise`, controls the
  desired behaviour for when `journalize/2` produces a unbalanced
  interledger entry. Defaults to `:nothing`.

## Examples

Returns a balanced interledger journal entry:

    iex> use Bookk.Notation
    iex>
    iex> %Bookk.InterledgerEntry{} = journal_entry =
    iex>   journalize using: DummyChartOfAccounts do
    iex>     on ledger(:acme) do
    iex>       debit account(:cash), Decimal.new(150)
    iex>       credit account(:deposits), Decimal.new(150)
    iex>     end
    iex>   end
    iex>
    iex> assert not Bookk.InterledgerEntry.empty?(journal_entry)
    iex> assert Bookk.InterledgerEntry.balanced?(journal_entry)

Returns an unbalanced interledger journal entry:

    iex> use Bookk.Notation
    iex>
    iex> %Bookk.InterledgerEntry{} = journal_entry =
    iex>   journalize using: DummyChartOfAccounts do
    iex>     on ledger(:acme) do
    iex>       debit account(:cash), Decimal.new(150)
    iex>       credit account(:deposits), Decimal.new(50)
    iex>     end
    iex>   end
    iex>
    iex> assert not Bookk.InterledgerEntry.empty?(journal_entry)
    iex> assert not Bookk.InterledgerEntry.balanced?(journal_entry)

You can do basic arithmetic operations with amounts even though they
are most likely `Decimal` structs. The supported operations are
addition, subtraction, multiplication and division where you can mix
and match the use of `Decimal` amounts with integer or float amounts
since they will automatically be converted into `Decimal`. These
operations will be replaced by `Decimal.add/2`, `Decimal.sub/2`,
`Decimal.mul/2` and `Decimal.div/2` respectively.

    iex> use Bookk.Notation
    iex>
    iex> foo = %{amount: 50}
    iex>
    iex> journalize using: DummyChartOfAccounts do
    iex>   on ledger(:acme) do
    iex>     debit account(:cash), ((%Decimal{exp: 0, sign: 1, coef: 100} + Decimal.new(100) - foo.amount) * 2) / 2
    iex>     credit account(:deposits), ((Decimal.new(100) + foo.amount) * Decimal.new(2)) / Decimal.new(2)
    iex>   end
    iex> end
    Bookk.InterledgerEntry.new([
      {"acme", Bookk.JournalEntry.new([
        debit(fixture_account_head(:cash), Decimal.new(150)),
        credit(fixture_account_head(:deposits), Decimal.new(150))
      ])}
    ])

It's possible to post multiple times to the same ledger inside the
interledger entry:

    iex> use Bookk.Notation
    iex>
    iex> journalize using: DummyChartOfAccounts do
    iex>   on ledger(:acme) do
    iex>     debit account(:cash), 50
    iex>     credit account(:deposits), 50
    iex>   end
    iex>
    iex>   on ledger(:acme) do
    iex>     debit account(:cash), 100
    iex>     credit account(:deposits), 100
    iex>   end
    iex> end
    Bookk.InterledgerEntry.new([
      {"acme", Bookk.JournalEntry.new([
        debit(fixture_account_head(:cash), Decimal.new(50)),
        credit(fixture_account_head(:deposits), Decimal.new(50))
      ])},
      {"acme", Bookk.JournalEntry.new([
        debit(fixture_account_head(:cash), Decimal.new(100)),
        credit(fixture_account_head(:deposits), Decimal.new(100))
      ])}
    ])

You can compact multiple postings to the same ledger into a single
post:

    iex> use Bookk.Notation
    iex>
    iex> journalize using: DummyChartOfAccounts, compact: true do
    iex>   on ledger(:acme) do
    iex>     debit account(:cash), 50
    iex>     credit account(:deposits), 50
    iex>   end
    iex>
    iex>   on ledger(:acme) do
    iex>     debit account(:cash), 100
    iex>     credit account(:deposits), 100
    iex>   end
    iex> end
    Bookk.InterledgerEntry.new([
      {"acme", Bookk.JournalEntry.new([
        debit(fixture_account_head(:cash), Decimal.new(150)),
        credit(fixture_account_head(:deposits), Decimal.new(150))
      ])}
    ])

You can define the behaviour for when your `journalize/2` produces
a unbalanced interledger entry. The default is doing `:nothing`, but
your can set it to `:raise`:

    iex> use Bookk.Notation
    iex>
    iex> journalize using: DummyChartOfAccounts, on_unbalanced: :raise do
    iex>   on ledger(:acme) do
    iex>     debit account(:cash), 50
    iex>   end
    iex> end
    ** (Bookk.UnbalancedError) The interledger entry is unbalanced!

---

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