mirror of
https://github.com/ash-project/ash_double_entry.git
synced 2024-09-21 14:03:18 +12:00
106 lines
3.3 KiB
Elixir
106 lines
3.3 KiB
Elixir
defmodule AshDoubleEntry.Balance.Transformers.AddStructure do
|
|
# Adds all the structure required for the resource. See the getting started guide for more.
|
|
@moduledoc false
|
|
use Spark.Dsl.Transformer
|
|
import Spark.Dsl.Builder
|
|
import Ash.Expr
|
|
|
|
def before?(Ash.Resource.Transformers.CachePrimaryKey), do: true
|
|
def before?(Ash.Resource.Transformers.BelongsToAttribute), do: true
|
|
def before?(_), do: false
|
|
|
|
def transform(dsl) do
|
|
storage_type =
|
|
if AshDoubleEntry.Balance.Info.balance_money_composite_type?(dsl) do
|
|
:money_with_currency
|
|
else
|
|
:map
|
|
end
|
|
|
|
dsl
|
|
|> Ash.Resource.Builder.add_new_attribute(:id, :uuid,
|
|
primary_key?: true,
|
|
writable?: false,
|
|
generated?: true,
|
|
allow_nil?: false,
|
|
default: &Ash.UUID.generate/0
|
|
)
|
|
|> Ash.Resource.Builder.add_new_attribute(:balance, AshMoney.Types.Money,
|
|
allow_nil?: false,
|
|
constraints: [
|
|
storage_type: storage_type
|
|
]
|
|
)
|
|
|> Ash.Resource.Builder.add_new_relationship(
|
|
:belongs_to,
|
|
:transfer,
|
|
AshDoubleEntry.Balance.Info.balance_transfer_resource!(dsl),
|
|
attribute_type: AshDoubleEntry.ULID,
|
|
allow_nil?: false,
|
|
attribute_writable?: true
|
|
)
|
|
|> Ash.Resource.Builder.add_new_relationship(
|
|
:belongs_to,
|
|
:account,
|
|
AshDoubleEntry.Balance.Info.balance_account_resource!(dsl),
|
|
allow_nil?: false,
|
|
attribute_writable?: true
|
|
)
|
|
|> add_primary_read_action()
|
|
|> Ash.Resource.Builder.add_action(:create, :upsert_balance,
|
|
accept: [:balance, :account_id, :transfer_id],
|
|
upsert?: true,
|
|
upsert_identity: :unique_references
|
|
)
|
|
|> Ash.Resource.Builder.add_action(:update, :adjust_balance,
|
|
changes: [
|
|
Ash.Resource.Builder.build_action_change(
|
|
{Ash.Resource.Change.Filter,
|
|
filter:
|
|
expr(
|
|
account_id in [^arg(:from_account_id), ^arg(:to_account_id)] and
|
|
transfer_id > ^arg(:transfer_id)
|
|
)}
|
|
),
|
|
Ash.Resource.Builder.build_action_change(
|
|
{AshDoubleEntry.Balance.Changes.AdjustBalance,
|
|
can_add_money?: AshDoubleEntry.Balance.Info.balance_data_layer_can_add_money?(dsl)}
|
|
)
|
|
],
|
|
arguments: [
|
|
Ash.Resource.Builder.build_action_argument(:from_account_id, :uuid, allow_nil?: false),
|
|
Ash.Resource.Builder.build_action_argument(:to_account_id, :uuid, allow_nil?: false),
|
|
Ash.Resource.Builder.build_action_argument(:delta, AshMoney.Types.Money,
|
|
allow_nil?: false
|
|
),
|
|
Ash.Resource.Builder.build_action_argument(:transfer_id, AshDoubleEntry.ULID,
|
|
allow_nil?: false
|
|
)
|
|
]
|
|
)
|
|
|> Ash.Resource.Builder.add_identity(:unique_references, [:account_id, :transfer_id],
|
|
pre_check_with: pre_check_with(dsl)
|
|
)
|
|
end
|
|
|
|
defbuilder add_primary_read_action(dsl) do
|
|
if Ash.Resource.Info.primary_action(dsl, :read) do
|
|
{:ok, dsl}
|
|
else
|
|
Ash.Resource.Builder.add_action(dsl, :read, :_autogenerated_primary_read,
|
|
primary?: true,
|
|
pagination: Ash.Resource.Builder.build_pagination(keyset?: true)
|
|
)
|
|
end
|
|
end
|
|
|
|
defp pre_check_with(dsl) do
|
|
case AshDoubleEntry.Balance.Info.balance_pre_check_identities_with(dsl) do
|
|
:error ->
|
|
nil
|
|
|
|
{:ok, value} ->
|
|
value
|
|
end
|
|
end
|
|
end
|