Skip to content

Commit

Permalink
transaction build and struct
Browse files Browse the repository at this point in the history
  • Loading branch information
fabiobarboza7 committed Feb 28, 2021
1 parent 8aec28c commit 6f25794
Show file tree
Hide file tree
Showing 9 changed files with 69 additions and 21 deletions.
3 changes: 2 additions & 1 deletion lib/rocketpay.ex
Original file line number Diff line number Diff line change
@@ -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
2 changes: 1 addition & 1 deletion lib/rocketpay/accounts/deposit.ex
Original file line number Diff line number Diff line change
Expand Up @@ -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
29 changes: 15 additions & 14 deletions lib/rocketpay/accounts/operation.ex
Original file line number Diff line number Diff line change
@@ -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)
Expand All @@ -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
10 changes: 6 additions & 4 deletions lib/rocketpay/accounts/transaction.ex
Original file line number Diff line number Diff line change
Expand Up @@ -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}
Expand All @@ -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
12 changes: 12 additions & 0 deletions lib/rocketpay/accounts/transactions/response.ex
Original file line number Diff line number Diff line change
@@ -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
2 changes: 1 addition & 1 deletion lib/rocketpay/accounts/withdraw.ex
Original file line number Diff line number Diff line change
Expand Up @@ -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
9 changes: 9 additions & 0 deletions lib/rocketpay_web/controllers/accounts_controller.ex
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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
1 change: 1 addition & 0 deletions lib/rocketpay_web/router.ex
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
22 changes: 22 additions & 0 deletions lib/rocketpay_web/views/accounts_view.ex
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
defmodule RocketpayWeb.AccountsView do
alias Rocketpay.Account
alias Rocketpay.Accounts.Transactions.Response, as: TransactionResponse

def render("update.json", %{
account: %Account{
Expand All @@ -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

0 comments on commit 6f25794

Please sign in to comment.