diff --git a/backend/lib/peach/event.ex b/backend/lib/peach/event.ex index a3d79ed..2ea84f4 100644 --- a/backend/lib/peach/event.ex +++ b/backend/lib/peach/event.ex @@ -28,4 +28,11 @@ defmodule Peach.Event do |> validate_required([:name, :description, :location, :date, :cover, :treasury]) |> validate_format(:treasury, ~r/^0x[0-9a-fA-F]{1,64}$/) end + + def update_changeset(event, attrs) do + event + |> cast(attrs, [:name, :description, :location, :date, :cover, :treasury]) + |> validate_required([:name, :description, :location, :date, :cover, :treasury]) + |> validate_format(:treasury, ~r/^0x[0-9a-fA-F]{1,64}$/) + end end diff --git a/backend/lib/peach/events.ex b/backend/lib/peach/events.ex index 3eacb88..38c3245 100644 --- a/backend/lib/peach/events.ex +++ b/backend/lib/peach/events.ex @@ -1,4 +1,4 @@ -defmodule Events do +defmodule Peach.Events do @moduledoc """ Manages the events for the peach app """ @@ -13,4 +13,70 @@ defmodule Events do |> Event.changeset(event) |> Repo.insert() end + + @doc """ + Updates the `name` field + """ + def update_event_name(event_id, name) do + event = Repo.get!(Event, event_id) + + event + |> Event.update_changeset(%{name: name}) + |> Repo.update() + end + + @doc """ + Updates the `date` field + """ + def update_event_date(event_id, date) do + event = Repo.get!(Event, event_id) + + event + |> Event.update_changeset(%{date: date}) + |> Repo.update() + end + + @doc """ + Updates the `description` field + """ + def update_event_description(event_id, description) do + event = Repo.get!(Event, event_id) + + event + |> Event.update_changeset(%{description: description}) + |> Repo.update() + end + + @doc """ + Updates the `location` field + """ + def update_event_location(event_id, location) do + event = Repo.get!(Event, event_id) + + event + |> Event.update_changeset(%{location: location}) + |> Repo.update() + end + + @doc """ + Updates the `cover` field + """ + def update_event_cover(event_id, cover) do + event = Repo.get!(Event, event_id) + + event + |> Event.update_changeset(%{cover: cover}) + |> Repo.update() + end + + @doc """ + Updates the `treasury` field + """ + def update_event_treasury(event_id, treasury) do + event = Repo.get!(Event, event_id) + + event + |> Event.update_changeset(%{treasury: treasury}) + |> Repo.update() + end end diff --git a/backend/lib/peach_web/controllers/event_controller.ex b/backend/lib/peach_web/controllers/event_controller.ex index f69fc36..0d3ba7b 100644 --- a/backend/lib/peach_web/controllers/event_controller.ex +++ b/backend/lib/peach_web/controllers/event_controller.ex @@ -1,5 +1,6 @@ defmodule PeachWeb.EventController do use PeachWeb, :controller + alias Peach.Events def create(conn, %{"event" => event_params}) do case Events.create_event(event_params) do @@ -19,4 +20,130 @@ defmodule PeachWeb.EventController do |> json(%{errors: errors}) end end + + @doc """ + Updates the name of an event. + """ + def update_event_name(conn, %{"id" => id, "name" => name}) do + case Peach.Events.update_event_name(id, name) do + {:ok, _event} -> + conn + |> put_status(:no_content) + + {:error, changeset} -> + errors = + Ecto.Changeset.traverse_errors(changeset, fn {msg, _opts} -> + Phoenix.Naming.humanize(msg) + end) + + conn + |> put_status(:bad_request) + |> json(%{errors: errors}) + end + end + + @doc """ + Updates the date of an event. + """ + def update_event_date(conn, %{"id" => id, "date" => date}) do + case Events.update_event_cover(id, date) do + {:ok, _event} -> + conn + |> put_status(:no_content) + + {:error, changeset} -> + errors = + Ecto.Changeset.traverse_errors(changeset, fn {msg, _opts} -> + Phoenix.Naming.humanize(msg) + end) + + conn + |> put_status(:bad_request) + |> json(%{errors: errors}) + end + end + + @doc """ + Updates the description of an event. + """ + def update_event_description(conn, %{"id" => id, "description" => description}) do + case Events.update_event_description(id, description) do + {:ok, _event} -> + conn + |> put_status(:no_content) + + {:error, changeset} -> + errors = + Ecto.Changeset.traverse_errors(changeset, fn {msg, _opts} -> + Phoenix.Naming.humanize(msg) + end) + + conn + |> put_status(:bad_request) + |> json(%{errors: errors}) + end + end + + @doc """ + Updates the location of an event. + """ + def update_event_location(conn, %{"id" => id, "location" => location}) do + case Events.update_event_location(id, location) do + {:ok, _event} -> + conn + |> put_status(:no_content) + + {:error, changeset} -> + errors = + Ecto.Changeset.traverse_errors(changeset, fn {msg, _opts} -> + Phoenix.Naming.humanize(msg) + end) + + conn + |> put_status(:bad_request) + |> json(%{errors: errors}) + end + end + + @doc """ + Updates the cover of an event. + """ + def update_event_cover(conn, %{"id" => id, "cover" => cover}) do + case Events.update_event_cover(id, cover) do + {:ok, _event} -> + conn + |> put_status(:no_content) + + {:error, changeset} -> + errors = + Ecto.Changeset.traverse_errors(changeset, fn {msg, _opts} -> + Phoenix.Naming.humanize(msg) + end) + + conn + |> put_status(:bad_request) + |> json(%{errors: errors}) + end + end + + @doc """ + Updates the treasury of an event. + """ + def update_event_treasury(conn, %{"id" => id, "treasury" => treasury}) do + case Events.update_event_treasury(id, treasury) do + {:ok, _event} -> + conn + |> put_status(:no_content) + + {:error, changeset} -> + errors = + Ecto.Changeset.traverse_errors(changeset, fn {msg, _opts} -> + Phoenix.Naming.humanize(msg) + end) + + conn + |> put_status(:bad_request) + |> json(%{errors: errors}) + end + end end diff --git a/backend/lib/peach_web/router.ex b/backend/lib/peach_web/router.ex index 9e685bf..4926cae 100644 --- a/backend/lib/peach_web/router.ex +++ b/backend/lib/peach_web/router.ex @@ -7,7 +7,12 @@ defmodule PeachWeb.Router do scope "/api", PeachWeb do pipe_through(:api) - post "/create_event", EventController, :create + post "/events/create", EventController, :create + patch "/events/:id/name", EventController, :update_event_name + patch "/events/:id/description", EventController, :update_event_description + patch "/events/:id/location", EventController, :update_event_location + patch "/events/:id/cover", EventController, :update_event_cover + patch "/events/:id/treasury", EventController, :update_event_treasury end # Enable LiveDashboard and Swoosh mailbox preview in development diff --git a/backend/test/peach/events/event_db_setters_test.exs b/backend/test/peach/events/event_db_setters_test.exs new file mode 100644 index 0000000..0a3fe87 --- /dev/null +++ b/backend/test/peach/events/event_db_setters_test.exs @@ -0,0 +1,82 @@ +defmodule Peach.Events.EventDBSettersTest do + use Peach.DataCase, async: true + + alias Peach.Event + alias Peach.Events + alias Peach.Repo + + setup do + # Create an initial event record for testing + {:ok, event} = + Repo.insert(%Event{ + name: "Original Name", + date: ~N[2024-01-01 10:00:00], + description: "Original description", + location: "Original location", + cover: "https://example.com/original_cover.jpg", + onchain: false, + treasury: "0xdead" + }) + + {:ok, event: event} + end + + test "updates name in the database", %{event: event} do + updated_name = "Updated Name" + Events.update_event_name(event.id, updated_name) + updated_event = Repo.get!(Event, event.id) + assert updated_event.name == updated_name + Events.update_event_name(event.id, 1) + updated_event = Repo.get!(Event, event.id) + assert updated_event.name == updated_name + end + + test "updates date in the database", %{event: event} do + new_date = ~N[2025-12-31 23:59:59] + Events.update_event_date(event.id, new_date) + updated_event = Repo.get!(Event, event.id) + assert updated_event.date == new_date + Events.update_event_date(event.id, 1) + updated_event = Repo.get!(Event, event.id) + assert updated_event.date == new_date + end + + test "updates description in the database", %{event: event} do + updated_description = "Updated description" + Events.update_event_description(event.id, updated_description) + updated_event = Repo.get!(Event, event.id) + assert updated_event.description == updated_description + Events.update_event_description(event.id, 1) + updated_event = Repo.get!(Event, event.id) + assert updated_event.description == updated_description + end + + test "updates location in the database", %{event: event} do + updated_location = "Updated location" + Events.update_event_location(event.id, updated_location) + updated_event = Repo.get!(Event, event.id) + assert updated_event.location == updated_location + Events.update_event_location(event.id, 1) + updated_event = Repo.get!(Event, event.id) + assert updated_event.location == updated_location + end + + test "updates cover in the database", %{event: event} do + updated_cover = "https://example.com/updated_cover.jpg" + Events.update_event_cover(event.id, updated_cover) + updated_event = Repo.get!(Event, event.id) + assert updated_event.cover == updated_cover + Events.update_event_cover(event.id, 1) + updated_event = Repo.get!(Event, event.id) + assert updated_event.cover == updated_cover + end + + test "updates treasury in the database", %{event: event} do + updated_treasury = "0xbeef" + Events.update_event_treasury(event.id, updated_treasury) + updated_event = Repo.get!(Event, event.id) + assert updated_event.treasury == updated_treasury + Events.update_event_treasury(event.id, "beef") + assert updated_event.treasury == updated_treasury + end +end diff --git a/backend/test/peach_web/controllers/create_event_test.exs b/backend/test/peach_web/controllers/create_event_test.exs index 836a3b2..ebc769e 100644 --- a/backend/test/peach_web/controllers/create_event_test.exs +++ b/backend/test/peach_web/controllers/create_event_test.exs @@ -1,4 +1,4 @@ -defmodule PeachWeb.EventControllerTest do +defmodule PeachWeb.EventCreateControllerTest do use PeachWeb.ConnCase, async: true import Ecto.Query @@ -29,7 +29,7 @@ defmodule PeachWeb.EventControllerTest do } test "creates an event with ticket tiers", %{conn: conn} do - conn = post(conn, "/api/create_event", %{"event" => @valid_event_attrs}) + conn = post(conn, "/api/events/create", %{"event" => @valid_event_attrs}) # Assert response status assert json_response(conn, 201)["message"] == "Event created successfully" @@ -57,14 +57,14 @@ defmodule PeachWeb.EventControllerTest do # Remove one required field at a time invalid_attrs = Map.drop(@valid_event_attrs, [field]) - conn = post(conn, "/api/create_event", %{"event" => invalid_attrs}) + conn = post(conn, "/api/events/create", %{"event" => invalid_attrs}) assert json_response(conn, 422)["errors"][field] == ["Can't be blank"] end) # Test with an empty ticket tier list empty_tiers = Map.replace(@valid_event_attrs, "ticket_tiers", []) - conn = post(conn, "/api/create_event", %{"event" => empty_tiers}) + conn = post(conn, "/api/events/create", %{"event" => empty_tiers}) assert json_response(conn, 422)["errors"]["ticket_tiers"] == ["Can't be blank"] end @@ -85,7 +85,7 @@ defmodule PeachWeb.EventControllerTest do Map.replace(@valid_event_attrs, field, true) end - conn = post(conn, "/api/create_event", %{"event" => invalid_attrs}) + conn = post(conn, "/api/events/create", %{"event" => invalid_attrs}) assert json_response(conn, 422)["errors"][field] == ["Is invalid"] end) @@ -94,7 +94,7 @@ defmodule PeachWeb.EventControllerTest do invalid_address_format = Map.replace(@valid_event_attrs, "treasury", "Some string that is not a starknet address") - conn = post(conn, "/api/create_event", %{"event" => invalid_address_format}) + conn = post(conn, "/api/events/create", %{"event" => invalid_address_format}) assert json_response(conn, 422)["errors"]["treasury"] == ["Has invalid format"] end diff --git a/backend/test/peach_web/controllers/update_event_test.exs b/backend/test/peach_web/controllers/update_event_test.exs new file mode 100644 index 0000000..f447264 --- /dev/null +++ b/backend/test/peach_web/controllers/update_event_test.exs @@ -0,0 +1,78 @@ +defmodule PeachWeb.EventUpdateControllertest do + use PeachWeb.ConnCase, async: true + + alias Peach.Event + alias Peach.Repo + + @original_event %Event{ + name: "Original Name", + date: ~N[2024-01-01 10:00:00], + description: "Original description", + location: "Original location", + cover: "https://example.com/original_cover.jpg", + onchain: false, + treasury: "0xdead" + } + + setup do + # Create an initial event record for testing + {:ok, event} = + Repo.insert(@original_event) + + {:ok, event: event} + end + + test "updates the event fields", %{conn: conn} do + updated_fields = [ + {"name", "Updated name"}, + {"description", "Updated description"}, + {"location", "Updated location"}, + {"treasury", "0xbeef"}, + {"cover", "https://example.com/updated_cover.jpg"} + ] + + expected_event = @original_event + + Enum.reduce(updated_fields, expected_event, fn {field, value}, acc -> + conn = patch(conn, "/api/events/1/#{field}", %{"#{field}" => value}) + acc = Map.replace(acc, String.to_atom(field), value) + + # Assert response status + assert conn.status == 204 + event = Repo.get_by(Event, id: 1) + assert event + assert event.name == acc.name + assert event.description == acc.description + assert event.location == acc.location + assert event.cover == acc.cover + assert not event.onchain + acc + end) + end + + test "fail to update the event fields", %{conn: conn} do + updated_fields = [ + {"name", 1}, + {"description", 2}, + {"location", 3}, + {"treasury", "wrong treasury format"}, + {"cover", 4} + ] + + expected_event = @original_event + + Enum.each(updated_fields, fn {field, value} -> + conn = patch(conn, "/api/events/1/#{field}", %{"#{field}" => value}) + + # Assert response status + assert conn.status == 400 + event = Repo.get_by(Event, id: 1) + assert event + assert event.name == expected_event.name + assert event.description == expected_event.description + assert event.location == expected_event.location + assert event.cover == expected_event.cover + assert not event.onchain + end) + end +end