From 6f257945c8e3b84ac22af484d2d453a0afb319a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A1bio=20Souza?= Date: Sun, 28 Feb 2021 20:03:43 -0300 Subject: [PATCH] transaction build and struct --- lib/rocketpay.ex | 3 +- lib/rocketpay/accounts/deposit.ex | 2 +- lib/rocketpay/accounts/operation.ex | 29 ++++++++++--------- lib/rocketpay/accounts/transaction.ex | 10 ++++--- .../accounts/transactions/response.ex | 12 ++++++++ lib/rocketpay/accounts/withdraw.ex | 2 +- .../controllers/accounts_controller.ex | 9 ++++++ lib/rocketpay_web/router.ex | 1 + lib/rocketpay_web/views/accounts_view.ex | 22 ++++++++++++++ 9 files changed, 69 insertions(+), 21 deletions(-) create mode 100644 lib/rocketpay/accounts/transactions/response.ex diff --git a/lib/rocketpay.ex b/lib/rocketpay.ex index b66383d..84289e3 100644 --- a/lib/rocketpay.ex +++ b/lib/rocketpay.ex @@ -1,11 +1,12 @@ defmodule Rocketpay do alias Rocketpay.Users.Create, as: UserCreate - alias Rocketpay.Accounts.{Deposit, Withdraw} + alias Rocketpay.Accounts.{Deposit, Transaction, Withdraw} defdelegate create_user(params), to: UserCreate, as: :call defdelegate deposit(params), to: Deposit, as: :call defdelegate withdraw(params), to: Withdraw, as: :call + defdelegate transaction(params), to: Transaction, as: :call end diff --git a/lib/rocketpay/accounts/deposit.ex b/lib/rocketpay/accounts/deposit.ex index c535fed..e6d4102 100644 --- a/lib/rocketpay/accounts/deposit.ex +++ b/lib/rocketpay/accounts/deposit.ex @@ -11,7 +11,7 @@ defmodule Rocketpay.Accounts.Deposit do defp run_transaction(multi) do case Repo.transaction(multi) do {:error, _opration, reason, _changes} -> {:error, reason} - {:ok, %{update_balance: account}} -> {:ok, account} + {:ok, %{account_deposit: account}} -> {:ok, account} end end end diff --git a/lib/rocketpay/accounts/operation.ex b/lib/rocketpay/accounts/operation.ex index aa9f14c..648e45c 100644 --- a/lib/rocketpay/accounts/operation.ex +++ b/lib/rocketpay/accounts/operation.ex @@ -1,36 +1,37 @@ defmodule Rocketpay.Accounts.Operation do alias Ecto.Multi - alias Rocketpay.{Account, Repo} + alias Rocketpay.Account def call(%{"id" => id, "value" => value}, operation) do operation_name = account_operation_name(operation) Multi.new() - |> Multi.run(operation_name, fn repo, _changes -> get_account(repo, id) end) - |> Multi.run(:update_balance, fn repo, changes -> - account = Map.get(changes, operation_name) - update_balance(repo, account, value, operation) - end) + |> Multi.run(operation_name, fn repo, _changes -> get_account(repo, id) end) + |> Multi.run(operation, fn repo, changes -> + account = Map.get(changes, operation_name) + + update_balance(repo, account, value, operation) + end) end defp get_account(repo, id) do case repo.get(Account, id) do nil -> {:error, "Account not found!"} - account -> {:ok, account} + account -> {:ok, account} end end defp update_balance(repo, account, value, operation) do account - |> operation(value, operation) - |> update_account(repo, account) + |> operation(value, operation) + |> update_account(repo, account) end defp operation(%Account{balance: balance}, value, operation) do value - |>Decimal.cast() - |> handle_cast(balance, operation) + |> Decimal.cast() + |> handle_cast(balance, operation) end defp handle_cast({:ok, value}, balance, :deposit), do: Decimal.add(balance, value) @@ -43,12 +44,12 @@ defmodule Rocketpay.Accounts.Operation do params = %{balance: value} account - |> Account.changeset(params) - |> repo.update() + |> Account.changeset(params) + |> repo.update() end defp account_operation_name(operation) do "account_#{Atom.to_string(operation)}" - |> String.to_atom() + |> String.to_atom() end end diff --git a/lib/rocketpay/accounts/transaction.ex b/lib/rocketpay/accounts/transaction.ex index 348716f..ab36761 100644 --- a/lib/rocketpay/accounts/transaction.ex +++ b/lib/rocketpay/accounts/transaction.ex @@ -2,15 +2,16 @@ defmodule Rocketpay.Accounts.Transaction do alias Ecto.Multi alias Rocketpay.Repo alias Rocketpay.Accounts.Operation + alias Rocketpay.Accounts.Transactions.Response, as: TransactionResponse def call(%{"from" => from_id, "to" => to_id, "value" => value}) do withdraw_params = build_params(from_id, value) deposit_params = build_params(to_id, value) Multi.new() - |> Multi.merge(fn _changes -> Operation.call(withdraw_params, :withdraw) end) - |> Multi.merge(fn _changes -> Operation.call(deposit_params, :deposit) end) - |> run_transaction() + |> Multi.merge(fn _changes -> Operation.call(withdraw_params, :withdraw) end) + |> Multi.merge(fn _changes -> Operation.call(deposit_params, :deposit) end) + |> run_transaction() end defp build_params(id, value), do: %{"id" => id, "value" => value} @@ -19,8 +20,9 @@ defmodule Rocketpay.Accounts.Transaction do case Repo.transaction(multi) do {:error, _opration, reason, _changes} -> {:error, reason} + {:ok, %{deposit: to_account, withdraw: from_account}} -> - {:ok, %{to_account: to_account, from_account: from_account}} + {:ok, TransactionResponse.build(from_account, to_account)} end end end diff --git a/lib/rocketpay/accounts/transactions/response.ex b/lib/rocketpay/accounts/transactions/response.ex new file mode 100644 index 0000000..57b7a5c --- /dev/null +++ b/lib/rocketpay/accounts/transactions/response.ex @@ -0,0 +1,12 @@ +defmodule Rocketpay.Accounts.Transactions.Response do + alias Rocketpay.Account + + defstruct [:from_account, :to_account] + + def build(%Account{} = from_account, %Account{} = to_account) do + %__MODULE__{ + from_account: from_account, + to_account: to_account + } + end +end diff --git a/lib/rocketpay/accounts/withdraw.ex b/lib/rocketpay/accounts/withdraw.ex index f593f29..dc37acc 100644 --- a/lib/rocketpay/accounts/withdraw.ex +++ b/lib/rocketpay/accounts/withdraw.ex @@ -11,7 +11,7 @@ defmodule Rocketpay.Accounts.Withdraw do defp run_transaction(multi) do case Repo.transaction(multi) do {:error, _opration, reason, _changes} -> {:error, reason} - {:ok, %{update_balance: account}} -> {:ok, account} + {:ok, %{account_withdraw: account}} -> {:ok, account} end end end diff --git a/lib/rocketpay_web/controllers/accounts_controller.ex b/lib/rocketpay_web/controllers/accounts_controller.ex index 43a42e8..284046a 100644 --- a/lib/rocketpay_web/controllers/accounts_controller.ex +++ b/lib/rocketpay_web/controllers/accounts_controller.ex @@ -2,6 +2,7 @@ defmodule RocketpayWeb.AccountsController do use RocketpayWeb, :controller alias Rocketpay.Account + alias Rocketpay.Accounts.Transactions.Response, as: TransactionResponse action_fallback RocketpayWeb.FallbackController @@ -20,4 +21,12 @@ defmodule RocketpayWeb.AccountsController do |> render("update.json", account: account) end end + + def transaction(conn, params) do + with {:ok, %TransactionResponse{} = transaction} <- Rocketpay.transaction(params) do + conn + |> put_status(:ok) + |> render("transaction.json", transaction: transaction) + end + end end diff --git a/lib/rocketpay_web/router.ex b/lib/rocketpay_web/router.ex index bad8034..5b814cd 100644 --- a/lib/rocketpay_web/router.ex +++ b/lib/rocketpay_web/router.ex @@ -13,6 +13,7 @@ defmodule RocketpayWeb.Router do post "/accounts/:id/deposit", AccountsController, :deposit post "/accounts/:id/withdraw", AccountsController, :withdraw + post "/accounts/transaction", AccountsController, :transaction end # Enables LiveDashboard only for development diff --git a/lib/rocketpay_web/views/accounts_view.ex b/lib/rocketpay_web/views/accounts_view.ex index 4665d6c..4d219ef 100644 --- a/lib/rocketpay_web/views/accounts_view.ex +++ b/lib/rocketpay_web/views/accounts_view.ex @@ -1,5 +1,6 @@ defmodule RocketpayWeb.AccountsView do alias Rocketpay.Account + alias Rocketpay.Accounts.Transactions.Response, as: TransactionResponse def render("update.json", %{ account: %Account{ @@ -15,4 +16,25 @@ defmodule RocketpayWeb.AccountsView do } } end + + def render("transaction.json", %{ + transaction: %TransactionResponse{ + to_account: to_account, + from_account: from_account + } + }) do + %{ + message: "Transaction done successfully", + transaction: %{ + from_account: %{ + id: from_account.id, + balance: from_account.balance + }, + to_account: %{ + id: to_account.id, + balance: to_account.balance + } + } + } + end end