Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Integrate flutterwave api and add payment details in manufacturer #1

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions config/runtime.exs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ if config_env() == :prod do
],
secret_key_base: secret_key_base

config :distributed_orders, :flutterwave, System.get_env("FLUTTER_WAVE_SECRET_KEY")
# ## SSL Support
#
# To get SSL working, you will need to add the `https` key
Expand Down
23 changes: 23 additions & 0 deletions lib/distributed_orders/api_client/flutterwave.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
defmodule DistributedOrders.ApiClient.Flutterwave do
use Tesla
require Logger

plug Tesla.Middleware.BaseUrl, get_endpoint()

plug Tesla.Middleware.Headers, [
{"Content-Type", "application/json"},
{"Authorization", "Bearer " <> auth_token()}
]

plug Tesla.Middleware.DecodeJson
plug Tesla.Middleware.JSON

def transfer_money(params) do
post!("/payments", params)
end

defp get_endpoint(), do: "https://api.flutterwave.com/v3"

def auth_token, do: Application.get_env(:distributed_orders, :flutterwave)

end
17 changes: 13 additions & 4 deletions lib/distributed_orders/orders.ex
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,10 @@ defmodule DistributedOrders.Orders do
Manufacturer.changeset(manufacturer, attrs)
end

def get_manufacturer(manufacturer_id) do
Repo.get!(Manufacturer, manufacturer_id)
end

def change_manufacturer_form(%Manufacturer{} = manufacturer, attrs \\ %{}) do
Manufacturer.form_changeset(manufacturer, attrs)
end
Expand All @@ -137,13 +141,12 @@ defmodule DistributedOrders.Orders do
Ecto.Changeset.put_assoc(quality_inspector_changeset, :order, order)
end)
|> Ecto.Multi.insert_all(:manufacturers, Manufacturer, fn %{order: order} ->
insert_manufacturers(manufacturer_changesets, order.id)
end)
insert_manufacturers(manufacturer_changesets, order.id)
end)
|> Repo.transaction()
|> case do
{:ok, %{order: order}} -> {:ok, order}
{:error, _, changeset, _} ->
IO.inspect(changeset)
{:error, changeset}
end
end
Expand All @@ -161,7 +164,7 @@ defmodule DistributedOrders.Orders do

def start_order_process(order) do
order_details = Repo.get!(Order, order.id) |> Repo.preload([:initiator, :quality_inspector, :manufacturers])
req_url = "https://cloud.activepieces.com/api/v1/webhooks/rTY85oBAtl7iHdrf1nsA6"
req_url = "https://cloud.activepieces.com/api/v1/webhooks/KVYuTaKpSYODBlXNTnZGX"
results = for manufacturer <- order_details.manufacturers do
req_body = %{
product_name: order_details.item_name,
Expand All @@ -170,10 +173,16 @@ defmodule DistributedOrders.Orders do
initiator_email: order_details.initiator.email,
qi_name: order_details.quality_inspector.name,
qi_email: order_details.quality_inspector.email,
manufacturer_id: manufacturer.id,
manufacturer_name: manufacturer.name,
manufacturer_email: manufacturer.email,
payment_amount_1: manufacturer.payment_amount_1,
payment_amount_2: manufacturer.payment_amount_2,
payment_amount_3: manufacturer.payment_amount_3,
currency: manufacturer.currency,
quantity: manufacturer.quantity
}

case Req.post!(req_url, json: req_body) do
%{status: 200} -> {manufacturer.name, :ok}
%{status: 400} -> {manufacturer.name, :error}
Expand Down
16 changes: 10 additions & 6 deletions lib/distributed_orders/orders/manufacturer.ex
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,27 @@ defmodule DistributedOrders.Orders.Manufacturer do
field :email, :string
field :name, :string
field :quantity, :integer
field :payment_amount_1, :integer
field :payment_amount_2, :integer
field :payment_amount_3, :integer
field :currency, :string

belongs_to :order, DistributedOrders.Orders.Order

timestamps(type: :utc_datetime)
end

@doc false
def changeset(manufacturer, attrs) do
def changeset(manufacturer, attrs \\ %{}) do
manufacturer
|> cast(attrs, [:name, :email, :quantity, :order_id])
|> validate_required([:name, :email, :quantity, :order_id])
|> cast(attrs, [:name, :email, :quantity, :payment_amount_1, :payment_amount_2, :payment_amount_3, :currency, :order_id])
|> validate_required([:name, :email, :quantity, :payment_amount_1, :payment_amount_2, :payment_amount_3, :currency, :order_id])
|> foreign_key_constraint(:order_id)
end

