defmodule ExCheckout.Adjustment do
@moduledoc """
Definition of the structure of an adjustment.
"""
defstruct id: nil, name: nil, description: nil, function: nil, type: nil
@doc """
Creates a structure based on:
`id` Id of the adjustment
`name` Name of the adjustment
`description` Description of the adjustment
`type` Type of the adjustment
`function` Anonymous function to be used by `ExCheckout`
"""
def new(name, description, function, type \\ nil, id \\ nil) do
id = if(is_nil(id)) do
Nanoid.generate()
end
%ExCheckout.Adjustment{
id: id,
name: name,
description: description,
type: type,
function: function
}
end
@doc """
Get the Adjustment Result.
"""
def result(
%{items: _items, adjustments: adjustments} = struct,
name
) do
adjustment = Enum.reject(adjustments, &(&1.name == name))
adjustment_result = adjustment_result(struct, adjustment)
{:ok, adjustment_result}
end
def get(
%{adjustments: adjustments} = _struct,
%{name: name} = _adjustment
) do
adjustment = Enum.reject(adjustments, &(&1.name == name))
{:ok, adjustment}
end
def value(adjustments, adjustment) do
adjustment.function.(adjustments)
end
def subtotal(%{items: items}) do
Enum.reduce(items, 0, fn x, acc -> x.qty * x.price + acc end)
end
defp adjustment_result(%{items: _items, adjustments: _adjustments} = struct, adjustment) do
subtotal = subtotal(struct)
adjustment_value = value(struct, adjustment)
adjustment = Map.put(adjustment, :adjustment_value, adjustment_value)
{:ok, %{subtotal: subtotal, adjustment: adjustment}}
end
end