diff --git a/README.md b/README.md
index c3a59d5..0267212 100644
--- a/README.md
+++ b/README.md
@@ -65,6 +65,35 @@ we need to create the **`sent`** schema:
mix phx.gen.html Ctx Sent sent message_id:string person_id:references:people request_id:string status_id:references:status template:string
```
+When you run this command in your terminal,
+you should see the following output:
+
+```
+* creating lib/app_web/controllers/sent_controller.ex
+* creating lib/app_web/templates/sent/edit.html.eex
+* creating lib/app_web/templates/sent/form.html.eex
+* creating lib/app_web/templates/sent/index.html.eex
+* creating lib/app_web/templates/sent/new.html.eex
+* creating lib/app_web/templates/sent/show.html.eex
+* creating lib/app_web/views/sent_view.ex
+* creating test/app_web/controllers/sent_controller_test.exs
+* creating lib/app/ctx/sent.ex
+* creating priv/repo/migrations/20200224224024_create_sent.exs
+* creating lib/app/ctx.ex
+* injecting lib/app/ctx.ex
+* creating test/app/ctx_test.exs
+* injecting test/app/ctx_test.exs
+
+Add the resource to your browser scope in lib/app_web/router.ex:
+
+ resources "/sent", SentController
+
+Remember to update your repository by running migrations:
+
+$ mix ecto.migrate
+```
+
+We will follow these instructions in the next step!
In case you are wondering what the **`message_id`** and **`request_id`** fields
diff --git a/lib/app/ctx.ex b/lib/app/ctx.ex
new file mode 100644
index 0000000..91d4f2a
--- /dev/null
+++ b/lib/app/ctx.ex
@@ -0,0 +1,104 @@
+defmodule App.Ctx do
+ @moduledoc """
+ The Ctx context.
+ """
+
+ import Ecto.Query, warn: false
+ alias App.Repo
+
+ alias App.Ctx.Sent
+
+ @doc """
+ Returns the list of sent.
+
+ ## Examples
+
+ iex> list_sent()
+ [%Sent{}, ...]
+
+ """
+ def list_sent do
+ Repo.all(Sent)
+ end
+
+ @doc """
+ Gets a single sent.
+
+ Raises `Ecto.NoResultsError` if the Sent does not exist.
+
+ ## Examples
+
+ iex> get_sent!(123)
+ %Sent{}
+
+ iex> get_sent!(456)
+ ** (Ecto.NoResultsError)
+
+ """
+ def get_sent!(id), do: Repo.get!(Sent, id)
+
+ @doc """
+ Creates a sent.
+
+ ## Examples
+
+ iex> create_sent(%{field: value})
+ {:ok, %Sent{}}
+
+ iex> create_sent(%{field: bad_value})
+ {:error, %Ecto.Changeset{}}
+
+ """
+ def create_sent(attrs \\ %{}) do
+ %Sent{}
+ |> Sent.changeset(attrs)
+ |> Repo.insert()
+ end
+
+ @doc """
+ Updates a sent.
+
+ ## Examples
+
+ iex> update_sent(sent, %{field: new_value})
+ {:ok, %Sent{}}
+
+ iex> update_sent(sent, %{field: bad_value})
+ {:error, %Ecto.Changeset{}}
+
+ """
+ def update_sent(%Sent{} = sent, attrs) do
+ sent
+ |> Sent.changeset(attrs)
+ |> Repo.update()
+ end
+
+ @doc """
+ Deletes a sent.
+
+ ## Examples
+
+ iex> delete_sent(sent)
+ {:ok, %Sent{}}
+
+ iex> delete_sent(sent)
+ {:error, %Ecto.Changeset{}}
+
+ """
+ def delete_sent(%Sent{} = sent) do
+ Repo.delete(sent)
+ end
+
+ @doc """
+ Returns an `%Ecto.Changeset{}` for tracking sent changes.
+
+ ## Examples
+
+ iex> change_sent(sent)
+ %Ecto.Changeset{source: %Sent{}}
+
+ """
+ def change_sent(%Sent{} = sent) do
+ Sent.changeset(sent, %{})
+ end
+end
diff --git a/lib/app/ctx/sent.ex b/lib/app/ctx/sent.ex
new file mode 100644
index 0000000..e97f8ef
--- /dev/null
+++ b/lib/app/ctx/sent.ex
@@ -0,0 +1,21 @@
+defmodule App.Ctx.Sent do
+ use Ecto.Schema
+ import Ecto.Changeset
+
+ schema "sent" do
+ field :message_id, :string
+ field :request_id, :string
+ field :template, :string
+ field :person_id, :id
+ field :status_id, :id
+
+ timestamps()
+ end
+
+ @doc false
+ def changeset(sent, attrs) do
+ sent
+ |> cast(attrs, [:message_id, :request_id, :template])
+ |> validate_required([:message_id, :request_id, :template])
+ end
+end
diff --git a/lib/app_web/controllers/sent_controller.ex b/lib/app_web/controllers/sent_controller.ex
new file mode 100644
index 0000000..2aa4f30
--- /dev/null
+++ b/lib/app_web/controllers/sent_controller.ex
@@ -0,0 +1,62 @@
+defmodule AppWeb.SentController do
+ use AppWeb, :controller
+
+ alias App.Ctx
+ alias App.Ctx.Sent
+
+ def index(conn, _params) do
+ sent = Ctx.list_sent()
+ render(conn, "index.html", sent: sent)
+ end
+
+ def new(conn, _params) do
+ changeset = Ctx.change_sent(%Sent{})
+ render(conn, "new.html", changeset: changeset)
+ end
+
+ def create(conn, %{"sent" => sent_params}) do
+ case Ctx.create_sent(sent_params) do
+ {:ok, sent} ->
+ conn
+ |> put_flash(:info, "Sent created successfully.")
+ |> redirect(to: Routes.sent_path(conn, :show, sent))
+
+ {:error, %Ecto.Changeset{} = changeset} ->
+ render(conn, "new.html", changeset: changeset)
+ end
+ end
+
+ def show(conn, %{"id" => id}) do
+ sent = Ctx.get_sent!(id)
+ render(conn, "show.html", sent: sent)
+ end
+
+ def edit(conn, %{"id" => id}) do
+ sent = Ctx.get_sent!(id)
+ changeset = Ctx.change_sent(sent)
+ render(conn, "edit.html", sent: sent, changeset: changeset)
+ end
+
+ def update(conn, %{"id" => id, "sent" => sent_params}) do
+ sent = Ctx.get_sent!(id)
+
+ case Ctx.update_sent(sent, sent_params) do
+ {:ok, sent} ->
+ conn
+ |> put_flash(:info, "Sent updated successfully.")
+ |> redirect(to: Routes.sent_path(conn, :show, sent))
+
+ {:error, %Ecto.Changeset{} = changeset} ->
+ render(conn, "edit.html", sent: sent, changeset: changeset)
+ end
+ end
+
+ def delete(conn, %{"id" => id}) do
+ sent = Ctx.get_sent!(id)
+ {:ok, _sent} = Ctx.delete_sent(sent)
+
+ conn
+ |> put_flash(:info, "Sent deleted successfully.")
+ |> redirect(to: Routes.sent_path(conn, :index))
+ end
+end
diff --git a/lib/app_web/templates/sent/edit.html.eex b/lib/app_web/templates/sent/edit.html.eex
new file mode 100644
index 0000000..29f1a3a
--- /dev/null
+++ b/lib/app_web/templates/sent/edit.html.eex
@@ -0,0 +1,5 @@
+
Edit Sent
+
+<%= render "form.html", Map.put(assigns, :action, Routes.sent_path(@conn, :update, @sent)) %>
+
+<%= link "Back", to: Routes.sent_path(@conn, :index) %>
diff --git a/lib/app_web/templates/sent/form.html.eex b/lib/app_web/templates/sent/form.html.eex
new file mode 100644
index 0000000..27ec585
--- /dev/null
+++ b/lib/app_web/templates/sent/form.html.eex
@@ -0,0 +1,23 @@
+<%= form_for @changeset, @action, fn f -> %>
+ <%= if @changeset.action do %>
+
+
Oops, something went wrong! Please check the errors below.
+
+ <% end %>
+
+ <%= label f, :message_id %>
+ <%= text_input f, :message_id %>
+ <%= error_tag f, :message_id %>
+
+ <%= label f, :request_id %>
+ <%= text_input f, :request_id %>
+ <%= error_tag f, :request_id %>
+
+ <%= label f, :template %>
+ <%= text_input f, :template %>
+ <%= error_tag f, :template %>
+
+
+ <%= submit "Save" %>
+
+<% end %>
diff --git a/lib/app_web/templates/sent/index.html.eex b/lib/app_web/templates/sent/index.html.eex
new file mode 100644
index 0000000..d5b9790
--- /dev/null
+++ b/lib/app_web/templates/sent/index.html.eex
@@ -0,0 +1,30 @@
+Listing Sent
+
+
+
+
+ Message |
+ Request |
+ Template |
+
+ |
+
+
+
+<%= for sent <- @sent do %>
+
+ <%= sent.message_id %> |
+ <%= sent.request_id %> |
+ <%= sent.template %> |
+
+
+ <%= link "Show", to: Routes.sent_path(@conn, :show, sent) %>
+ <%= link "Edit", to: Routes.sent_path(@conn, :edit, sent) %>
+ <%= link "Delete", to: Routes.sent_path(@conn, :delete, sent), method: :delete, data: [confirm: "Are you sure?"] %>
+ |
+
+<% end %>
+
+
+
+<%= link "New Sent", to: Routes.sent_path(@conn, :new) %>
diff --git a/lib/app_web/templates/sent/new.html.eex b/lib/app_web/templates/sent/new.html.eex
new file mode 100644
index 0000000..fb1d323
--- /dev/null
+++ b/lib/app_web/templates/sent/new.html.eex
@@ -0,0 +1,5 @@
+New Sent
+
+<%= render "form.html", Map.put(assigns, :action, Routes.sent_path(@conn, :create)) %>
+
+<%= link "Back", to: Routes.sent_path(@conn, :index) %>
diff --git a/lib/app_web/templates/sent/show.html.eex b/lib/app_web/templates/sent/show.html.eex
new file mode 100644
index 0000000..a5aff35
--- /dev/null
+++ b/lib/app_web/templates/sent/show.html.eex
@@ -0,0 +1,23 @@
+Show Sent
+
+
+
+ -
+ Message:
+ <%= @sent.message_id %>
+
+
+ -
+ Request:
+ <%= @sent.request_id %>
+
+
+ -
+ Template:
+ <%= @sent.template %>
+
+
+
+
+<%= link "Edit", to: Routes.sent_path(@conn, :edit, @sent) %>
+<%= link "Back", to: Routes.sent_path(@conn, :index) %>
diff --git a/lib/app_web/views/sent_view.ex b/lib/app_web/views/sent_view.ex
new file mode 100644
index 0000000..0c06122
--- /dev/null
+++ b/lib/app_web/views/sent_view.ex
@@ -0,0 +1,3 @@
+defmodule AppWeb.SentView do
+ use AppWeb, :view
+end
diff --git a/priv/repo/migrations/20200224224024_create_sent.exs b/priv/repo/migrations/20200224224024_create_sent.exs
new file mode 100644
index 0000000..7c106b2
--- /dev/null
+++ b/priv/repo/migrations/20200224224024_create_sent.exs
@@ -0,0 +1,18 @@
+defmodule App.Repo.Migrations.CreateSent do
+ use Ecto.Migration
+
+ def change do
+ create table(:sent) do
+ add :message_id, :string
+ add :request_id, :string
+ add :template, :string
+ add :person_id, references(:people, on_delete: :nothing)
+ add :status_id, references(:status, on_delete: :nothing)
+
+ timestamps()
+ end
+
+ create index(:sent, [:person_id])
+ create index(:sent, [:status_id])
+ end
+end
diff --git a/test/app/ctx_test.exs b/test/app/ctx_test.exs
new file mode 100644
index 0000000..d699a55
--- /dev/null
+++ b/test/app/ctx_test.exs
@@ -0,0 +1,68 @@
+defmodule App.CtxTest do
+ use App.DataCase
+
+ alias App.Ctx
+
+ describe "sent" do
+ alias App.Ctx.Sent
+
+ @valid_attrs %{message_id: "some message_id", request_id: "some request_id", template: "some template"}
+ @update_attrs %{message_id: "some updated message_id", request_id: "some updated request_id", template: "some updated template"}
+ @invalid_attrs %{message_id: nil, request_id: nil, template: nil}
+
+ def sent_fixture(attrs \\ %{}) do
+ {:ok, sent} =
+ attrs
+ |> Enum.into(@valid_attrs)
+ |> Ctx.create_sent()
+
+ sent
+ end
+
+ test "list_sent/0 returns all sent" do
+ sent = sent_fixture()
+ assert Ctx.list_sent() == [sent]
+ end
+
+ test "get_sent!/1 returns the sent with given id" do
+ sent = sent_fixture()
+ assert Ctx.get_sent!(sent.id) == sent
+ end
+
+ test "create_sent/1 with valid data creates a sent" do
+ assert {:ok, %Sent{} = sent} = Ctx.create_sent(@valid_attrs)
+ assert sent.message_id == "some message_id"
+ assert sent.request_id == "some request_id"
+ assert sent.template == "some template"
+ end
+
+ test "create_sent/1 with invalid data returns error changeset" do
+ assert {:error, %Ecto.Changeset{}} = Ctx.create_sent(@invalid_attrs)
+ end
+
+ test "update_sent/2 with valid data updates the sent" do
+ sent = sent_fixture()
+ assert {:ok, %Sent{} = sent} = Ctx.update_sent(sent, @update_attrs)
+ assert sent.message_id == "some updated message_id"
+ assert sent.request_id == "some updated request_id"
+ assert sent.template == "some updated template"
+ end
+
+ test "update_sent/2 with invalid data returns error changeset" do
+ sent = sent_fixture()
+ assert {:error, %Ecto.Changeset{}} = Ctx.update_sent(sent, @invalid_attrs)
+ assert sent == Ctx.get_sent!(sent.id)
+ end
+
+ test "delete_sent/1 deletes the sent" do
+ sent = sent_fixture()
+ assert {:ok, %Sent{}} = Ctx.delete_sent(sent)
+ assert_raise Ecto.NoResultsError, fn -> Ctx.get_sent!(sent.id) end
+ end
+
+ test "change_sent/1 returns a sent changeset" do
+ sent = sent_fixture()
+ assert %Ecto.Changeset{} = Ctx.change_sent(sent)
+ end
+ end
+end
diff --git a/test/app_web/controllers/sent_controller_test.exs b/test/app_web/controllers/sent_controller_test.exs
new file mode 100644
index 0000000..d18a40e
--- /dev/null
+++ b/test/app_web/controllers/sent_controller_test.exs
@@ -0,0 +1,88 @@
+defmodule AppWeb.SentControllerTest do
+ use AppWeb.ConnCase
+
+ alias App.Ctx
+
+ @create_attrs %{message_id: "some message_id", request_id: "some request_id", template: "some template"}
+ @update_attrs %{message_id: "some updated message_id", request_id: "some updated request_id", template: "some updated template"}
+ @invalid_attrs %{message_id: nil, request_id: nil, template: nil}
+
+ def fixture(:sent) do
+ {:ok, sent} = Ctx.create_sent(@create_attrs)
+ sent
+ end
+
+ describe "index" do
+ test "lists all sent", %{conn: conn} do
+ conn = get(conn, Routes.sent_path(conn, :index))
+ assert html_response(conn, 200) =~ "Listing Sent"
+ end
+ end
+
+ describe "new sent" do
+ test "renders form", %{conn: conn} do
+ conn = get(conn, Routes.sent_path(conn, :new))
+ assert html_response(conn, 200) =~ "New Sent"
+ end
+ end
+
+ describe "create sent" do
+ test "redirects to show when data is valid", %{conn: conn} do
+ conn = post(conn, Routes.sent_path(conn, :create), sent: @create_attrs)
+
+ assert %{id: id} = redirected_params(conn)
+ assert redirected_to(conn) == Routes.sent_path(conn, :show, id)
+
+ conn = get(conn, Routes.sent_path(conn, :show, id))
+ assert html_response(conn, 200) =~ "Show Sent"
+ end
+
+ test "renders errors when data is invalid", %{conn: conn} do
+ conn = post(conn, Routes.sent_path(conn, :create), sent: @invalid_attrs)
+ assert html_response(conn, 200) =~ "New Sent"
+ end
+ end
+
+ describe "edit sent" do
+ setup [:create_sent]
+
+ test "renders form for editing chosen sent", %{conn: conn, sent: sent} do
+ conn = get(conn, Routes.sent_path(conn, :edit, sent))
+ assert html_response(conn, 200) =~ "Edit Sent"
+ end
+ end
+
+ describe "update sent" do
+ setup [:create_sent]
+
+ test "redirects when data is valid", %{conn: conn, sent: sent} do
+ conn = put(conn, Routes.sent_path(conn, :update, sent), sent: @update_attrs)
+ assert redirected_to(conn) == Routes.sent_path(conn, :show, sent)
+
+ conn = get(conn, Routes.sent_path(conn, :show, sent))
+ assert html_response(conn, 200) =~ "some updated message_id"
+ end
+
+ test "renders errors when data is invalid", %{conn: conn, sent: sent} do
+ conn = put(conn, Routes.sent_path(conn, :update, sent), sent: @invalid_attrs)
+ assert html_response(conn, 200) =~ "Edit Sent"
+ end
+ end
+
+ describe "delete sent" do
+ setup [:create_sent]
+
+ test "deletes chosen sent", %{conn: conn, sent: sent} do
+ conn = delete(conn, Routes.sent_path(conn, :delete, sent))
+ assert redirected_to(conn) == Routes.sent_path(conn, :index)
+ assert_error_sent 404, fn ->
+ get(conn, Routes.sent_path(conn, :show, sent))
+ end
+ end
+ end
+
+ defp create_sent(_) do
+ sent = fixture(:sent)
+ {:ok, sent: sent}
+ end
+end