# `Beancount.CostSpec`
[🔗](https://github.com/thanos/beancount_ex/blob/v0.6.0/lib/beancount/cost_spec.ex#L1)

Beancount cost/lot specification for inventory postings.

Used by `Beancount.Directives.Posting` when commodities are held at cost.
See [Costs and Prices](https://beancount.github.io/docs/beancount_language_syntax/#costs-and-prices).

## Beancount syntax

    {10 USD}                 per-unit cost
    {{100 USD}}              total cost
    {10 # 9.95 USD}          per-unit and total (e.g. commission)
    {10 USD, 2020-01-02}     with acquisition date
    {10 USD, "lot-a"}        with label
    {10 USD, merge}          merge lots
    {2020-01-01}             date only (lot override)
    {"magic lot"}            label only (lot selection)

## Elixir struct

    %Beancount.CostSpec{
      per_amount: Decimal.new("10"),
      per_currency: "USD",
      total_amount: nil,
      total_currency: nil,
      date: ~D[2020-01-02],
      label: "lot-a",
      merge: false
    }

Legacy shorthand accepted by `Beancount.posting/4`:

    %{amount: Decimal.new("10"), currency: "USD"}

## Fields

  * `per_amount` - per-unit cost as `Decimal.t()`, or `nil` for total-only /
    date-only / label-only specs.
  * `per_currency` - currency for `per_amount`.
  * `total_amount` - total cost for all units (`{{...}}` or `{N # total}`).
  * `total_currency` - currency for `total_amount`.
  * `date` - acquisition `Date.t()` for lot matching (`{10 USD, 2020-01-02}`).
  * `label` - lot label string (`{"magic lot"}` or `{10 USD, "lot-a"}`).
  * `merge` - when `true`, render `merge` to combine matching lots on deposit.

# `t`

```elixir
@type t() :: %Beancount.CostSpec{
  date: Date.t() | nil,
  label: String.t() | nil,
  merge: boolean(),
  per_amount: Decimal.t() | nil,
  per_currency: String.t() | nil,
  total_amount: Decimal.t() | nil,
  total_currency: String.t() | nil
}
```

# `normalize`

```elixir
@spec normalize(t() | map() | nil) :: t() | nil
```

Normalize a cost spec from a struct, legacy map, or `nil`.

## Examples

    iex> Beancount.CostSpec.normalize(%{amount: Decimal.new("10"), currency: "USD"})
    %Beancount.CostSpec{per_amount: Decimal.new("10"), per_currency: "USD", merge: false}

    iex> Beancount.CostSpec.normalize(nil)
    nil

# `to_string`

```elixir
@spec to_string(t()) :: binary()
```

Render a cost spec as a Beancount `{...}` or `{{...}}` suffix (without leading space).

## Examples

    iex> spec = %Beancount.CostSpec{per_amount: Decimal.new("10"), per_currency: "USD", merge: false}
    iex> Beancount.CostSpec.to_string(spec)
    "{10 USD}"

---

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