From fccb0c38ddcfd192153e3bc31dc8fa65836ec04e Mon Sep 17 00:00:00 2001 From: endoooo Date: Sat, 11 Nov 2023 19:46:29 -0300 Subject: [PATCH] feat: created `Cycle` schema in `Schools` context adjusted files generated by `mix phx.gen.live`, supporting DB constraints --- lib/lanttern/schools.ex | 96 ++++++++++++ lib/lanttern/schools/cycle.ex | 25 ++++ .../controllers/admin_html/home.html.heex | 1 + .../live/admin/cycle_live/form_component.ex | 101 +++++++++++++ .../live/admin/cycle_live/index.ex | 47 ++++++ .../live/admin/cycle_live/index.html.heex | 48 ++++++ .../live/admin/cycle_live/show.ex | 21 +++ .../live/admin/cycle_live/show.html.heex | 33 +++++ lib/lanttern_web/router.ex | 8 + .../20231110160629_create_school_cycles.exs | 22 +++ test/lanttern/schools_test.exs | 70 +++++++++ .../live/admin/cycle_live_test.exs | 140 ++++++++++++++++++ test/support/fixtures/schools_fixtures.ex | 70 ++++----- 13 files changed, 637 insertions(+), 45 deletions(-) create mode 100644 lib/lanttern/schools/cycle.ex create mode 100644 lib/lanttern_web/live/admin/cycle_live/form_component.ex create mode 100644 lib/lanttern_web/live/admin/cycle_live/index.ex create mode 100644 lib/lanttern_web/live/admin/cycle_live/index.html.heex create mode 100644 lib/lanttern_web/live/admin/cycle_live/show.ex create mode 100644 lib/lanttern_web/live/admin/cycle_live/show.html.heex create mode 100644 priv/repo/migrations/20231110160629_create_school_cycles.exs create mode 100644 test/lanttern_web/live/admin/cycle_live_test.exs diff --git a/lib/lanttern/schools.ex b/lib/lanttern/schools.ex index 238223b8..f17a2f69 100644 --- a/lib/lanttern/schools.ex +++ b/lib/lanttern/schools.ex @@ -715,4 +715,100 @@ defmodule Lanttern.Schools do {:ok, response} end + + alias Lanttern.Schools.Cycle + + @doc """ + Returns the list of school_cycles. + + ## Examples + + iex> list_school_cycles() + [%Cycle{}, ...] + + """ + def list_school_cycles do + Repo.all(Cycle) + end + + @doc """ + Gets a single cycle. + + Raises `Ecto.NoResultsError` if the Cycle does not exist. + + ## Examples + + iex> get_cycle!(123) + %Cycle{} + + iex> get_cycle!(456) + ** (Ecto.NoResultsError) + + """ + def get_cycle!(id), do: Repo.get!(Cycle, id) + + @doc """ + Creates a cycle. + + ## Examples + + iex> create_cycle(%{field: value}) + {:ok, %Cycle{}} + + iex> create_cycle(%{field: bad_value}) + {:error, %Ecto.Changeset{}} + + """ + def create_cycle(attrs \\ %{}) do + %Cycle{} + |> Cycle.changeset(attrs) + |> Repo.insert() + end + + @doc """ + Updates a cycle. + + ## Examples + + iex> update_cycle(cycle, %{field: new_value}) + {:ok, %Cycle{}} + + iex> update_cycle(cycle, %{field: bad_value}) + {:error, %Ecto.Changeset{}} + + """ + def update_cycle(%Cycle{} = cycle, attrs) do + cycle + |> Cycle.changeset(attrs) + |> Repo.update() + end + + @doc """ + Deletes a cycle. + + ## Examples + + iex> delete_cycle(cycle) + {:ok, %Cycle{}} + + iex> delete_cycle(cycle) + {:error, %Ecto.Changeset{}} + + """ + def delete_cycle(%Cycle{} = cycle) do + Repo.delete(cycle) + end + + @doc """ + Returns an `%Ecto.Changeset{}` for tracking cycle changes. + + ## Examples + + iex> change_cycle(cycle) + %Ecto.Changeset{data: %Cycle{}} + + """ + def change_cycle(%Cycle{} = cycle, attrs \\ %{}) do + Cycle.changeset(cycle, attrs) + end end diff --git a/lib/lanttern/schools/cycle.ex b/lib/lanttern/schools/cycle.ex new file mode 100644 index 00000000..630988be --- /dev/null +++ b/lib/lanttern/schools/cycle.ex @@ -0,0 +1,25 @@ +defmodule Lanttern.Schools.Cycle do + use Ecto.Schema + import Ecto.Changeset + + schema "school_cycles" do + field :name, :string + field :start_at, :date + field :end_at, :date + belongs_to :school, Lanttern.Schools.School + + timestamps() + end + + @doc false + def changeset(cycle, attrs) do + cycle + |> cast(attrs, [:name, :start_at, :end_at, :school_id]) + |> validate_required([:name, :start_at, :end_at, :school_id]) + |> check_constraint( + :end_at, + name: :cycle_end_date_is_greater_than_start_date, + message: "End date should be greater than start date" + ) + end +end diff --git a/lib/lanttern_web/controllers/admin_html/home.html.heex b/lib/lanttern_web/controllers/admin_html/home.html.heex index 49f19507..1ad9419b 100644 --- a/lib/lanttern_web/controllers/admin_html/home.html.heex +++ b/lib/lanttern_web/controllers/admin_html/home.html.heex @@ -32,6 +32,7 @@ <:item link={~p"/admin/import_students"}>Import students <:item link={~p"/admin/teachers"}>Teachers <:item link={~p"/admin/import_teachers"}>Import teachers + <:item link={~p"/admin/school_cycles"}>Cycles <.link_list title="Taxonomy"> <:item link={~p"/admin/subjects"}>Subjects diff --git a/lib/lanttern_web/live/admin/cycle_live/form_component.ex b/lib/lanttern_web/live/admin/cycle_live/form_component.ex new file mode 100644 index 00000000..fc603e49 --- /dev/null +++ b/lib/lanttern_web/live/admin/cycle_live/form_component.ex @@ -0,0 +1,101 @@ +defmodule LantternWeb.Admin.CycleLive.FormComponent do + use LantternWeb, :live_component + + alias Lanttern.Schools + import LantternWeb.SchoolsHelpers + + @impl true + def render(assigns) do + ~H""" +
+ <.header> + <%= @title %> + <:subtitle>Use this form to manage cycle records in your database. + + + <.simple_form + for={@form} + id="cycle-form" + phx-target={@myself} + phx-change="validate" + phx-submit="save" + > + <.input + field={@form[:school_id]} + type="select" + label="School" + prompt="Select school" + options={@school_options} + /> + <.input field={@form[:name]} type="text" label="Name" /> + <.input field={@form[:start_at]} type="date" label="Start at" /> + <.input field={@form[:end_at]} type="date" label="End at" /> + <:actions> + <.button phx-disable-with="Saving...">Save Cycle + + +
+ """ + end + + @impl true + def update(%{cycle: cycle} = assigns, socket) do + changeset = Schools.change_cycle(cycle) + + {:ok, + socket + |> assign(assigns) + |> assign(:school_options, generate_school_options()) + |> assign_form(changeset)} + end + + @impl true + def handle_event("validate", %{"cycle" => cycle_params}, socket) do + changeset = + socket.assigns.cycle + |> Schools.change_cycle(cycle_params) + |> Map.put(:action, :validate) + + {:noreply, assign_form(socket, changeset)} + end + + def handle_event("save", %{"cycle" => cycle_params}, socket) do + save_cycle(socket, socket.assigns.action, cycle_params) + end + + defp save_cycle(socket, :edit, cycle_params) do + case Schools.update_cycle(socket.assigns.cycle, cycle_params) do + {:ok, cycle} -> + notify_parent({:saved, cycle}) + + {:noreply, + socket + |> put_flash(:info, "Cycle updated successfully") + |> push_patch(to: socket.assigns.patch)} + + {:error, %Ecto.Changeset{} = changeset} -> + {:noreply, assign_form(socket, changeset)} + end + end + + defp save_cycle(socket, :new, cycle_params) do + case Schools.create_cycle(cycle_params) do + {:ok, cycle} -> + notify_parent({:saved, cycle}) + + {:noreply, + socket + |> put_flash(:info, "Cycle created successfully") + |> push_patch(to: socket.assigns.patch)} + + {:error, %Ecto.Changeset{} = changeset} -> + {:noreply, assign_form(socket, changeset)} + end + end + + defp assign_form(socket, %Ecto.Changeset{} = changeset) do + assign(socket, :form, to_form(changeset)) + end + + defp notify_parent(msg), do: send(self(), {__MODULE__, msg}) +end diff --git a/lib/lanttern_web/live/admin/cycle_live/index.ex b/lib/lanttern_web/live/admin/cycle_live/index.ex new file mode 100644 index 00000000..2b810fdf --- /dev/null +++ b/lib/lanttern_web/live/admin/cycle_live/index.ex @@ -0,0 +1,47 @@ +defmodule LantternWeb.Admin.CycleLive.Index do + use LantternWeb, {:live_view, layout: :admin} + + alias Lanttern.Schools + alias Lanttern.Schools.Cycle + + @impl true + def mount(_params, _session, socket) do + {:ok, stream(socket, :school_cycles, Schools.list_school_cycles())} + end + + @impl true + def handle_params(params, _url, socket) do + {:noreply, apply_action(socket, socket.assigns.live_action, params)} + end + + defp apply_action(socket, :edit, %{"id" => id}) do + socket + |> assign(:page_title, "Edit Cycle") + |> assign(:cycle, Schools.get_cycle!(id)) + end + + defp apply_action(socket, :new, _params) do + socket + |> assign(:page_title, "New Cycle") + |> assign(:cycle, %Cycle{}) + end + + defp apply_action(socket, :index, _params) do + socket + |> assign(:page_title, "Listing School cycles") + |> assign(:cycle, nil) + end + + @impl true + def handle_info({LantternWeb.Admin.CycleLive.FormComponent, {:saved, cycle}}, socket) do + {:noreply, stream_insert(socket, :school_cycles, cycle)} + end + + @impl true + def handle_event("delete", %{"id" => id}, socket) do + cycle = Schools.get_cycle!(id) + {:ok, _} = Schools.delete_cycle(cycle) + + {:noreply, stream_delete(socket, :school_cycles, cycle)} + end +end diff --git a/lib/lanttern_web/live/admin/cycle_live/index.html.heex b/lib/lanttern_web/live/admin/cycle_live/index.html.heex new file mode 100644 index 00000000..1086f96c --- /dev/null +++ b/lib/lanttern_web/live/admin/cycle_live/index.html.heex @@ -0,0 +1,48 @@ +<.header> + Listing School cycles + <:actions> + <.link patch={~p"/admin/school_cycles/new"}> + <.button>New Cycle + + + + +<.table + id="school_cycles" + rows={@streams.school_cycles} + row_click={fn {_id, cycle} -> JS.navigate(~p"/admin/school_cycles/#{cycle}") end} +> + <:col :let={{_id, cycle}} label="Name"><%= cycle.name %> + <:col :let={{_id, cycle}} label="Start at"><%= cycle.start_at %> + <:col :let={{_id, cycle}} label="End at"><%= cycle.end_at %> + <:action :let={{_id, cycle}}> +
+ <.link navigate={~p"/admin/school_cycles/#{cycle}"}>Show +
+ <.link patch={~p"/admin/school_cycles/#{cycle}/edit"}>Edit + + <:action :let={{id, cycle}}> + <.link + phx-click={JS.push("delete", value: %{id: cycle.id}) |> hide("##{id}")} + data-confirm="Are you sure?" + > + Delete + + + + +<.modal + :if={@live_action in [:new, :edit]} + id="cycle-modal" + show + on_cancel={JS.patch(~p"/admin/school_cycles")} +> + <.live_component + module={LantternWeb.Admin.CycleLive.FormComponent} + id={@cycle.id || :new} + title={@page_title} + action={@live_action} + cycle={@cycle} + patch={~p"/admin/school_cycles"} + /> + diff --git a/lib/lanttern_web/live/admin/cycle_live/show.ex b/lib/lanttern_web/live/admin/cycle_live/show.ex new file mode 100644 index 00000000..92a71606 --- /dev/null +++ b/lib/lanttern_web/live/admin/cycle_live/show.ex @@ -0,0 +1,21 @@ +defmodule LantternWeb.Admin.CycleLive.Show do + use LantternWeb, {:live_view, layout: :admin} + + alias Lanttern.Schools + + @impl true + def mount(_params, _session, socket) do + {:ok, socket} + end + + @impl true + def handle_params(%{"id" => id}, _, socket) do + {:noreply, + socket + |> assign(:page_title, page_title(socket.assigns.live_action)) + |> assign(:cycle, Schools.get_cycle!(id))} + end + + defp page_title(:show), do: "Show Cycle" + defp page_title(:edit), do: "Edit Cycle" +end diff --git a/lib/lanttern_web/live/admin/cycle_live/show.html.heex b/lib/lanttern_web/live/admin/cycle_live/show.html.heex new file mode 100644 index 00000000..0cafe2ef --- /dev/null +++ b/lib/lanttern_web/live/admin/cycle_live/show.html.heex @@ -0,0 +1,33 @@ +<.header> + Cycle <%= @cycle.id %> + <:subtitle>This is a cycle record from your database. + <:actions> + <.link patch={~p"/admin/school_cycles/#{@cycle}/show/edit"} phx-click={JS.push_focus()}> + <.button>Edit cycle + + + + +<.list> + <:item title="Name"><%= @cycle.name %> + <:item title="Start at"><%= @cycle.start_at %> + <:item title="End at"><%= @cycle.end_at %> + + +<.back navigate={~p"/admin/school_cycles"}>Back to school_cycles + +<.modal + :if={@live_action == :edit} + id="cycle-modal" + show + on_cancel={JS.patch(~p"/admin/school_cycles/#{@cycle}")} +> + <.live_component + module={LantternWeb.Admin.CycleLive.FormComponent} + id={@cycle.id} + title={@page_title} + action={@live_action} + cycle={@cycle} + patch={~p"/admin/school_cycles/#{@cycle}"} + /> + diff --git a/lib/lanttern_web/router.ex b/lib/lanttern_web/router.ex index dcfbcfc3..62d86f20 100644 --- a/lib/lanttern_web/router.ex +++ b/lib/lanttern_web/router.ex @@ -104,9 +104,17 @@ defmodule LantternWeb.Router do resources "/classes", ClassController resources "/students", StudentController resources "/teachers", TeacherController + live "/import_students", Admin.SchoolLive.ImportStudents live "/import_teachers", Admin.SchoolLive.ImportTeachers + live "/school_cycles", Admin.CycleLive.Index, :index + live "/school_cycles/new", Admin.CycleLive.Index, :new + + live "/school_cycles/:id/edit", Admin.CycleLive.Index, :edit + live "/school_cycles/:id", Admin.CycleLive.Show, :show + live "/school_cycles/:id/show/edit", Admin.CycleLive.Show, :edit + # Taxonomy context resources "/subjects", SubjectController resources "/years", YearController diff --git a/priv/repo/migrations/20231110160629_create_school_cycles.exs b/priv/repo/migrations/20231110160629_create_school_cycles.exs new file mode 100644 index 00000000..2b57043d --- /dev/null +++ b/priv/repo/migrations/20231110160629_create_school_cycles.exs @@ -0,0 +1,22 @@ +defmodule Lanttern.Repo.Migrations.CreateSchoolCycles do + use Ecto.Migration + + def change do + create table(:school_cycles) do + add :name, :text, null: false + add :start_at, :date, null: false + add :end_at, :date, null: false + add :school_id, references(:schools, on_delete: :delete_all), null: false + + timestamps() + end + + create index(:school_cycles, [:school_id]) + + create constraint( + :school_cycles, + :cycle_end_date_is_greater_than_start_date, + check: "start_at < end_at" + ) + end +end diff --git a/test/lanttern/schools_test.exs b/test/lanttern/schools_test.exs index c80ff5ed..22ce700d 100644 --- a/test/lanttern/schools_test.exs +++ b/test/lanttern/schools_test.exs @@ -598,4 +598,74 @@ defmodule Lanttern.SchoolsTest do |> Lanttern.Repo.one!() end end + + describe "school_cycles" do + alias Lanttern.Schools.Cycle + + import Lanttern.SchoolsFixtures + + @invalid_attrs %{name: nil, start_at: nil, end_at: nil} + + test "list_school_cycles/0 returns all school_cycles" do + cycle = cycle_fixture() + assert Schools.list_school_cycles() == [cycle] + end + + test "get_cycle!/1 returns the cycle with given id" do + cycle = cycle_fixture() + assert Schools.get_cycle!(cycle.id) == cycle + end + + test "create_cycle/1 with valid data creates a cycle" do + school = school_fixture() + + valid_attrs = %{ + name: "some name", + start_at: ~D[2023-11-09], + end_at: ~D[2023-12-09], + school_id: school.id + } + + assert {:ok, %Cycle{} = cycle} = Schools.create_cycle(valid_attrs) + assert cycle.name == "some name" + assert cycle.start_at == ~D[2023-11-09] + assert cycle.end_at == ~D[2023-12-09] + end + + test "create_cycle/1 with invalid data returns error changeset" do + assert {:error, %Ecto.Changeset{}} = Schools.create_cycle(@invalid_attrs) + end + + test "update_cycle/2 with valid data updates the cycle" do + cycle = cycle_fixture() + + update_attrs = %{ + name: "some updated name", + start_at: ~D[2023-11-10], + end_at: ~D[2023-12-10] + } + + assert {:ok, %Cycle{} = cycle} = Schools.update_cycle(cycle, update_attrs) + assert cycle.name == "some updated name" + assert cycle.start_at == ~D[2023-11-10] + assert cycle.end_at == ~D[2023-12-10] + end + + test "update_cycle/2 with invalid data returns error changeset" do + cycle = cycle_fixture() + assert {:error, %Ecto.Changeset{}} = Schools.update_cycle(cycle, @invalid_attrs) + assert cycle == Schools.get_cycle!(cycle.id) + end + + test "delete_cycle/1 deletes the cycle" do + cycle = cycle_fixture() + assert {:ok, %Cycle{}} = Schools.delete_cycle(cycle) + assert_raise Ecto.NoResultsError, fn -> Schools.get_cycle!(cycle.id) end + end + + test "change_cycle/1 returns a cycle changeset" do + cycle = cycle_fixture() + assert %Ecto.Changeset{} = Schools.change_cycle(cycle) + end + end end diff --git a/test/lanttern_web/live/admin/cycle_live_test.exs b/test/lanttern_web/live/admin/cycle_live_test.exs new file mode 100644 index 00000000..3cf65ae5 --- /dev/null +++ b/test/lanttern_web/live/admin/cycle_live_test.exs @@ -0,0 +1,140 @@ +defmodule LantternWeb.Admin.CycleLiveTest do + use LantternWeb.ConnCase + + import Phoenix.LiveViewTest + import Lanttern.SchoolsFixtures + + @invalid_attrs %{name: nil, start_at: nil, end_at: nil} + + defp create_cycle(_) do + cycle = cycle_fixture() + %{cycle: cycle} + end + + setup :register_and_log_in_root_admin + + describe "Index" do + setup [:create_cycle] + + test "lists all school_cycles", %{conn: conn, cycle: cycle} do + {:ok, _index_live, html} = live(conn, ~p"/admin/school_cycles") + + assert html =~ "Listing School cycles" + assert html =~ cycle.name + end + + test "saves new cycle", %{conn: conn} do + school = school_fixture() + + create_attrs = %{ + name: "some name", + start_at: "2023-11-09", + end_at: "2023-12-09", + school_id: school.id + } + + {:ok, index_live, _html} = live(conn, ~p"/admin/school_cycles") + + assert index_live |> element("a", "New Cycle") |> render_click() =~ + "New Cycle" + + assert_patch(index_live, ~p"/admin/school_cycles/new") + + assert index_live + |> form("#cycle-form", cycle: @invalid_attrs) + |> render_change() =~ "can't be blank" + + assert index_live + |> form("#cycle-form", cycle: create_attrs) + |> render_submit() + + assert_patch(index_live, ~p"/admin/school_cycles") + + html = render(index_live) + assert html =~ "Cycle created successfully" + assert html =~ "some name" + end + + test "updates cycle in listing", %{conn: conn, cycle: cycle} do + school = school_fixture() + + update_attrs = %{ + name: "some updated name", + start_at: "2023-11-10", + end_at: "2023-12-10", + school_id: school.id + } + + {:ok, index_live, _html} = live(conn, ~p"/admin/school_cycles") + + assert index_live |> element("#school_cycles-#{cycle.id} a", "Edit") |> render_click() =~ + "Edit Cycle" + + assert_patch(index_live, ~p"/admin/school_cycles/#{cycle}/edit") + + assert index_live + |> form("#cycle-form", cycle: @invalid_attrs) + |> render_change() =~ "can't be blank" + + assert index_live + |> form("#cycle-form", cycle: update_attrs) + |> render_submit() + + assert_patch(index_live, ~p"/admin/school_cycles") + + html = render(index_live) + assert html =~ "Cycle updated successfully" + assert html =~ "some updated name" + end + + test "deletes cycle in listing", %{conn: conn, cycle: cycle} do + {:ok, index_live, _html} = live(conn, ~p"/admin/school_cycles") + + assert index_live |> element("#school_cycles-#{cycle.id} a", "Delete") |> render_click() + refute has_element?(index_live, "#school_cycles-#{cycle.id}") + end + end + + describe "Show" do + setup [:create_cycle] + + test "displays cycle", %{conn: conn, cycle: cycle} do + {:ok, _show_live, html} = live(conn, ~p"/admin/school_cycles/#{cycle}") + + assert html =~ "Show Cycle" + assert html =~ cycle.name + end + + test "updates cycle within modal", %{conn: conn, cycle: cycle} do + school = school_fixture() + + update_attrs = %{ + name: "some updated name", + start_at: "2023-11-10", + end_at: "2023-12-10", + school_id: school.id + } + + {:ok, show_live, _html} = live(conn, ~p"/admin/school_cycles/#{cycle}") + + assert show_live |> element("a", "Edit") |> render_click() =~ + "Edit Cycle" + + assert_patch(show_live, ~p"/admin/school_cycles/#{cycle}/show/edit") + + assert show_live + |> form("#cycle-form", cycle: @invalid_attrs) + |> render_change() =~ "can't be blank" + + assert show_live + |> form("#cycle-form", cycle: update_attrs) + |> render_submit() + + assert_patch(show_live, ~p"/admin/school_cycles/#{cycle}") + + html = render(show_live) + assert html =~ "Cycle updated successfully" + assert html =~ "some updated name" + end + end +end diff --git a/test/support/fixtures/schools_fixtures.ex b/test/support/fixtures/schools_fixtures.ex index b6550d69..1f54a1dd 100644 --- a/test/support/fixtures/schools_fixtures.ex +++ b/test/support/fixtures/schools_fixtures.ex @@ -21,12 +21,11 @@ defmodule Lanttern.SchoolsFixtures do @doc """ Generate a class. """ - def class_fixture(attrs \\ %{}) - - def class_fixture(%{school_id: _school_id} = attrs) do + def class_fixture(attrs \\ %{}) do {:ok, class} = attrs |> Enum.into(%{ + school_id: school_id(attrs), name: "some class name #{Ecto.UUID.generate()}" }) |> Lanttern.Schools.create_class() @@ -34,29 +33,14 @@ defmodule Lanttern.SchoolsFixtures do class end - def class_fixture(attrs) do - school = school_fixture() - - {:ok, class} = - attrs - |> Enum.into(%{ - school_id: school.id, - name: "some class name" - }) - |> Lanttern.Schools.create_class() - - class - end - @doc """ Generate a student. """ - def student_fixture(attrs \\ %{}) - - def student_fixture(%{school_id: _school_id} = attrs) do + def student_fixture(attrs \\ %{}) do {:ok, student} = attrs |> Enum.into(%{ + school_id: school_id(attrs), name: "some full name #{Ecto.UUID.generate()}" }) |> Lanttern.Schools.create_student() @@ -64,29 +48,14 @@ defmodule Lanttern.SchoolsFixtures do student end - def student_fixture(attrs) do - school = school_fixture() - - {:ok, student} = - attrs - |> Enum.into(%{ - name: "some full name #{Ecto.UUID.generate()}", - school_id: school.id - }) - |> Lanttern.Schools.create_student() - - student - end - @doc """ Generate a teacher. """ - def teacher_fixture(attrs \\ %{}) - - def teacher_fixture(%{school_id: _school_id} = attrs) do + def teacher_fixture(attrs \\ %{}) do {:ok, teacher} = attrs |> Enum.into(%{ + school_id: school_id(attrs), name: "some full name #{Ecto.UUID.generate()}" }) |> Lanttern.Schools.create_teacher() @@ -94,17 +63,28 @@ defmodule Lanttern.SchoolsFixtures do teacher end - def teacher_fixture(attrs) do - school = school_fixture() - - {:ok, teacher} = + @doc """ + Generate a cycle. + """ + def cycle_fixture(attrs \\ %{}) do + {:ok, cycle} = attrs |> Enum.into(%{ - name: "some full name #{Ecto.UUID.generate()}", - school_id: school.id + school_id: school_id(attrs), + name: "some name", + start_at: ~D[2023-11-09], + end_at: ~D[2024-11-09] }) - |> Lanttern.Schools.create_teacher() + |> Lanttern.Schools.create_cycle() - teacher + cycle end + + # helpers + + defp school_id(%{school_id: school_id} = _attrs), + do: school_id + + defp school_id(_attrs), + do: school_fixture().id end