Skip to content

Commit db056dd

Browse files
authored
feat: events (#52)
1 parent 88dc091 commit db056dd

16 files changed

+1054
-0
lines changed

lib/atlas/events.ex

Lines changed: 317 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,317 @@
1+
defmodule Atlas.Events do
2+
@moduledoc """
3+
The Events context.
4+
"""
5+
6+
import Ecto.Query, warn: false
7+
alias Atlas.Repo
8+
9+
alias Atlas.Events.{Event, EventCategory, UserEventCategory}
10+
11+
@doc """
12+
Returns the list of event_categories.
13+
14+
## Examples
15+
16+
iex> list_event_categories()
17+
[%EventCategory{}, ...]
18+
19+
"""
20+
def list_event_categories do
21+
EventCategory
22+
|> preload(:course)
23+
|> Repo.all()
24+
end
25+
26+
@doc """
27+
Returns the list of event categories selected by a user.
28+
29+
## Examples
30+
31+
iex> list_event_categories_by_user(user_id)
32+
[%EventCategory{}, ...]
33+
34+
"""
35+
def list_event_categories_by_user(user_id) do
36+
EventCategory
37+
|> join(:left, [ec], uec in assoc(ec, :users_event_categories))
38+
|> where([ec, uec], uec.user_id == ^user_id or ec.type == :mandatory)
39+
|> preload(:course)
40+
|> Repo.all()
41+
end
42+
43+
@doc """
44+
Updates the event categories selected by a user.
45+
46+
## Examples
47+
iex> update_event_categories_for_user(user_id, category_ids)
48+
{:ok, [%UserEventCategory{}, ...]}
49+
50+
iex> update_event_categories_for_user(user_id, bad_category_ids)
51+
{:error, %Ecto.Changeset{}}
52+
"""
53+
def update_event_categories_for_user(user_id, category_ids) do
54+
Ecto.Multi.new()
55+
|> Ecto.Multi.delete_all(
56+
:delete_all,
57+
UserEventCategory
58+
|> where([uec], uec.user_id == ^user_id)
59+
)
60+
|> Ecto.Multi.run(:insert_all, fn repo, _changes ->
61+
insert_user_event_categories(repo, user_id, category_ids)
62+
end)
63+
|> Repo.transact()
64+
end
65+
66+
defp insert_user_event_categories(repo, user_id, category_ids) do
67+
category_ids
68+
|> Enum.reduce_while({:ok, []}, fn category_id, {:ok, acc} ->
69+
case repo.get(EventCategory, category_id) do
70+
nil ->
71+
{:halt, {:error, "EventCategory not found: #{category_id}"}}
72+
73+
%EventCategory{type: :mandatory} ->
74+
{:cont, {:ok, acc}}
75+
76+
_category ->
77+
insert_user_event_category(repo, user_id, category_id, acc)
78+
end
79+
end)
80+
end
81+
82+
defp insert_user_event_category(repo, user_id, category_id, acc) do
83+
%UserEventCategory{}
84+
|> UserEventCategory.changeset(%{user_id: user_id, event_category_id: category_id})
85+
|> repo.insert()
86+
|> case do
87+
{:ok, user_event_category} -> {:cont, {:ok, [user_event_category | acc]}}
88+
{:error, changeset} -> {:halt, {:error, changeset}}
89+
end
90+
end
91+
92+
@doc """
93+
Gets a single event_category.
94+
95+
Raises `Ecto.NoResultsError` if the Event category does not exist.
96+
97+
## Examples
98+
99+
iex> get_event_category!(123)
100+
%EventCategory{}
101+
102+
iex> get_event_category!(456)
103+
** (Ecto.NoResultsError)
104+
105+
"""
106+
def get_event_category!(id) do
107+
EventCategory
108+
|> preload(:course)
109+
|> Repo.get!(id)
110+
end
111+
112+
@doc """
113+
Creates a event_category.
114+
115+
## Examples
116+
117+
iex> create_event_category(%{field: value})
118+
{:ok, %EventCategory{}}
119+
120+
iex> create_event_category(%{field: bad_value})
121+
{:error, %Ecto.Changeset{}}
122+
123+
"""
124+
def create_event_category(attrs \\ %{}) do
125+
%EventCategory{}
126+
|> EventCategory.changeset(attrs)
127+
|> Repo.insert()
128+
|> case do
129+
{:ok, event_category} -> {:ok, Repo.preload(event_category, :course)}
130+
{:error, changeset} -> {:error, changeset}
131+
end
132+
end
133+
134+
@doc """
135+
Updates a event_category.
136+
137+
## Examples
138+
139+
iex> update_event_category(event_category, %{field: new_value})
140+
{:ok, %EventCategory{}}
141+
142+
iex> update_event_category(event_category, %{field: bad_value})
143+
{:error, %Ecto.Changeset{}}
144+
145+
"""
146+
def update_event_category(%EventCategory{} = event_category, attrs) do
147+
event_category
148+
|> EventCategory.changeset(attrs)
149+
|> Repo.update()
150+
|> case do
151+
{:ok, event_category} -> {:ok, Repo.preload(event_category, :course)}
152+
{:error, changeset} -> {:error, changeset}
153+
end
154+
end
155+
156+
@doc """
157+
Deletes a event_category.
158+
159+
## Examples
160+
161+
iex> delete_event_category(event_category)
162+
{:ok, %EventCategory{}}
163+
164+
iex> delete_event_category(event_category)
165+
{:error, %Ecto.Changeset{}}
166+
167+
"""
168+
def delete_event_category(%EventCategory{} = event_category) do
169+
Repo.delete(event_category)
170+
|> case do
171+
{:ok, event_category} -> {:ok, Repo.preload(event_category, :course)}
172+
{:error, changeset} -> {:error, changeset}
173+
end
174+
end
175+
176+
@doc """
177+
Returns an `%Ecto.Changeset{}` for tracking event_category changes.
178+
179+
## Examples
180+
181+
iex> change_event_category(event_category)
182+
%Ecto.Changeset{data: %EventCategory{}}
183+
184+
"""
185+
def change_event_category(%EventCategory{} = event_category, attrs \\ %{}) do
186+
EventCategory.changeset(event_category, attrs)
187+
end
188+
189+
@doc """
190+
Returns the list of events.
191+
192+
## Examples
193+
194+
iex> list_events()
195+
[%Event{}, ...]
196+
197+
"""
198+
def list_events do
199+
Event
200+
|> preload(category: :course)
201+
|> Repo.all()
202+
end
203+
204+
@doc """
205+
Returns the list of events for a specific user.
206+
207+
## Examples
208+
209+
iex> list_events_by_user(user_id)
210+
[%Event{}, ...]
211+
"""
212+
def list_events_by_user(user_id) do
213+
Event
214+
|> join(:inner, [e], ec in assoc(e, :category))
215+
|> join(:left, [e, ec], uec in assoc(ec, :users_event_categories))
216+
|> where([e, ec, uec], uec.user_id == ^user_id or ec.type == :mandatory)
217+
|> preload(category: :course)
218+
|> Repo.all()
219+
end
220+
221+
@doc """
222+
Gets a single event.
223+
224+
Raises `Ecto.NoResultsError` if the Event does not exist.
225+
226+
## Examples
227+
228+
iex> get_event!(123)
229+
%Event{}
230+
231+
iex> get_event!(456)
232+
** (Ecto.NoResultsError)
233+
234+
"""
235+
def get_event!(id) do
236+
Event
237+
|> preload(category: :course)
238+
|> Repo.get!(id)
239+
end
240+
241+
@doc """
242+
Creates a event.
243+
244+
## Examples
245+
246+
iex> create_event(%{field: value})
247+
{:ok, %Event{}}
248+
249+
iex> create_event(%{field: bad_value})
250+
{:error, %Ecto.Changeset{}}
251+
252+
"""
253+
def create_event(attrs \\ %{}) do
254+
%Event{}
255+
|> Event.changeset(attrs)
256+
|> Repo.insert()
257+
|> case do
258+
{:ok, event} -> {:ok, Repo.preload(event, category: :course)}
259+
{:error, changeset} -> {:error, changeset}
260+
end
261+
end
262+
263+
@doc """
264+
Updates a event.
265+
266+
## Examples
267+
268+
iex> update_event(event, %{field: new_value})
269+
{:ok, %Event{}}
270+
271+
iex> update_event(event, %{field: bad_value})
272+
{:error, %Ecto.Changeset{}}
273+
274+
"""
275+
def update_event(%Event{} = event, attrs) do
276+
event
277+
|> Event.changeset(attrs)
278+
|> Repo.update()
279+
|> case do
280+
{:ok, event} -> {:ok, Repo.preload(event, category: :course)}
281+
{:error, changeset} -> {:error, changeset}
282+
end
283+
end
284+
285+
@doc """
286+
Deletes a event.
287+
288+
## Examples
289+
290+
iex> delete_event(event)
291+
{:ok, %Event{}}
292+
293+
iex> delete_event(event)
294+
{:error, %Ecto.Changeset{}}
295+
296+
"""
297+
def delete_event(%Event{} = event) do
298+
Repo.delete(event)
299+
|> case do
300+
{:ok, event} -> {:ok, Repo.preload(event, category: :course)}
301+
{:error, changeset} -> {:error, changeset}
302+
end
303+
end
304+
305+
@doc """
306+
Returns an `%Ecto.Changeset{}` for tracking event changes.
307+
308+
## Examples
309+
310+
iex> change_event(event)
311+
%Ecto.Changeset{data: %Event{}}
312+
313+
"""
314+
def change_event(%Event{} = event, attrs \\ %{}) do
315+
Event.changeset(event, attrs)
316+
end
317+
end

lib/atlas/events/event.ex

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
defmodule Atlas.Events.Event do
2+
@moduledoc """
3+
Event schema.
4+
"""
5+
use Atlas.Schema
6+
7+
@required_fields ~w(title start end place link category_id)a
8+
9+
schema "events" do
10+
field :start, :utc_datetime
11+
field :end, :utc_datetime
12+
field :link, :string
13+
field :title, :string
14+
field :place, :string
15+
16+
belongs_to :category, Atlas.Events.EventCategory
17+
18+
timestamps(type: :utc_datetime)
19+
end
20+
21+
@doc false
22+
def changeset(event, attrs) do
23+
event
24+
|> cast(attrs, @required_fields)
25+
|> validate_required(@required_fields)
26+
|> foreign_key_constraint(:category_id)
27+
end
28+
end

lib/atlas/events/event_category.ex

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
defmodule Atlas.Events.EventCategory do
2+
@moduledoc """
3+
Event category schema.
4+
"""
5+
use Atlas.Schema
6+
7+
@types ~w(optional mandatory)a
8+
9+
@required_fields ~w(name color type)a
10+
@optional_fields ~w(course_id)a
11+
12+
schema "event_categories" do
13+
field :name, :string
14+
field :color, :string
15+
field :type, Ecto.Enum, values: @types
16+
17+
belongs_to :course, Atlas.University.Degrees.Courses.Course
18+
19+
has_many :users_event_categories, Atlas.Events.UserEventCategory
20+
21+
timestamps(type: :utc_datetime)
22+
end
23+
24+
@doc false
25+
def changeset(event_category, attrs) do
26+
event_category
27+
|> cast(attrs, @required_fields ++ @optional_fields)
28+
|> validate_required(@required_fields)
29+
end
30+
end

0 commit comments

Comments
 (0)