def form_changeset(manufacturer, attrs) do
def form_changeset(manufacturer, attrs \\ %{}) do
manufacturer
|> cast(attrs, [:name, :email, :quantity])
|> validate_required([:name, :email, :quantity])
|> cast(attrs, [:name, :email, :quantity, :payment_amount_1, :payment_amount_2, :payment_amount_3, :currency])
|> validate_required([:name, :email, :quantity, :payment_amount_1, :payment_amount_2, :payment_amount_3, :currency])
end
end
27 changes: 27 additions & 0 deletions lib/distributed_orders_web/controllers/payment_controller.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
defmodule DistributedOrdersWeb.PaymentController do
use DistributedOrdersWeb, :controller
alias DistributedOrders.ApiClient.Flutterwave
alias DistributedOrders.Orders

def payment(conn, params) do
manufacturer = Orders.get_manufacturer(params["manufacturer_id"])
amount = get_payment_amount(params["payment_no"], manufacturer)

params = %{
"tx_ref" => "ref" <> UUID.uuid4(),
"currency" => manufacturer.currency,
"amount" => Integer.to_string(amount),
"customer" => %{
"email" => manufacturer.email,
"name" => manufacturer.name
},
"redirect_url" => params["redirect_url"]
}
response = Flutterwave.transfer_money(params)
json(conn, %{redirect_link: response.body["data"]["link"]})
end

defp get_payment_amount(1, manufacturer), do: manufacturer.payment_amount_1
defp get_payment_amount(2, manufacturer), do: manufacturer.payment_amount_2
defp get_payment_amount(_, manufacturer), do: manufacturer.payment_amount_3
end
148 changes: 112 additions & 36 deletions lib/distributed_orders_web/live/order_live/new.ex
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,61 @@ defmodule DistributedOrdersWeb.OrderLive.New do
alias DistributedOrders.Orders
alias DistributedOrders.Orders.{Order, Initiator, QualityInspector, Manufacturer}

@available_countries [
%{
country: "Nigeria",
currency: "NGN"
},
%{
country: "United State",
currency: "US"
},
%{
country: "Europe",
currency: "EUR"
},
%{
country: "United Kingdom",
currency: "GBP"
},
%{
country: "Ghana",
currency: "GHS"
},
%{
country: "Francophone Africa (Central Africa)",
currency: "XAF"
},
%{
country: "Francophone Africa (West Africa)",
currency: "XOF"
},
%{
country: "South Africa",
currency: "ZAR"
},
%{
country: "Malawi",
currency: "MWK"
},
%{
country: "Kenya",
currency: "KES"
},
%{
country: "Uganda",
currency: "UGX"
},
%{
country: "Rwanda",
currency: "RWF"
},
%{
country: "Tanzania",
currency: "TZS"
}
]

@impl true
def mount(_params, _session, socket) do
order = %Order{}
Expand All @@ -15,6 +70,7 @@ defmodule DistributedOrdersWeb.OrderLive.New do
{:ok,
socket
|> assign(page_title: "New Order")
|> assign(available_countries: @available_countries)
|> assign(order_details_submitted: false)
|> assign(initiator_submitted: false)
|> assign(quality_inspector_submitted: false)
Expand Down Expand Up @@ -58,10 +114,10 @@ defmodule DistributedOrdersWeb.OrderLive.New do

if changeset.valid? do
{:noreply,
socket
|> assign(order_changeset: changeset)
|> assign(order_details_submitted: true)
|> assign(step: "initiator")}
socket
|> assign(order_changeset: changeset)
|> assign(order_details_submitted: true)
|> assign(step: "initiator")}
else
{:noreply, assign(socket, order_changeset: changeset)}
end
Expand All @@ -81,33 +137,46 @@ defmodule DistributedOrdersWeb.OrderLive.New do

if changeset.valid? do
{:noreply,
socket
|> assign(initiator_changeset: changeset)
|> assign(initiator_submitted: true)
|> assign(step: "quality_inspector")}
else
{:noreply, assign(socket, initiator_changeset: changeset)}
end
socket
|> assign(initiator_changeset: changeset)
|> assign(initiator_submitted: true)
|> assign(step: "quality_inspector")}
else
{:noreply, assign(socket, initiator_changeset: changeset)}
end
end

def handle_event("validate_quality_inspector", %{"quality_inspector" => quality_inspector_params}, socket) do
changeset = Orders.change_quality_inspector_form(socket.assigns.quality_inspector, quality_inspector_params)
{:noreply, assign(socket, quality_inspector_form: to_form(changeset, action: :validate))}
end
def handle_event(
"validate_quality_inspector",
%{"quality_inspector" => quality_inspector_params},
socket
) do
changeset =
Orders.change_quality_inspector_form(
socket.assigns.quality_inspector,
quality_inspector_params
)

