Current section
Files
Jump to
Current section
Files
lib/invoicex/document/document.ex
defmodule Invoicex.Document do
@moduledoc """
A helper module for `Document` context.
"""
alias __MODULE__.{Group, Invoice}
alias Ecto.{Changeset, Schema}
@doc """
Returns a sorted list of discounts, items and taxes for specified `Invoicex.Document.Group`.
"""
@spec build_group_list(Changeset.t() | Schema.t()) :: [Schema.t()]
def build_group_list(%Changeset{} = changeset) do
discounts = Changeset.get_field(changeset, :discounts)
items = Changeset.get_field(changeset, :items)
taxes = Changeset.get_field(changeset, :taxes)
sort_by_order(discounts ++ items ++ taxes)
end
def build_group_list(%Group{} = group) do
sort_by_order(group.discounts ++ group.items ++ group.taxes)
end
@doc """
Returns a sorted list of discounts, items and taxes for specified `Invoicex.Document.Invoice`.
"""
@spec build_list(Changeset.t() | Schema.t()) :: [Schema.t()]
def build_list(%Changeset{} = changeset) do
groups = Changeset.get_field(changeset, :groups)
items = Changeset.get_field(changeset, :items)
sort_by_order(groups ++ items)
end
def build_list(%Invoice{} = invoice) do
sort_by_order(invoice.groups ++ invoice.items)
end
defp sort_by_order(list), do: Enum.sort_by(list, & &1.order)
@doc """
Checks if every item in list from changeset have properly set order.
"""
@spec validate_orders(Changeset.t(), list, map) :: Changeset.t()
def validate_orders(changeset, [], %{empty: empty}),
do: Changeset.add_error(changeset, :list, empty)
def validate_orders(changeset, list, messages) do
orders = Enum.map(list, & &1.order)
count = Enum.count(orders)
{min, max} = Enum.min_max(orders)
do_validate_orders(changeset, count, min, max, messages)
end
defp do_validate_orders(changeset, count, 1, max, _messages) when count == max, do: changeset
defp do_validate_orders(changeset, _count, _min, _max, %{invalid: invalid}),
do: Changeset.add_error(changeset, :list, invalid)
end