From 9641d01c0488b5bd3e15b697c40907284713bf30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A1bio=20Souza?= Date: Sun, 28 Feb 2021 15:40:46 -0300 Subject: [PATCH] deposit flow --- lib/rocketpay.ex | 4 ++ lib/rocketpay/accounts/deposit.ex | 45 +++++++++++++++++++ lib/rocketpay/users/create.ex | 16 ++++++- .../controllers/accounts_controller.ex | 19 ++++++++ lib/rocketpay_web/router.ex | 3 ++ lib/rocketpay_web/views/users_view.ex | 17 +++++-- 6 files changed, 100 insertions(+), 4 deletions(-) create mode 100644 lib/rocketpay/accounts/deposit.ex create mode 100644 lib/rocketpay_web/controllers/accounts_controller.ex diff --git a/lib/rocketpay.ex b/lib/rocketpay.ex index def6357..424b93c 100644 --- a/lib/rocketpay.ex +++ b/lib/rocketpay.ex @@ -1,5 +1,9 @@ defmodule Rocketpay do alias Rocketpay.Users.Create, as: UserCreate + alias Rocketpay.Accouns.Deposit + defdelegate create_user(params), to: UserCreate, as: :call + + defdelegate deposit(params), to: Deposit, as: :call end diff --git a/lib/rocketpay/accounts/deposit.ex b/lib/rocketpay/accounts/deposit.ex new file mode 100644 index 0000000..b64ee3f --- /dev/null +++ b/lib/rocketpay/accounts/deposit.ex @@ -0,0 +1,45 @@ +defmodule Rocketpay.Accounts.Deposit do + alias Ecto.Multi + + alias Rocketpay.{Account, Repo} + + def call(%{"id" => id, "value" => value}) do + Multi.new() + |> Multi.run(:account, fn repo, _changes -> get_account(repo, id) end) + |> Multi.run(:update_balance, fn repo, %{account: account} -> + update_balance(repo, account, value) + end) + end + + defp get_account(repo, id) do + case repo.get(Account, id) do + nil -> {:error, "Account, not found!"} + account -> {:ok, account} + end + end + + defp update_balance(repo, account, value) do + account + |> sum_values(value) + |> update_account(repo) + end + + defp sum_values(%Account{balance: balance}, value) do + value + |>Decimal.cast() + |> handle_cast(balance) + end + + defp handle_cast({:ok, value}, balance), do: Decimal.add(value, balance) + defp handle_cast(:error, _balanace), do: {:error, "Invalid deposit value!"} + + defp update_account({:error, _reason} = error, _repo), do: error + + defp update_account(value, repo) do + params = %{balance: value} + + params + |> Account.changeset() + |> repo.update() + end +end diff --git a/lib/rocketpay/users/create.ex b/lib/rocketpay/users/create.ex index 00f4764..58e99d7 100644 --- a/lib/rocketpay/users/create.ex +++ b/lib/rocketpay/users/create.ex @@ -1,5 +1,5 @@ defmodule Rocketpay.Users.Create do - alias Rocketpay.{User, Account} + alias Rocketpay.{User, Repo, Account} alias Ecto.Multi def call(params) do @@ -8,6 +8,10 @@ defmodule Rocketpay.Users.Create do |> Multi.run(:create_account, fn repo, %{create_user: user} -> insert_account(repo, user) end) + |> Multi.run(:preload_data, fn repo, %{create_user: user} -> + preload_data(repo, user) + end) + |> run_transaction() end defp insert_account(repo, user) do @@ -20,6 +24,16 @@ defmodule Rocketpay.Users.Create do params = %{user_id: user_id, balance: "0.00"} Account.changeset(params) + end + + defp preload_data(repo, user) do + {:ok, repo.preload(user, :account)} + end + defp run_transaction(multi) do + case Repo.transaction(multi) do + {:error, _operation, reason, _changes} -> {:error, reason} + {:ok, %{preload_data: user}} -> {:ok, user} + end end end diff --git a/lib/rocketpay_web/controllers/accounts_controller.ex b/lib/rocketpay_web/controllers/accounts_controller.ex new file mode 100644 index 0000000..52797b9 --- /dev/null +++ b/lib/rocketpay_web/controllers/accounts_controller.ex @@ -0,0 +1,19 @@ +defmodule RocketpayWeb.AccountsController do + use RocketpayWeb, :controller + + alias Rocketpay.Account + + action_fallback RocketpayWeb.FallbackController + + def deposit(conn, params) do + with {:ok, %Account{} = account} <- Rocketpay.deposit(params) do + conn + |> put_status(:ok) + |> render("update.json", account: account) + end + end + + def withdraw(conn, params) do + + end +end diff --git a/lib/rocketpay_web/router.ex b/lib/rocketpay_web/router.ex index c71cdf6..bad8034 100644 --- a/lib/rocketpay_web/router.ex +++ b/lib/rocketpay_web/router.ex @@ -10,6 +10,9 @@ defmodule RocketpayWeb.Router do get "/:filename", WelcomeController, :index post "/users", UsersController, :create + + post "/accounts/:id/deposit", AccountsController, :deposit + post "/accounts/:id/withdraw", AccountsController, :withdraw end # Enables LiveDashboard only for development diff --git a/lib/rocketpay_web/views/users_view.ex b/lib/rocketpay_web/views/users_view.ex index 95f6d87..33befd5 100644 --- a/lib/rocketpay_web/views/users_view.ex +++ b/lib/rocketpay_web/views/users_view.ex @@ -1,13 +1,24 @@ defmodule RocketpayWeb.UsersView do - alias Rocketpay.User + alias Rocketpay.{Account, User} - def render("create.json", %{user: %User{id: id, name: name, nickname: nickname}}) do + def render("create.json", %{ + user: %User{ + account: %Account{id: account_id, balance: balance}, + id: id, + name: name, + nickname: nickname + } + }) do %{ message: "User created", user: %{ id: id, name: name, - nickname: nickname + nickname: nickname, + account: %{ + id: account_id, + balance: balance + } } } end