def handle_event("save_quality_inspector", %{"quality_inspector" => quality_inspector_params}, socket) do
changeset =
%QualityInspector{}
|> Orders.change_quality_inspector_form(quality_inspector_params)
|> Map.put(:action, :insert)

if changeset.valid? do
{:noreply,
socket
|> assign(quality_inspector_changeset: changeset)
|> assign(quality_inspector_submitted: true)
|> assign(add_manufacturer: true)
|> assign(step: "manufacturer")}
{:noreply, assign(socket, quality_inspector_form: to_form(changeset, action: :validate))}
end

def handle_event(
"save_quality_inspector",
%{"quality_inspector" => quality_inspector_params},
socket
) do
changeset =
%QualityInspector{}
|> Orders.change_quality_inspector_form(quality_inspector_params)
|> Map.put(:action, :insert)

if changeset.valid? do
{:noreply,
socket
|> assign(quality_inspector_changeset: changeset)
|> assign(quality_inspector_submitted: true)
|> assign(add_manufacturer: true)
|> assign(step: "manufacturer")}
else
{:noreply, assign(socket, quality_inspector_changeset: changeset)}
end
Expand All @@ -126,22 +195,27 @@ defmodule DistributedOrdersWeb.OrderLive.New do

if changeset.valid? do
manufacturers = socket.assigns.manufacturers ++ [changeset]

{:noreply,
socket
|> assign(manufacturer_changeset: changeset)
|> assign(manufacturers: manufacturers)
|> assign(add_manufacturer: false)
|> assign(quantity_assigned: socket.assigns.quantity_assigned + String.to_integer(manufacturer_params["quantity"]))}
socket
|> assign(manufacturer_changeset: changeset)
|> assign(manufacturers: manufacturers)
|> assign(add_manufacturer: false)
|> assign(
quantity_assigned:
socket.assigns.quantity_assigned + String.to_integer(manufacturer_params["quantity"])
)}
else
{:noreply, assign(socket, manufacturer_changeset: changeset)}
end
end

def handle_event("add_new_manufacturer", _params, socket) do
{:noreply,
socket
|> assign(add_manufacturer: true)
|> assign(:manufacturer_form, to_form(Orders.change_manufacturer_form(%Manufacturer{})))}
socket
|> assign(add_manufacturer: true)
|> assign(:manufacturer_form, to_form(Orders.change_manufacturer_form(%Manufacturer{})))
}
end

def handle_event("submit_full_order", _params, socket) do
Expand All @@ -155,10 +229,12 @@ defmodule DistributedOrdersWeb.OrderLive.New do
{:ok, order} ->
results = Orders.start_order_process(order)
IO.inspect(results)

{:noreply,
socket
|> put_flash(:info, "Order created successfully.")
|> redirect(to: ~p"/orders/#{order.id}")}

{:error, changeset} ->
{:noreply, assign(socket, order_changeset: changeset)}
end
Expand Down
7 changes: 7 additions & 0 deletions lib/distributed_orders_web/live/order_live/new.html.heex
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,13 @@
<.input field={@manufacturer_form[:name]} type="text" label="Manufacturer Name" />
<.input field={@manufacturer_form[:email]} type="email" label="Manufacturer Email" />
<.input field={@manufacturer_form[:quantity]} type="number" label="Quantity" />
<h3 class="text-xl text-zinc-700 py-4">
Payment Details
</h3>
<.input field={@manufacturer_form[:payment_amount_1]} type="number" label="Initial Payment" />
<.input field={@manufacturer_form[:payment_amount_2]} type="number" label="Interim Payment" />
<.input field={@manufacturer_form[:payment_amount_3]} type="number" label="Final Payment" />
<.input field={@manufacturer_form[:currency]} type="select" label="Currency" prompt="Select a Currency" options={Enum.map(@available_countries, & &1.currency)} />
<:actions>
<.button phx-disable-with="Saving..." value="add_manufacturer" class="mt-4 btn btn-primary">Add Manufacturer</.button>
</:actions>
Expand Down
6 changes: 6 additions & 0 deletions lib/distributed_orders_web/router.ex
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@ defmodule DistributedOrdersWeb.Router do
plug :accepts, ["json"]
end

scope "/api", DistributedOrdersWeb do
pipe_through :api

post "/payment", PaymentController, :payment
end

scope "/", DistributedOrdersWeb do
pipe_through :browser

Expand Down
4 changes: 3 additions & 1 deletion mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,9 @@ defmodule DistributedOrders.MixProject do
{:jason, "~> 1.4"},
{:dns_cluster, "~> 0.1.1"},
{:req, "~> 0.5.0"},
{:bandit, "~> 1.5"}
{:bandit, "~> 1.5"},
{:tesla, "~> 1.13"},
{:uuid, "~> 1.1"}
]
end

Expand Down
Loading