From a69b771847e009d04ba910c29df27a37b64fbac3 Mon Sep 17 00:00:00 2001 From: Joao P Dubas Date: Mon, 28 Jun 2021 00:15:52 +0000 Subject: [PATCH] [extra-01] training has a period validity We move from start/end date to a period date range to represent the interval where a training take place. Besides that, new constraints are added to ensure a trainings of a user can't overlap. These constraints reflect in changeset validation. --- lib/wabanex/training.ex | 10 ++-- .../20210627114504_create_gist_extension.exs | 11 +++++ ...10627114539_alter_trainings_add_period.exs | 46 +++++++++++++++++++ 3 files changed, 62 insertions(+), 5 deletions(-) create mode 100644 priv/repo/migrations/20210627114504_create_gist_extension.exs create mode 100644 priv/repo/migrations/20210627114539_alter_trainings_add_period.exs diff --git a/lib/wabanex/training.ex b/lib/wabanex/training.ex index fd8bca2..ef5e014 100644 --- a/lib/wabanex/training.ex +++ b/lib/wabanex/training.ex @@ -3,17 +3,16 @@ defmodule Wabanex.Training do import Ecto.Changeset + alias PgRanges.DateRange alias Wabanex.{Exercise, User} @primary_key {:id, :binary_id, autogenerate: true} @foreign_key_type :binary_id - @fields [:start_date, :end_date, :user_id] - @required_fields [:start_date, :user_id] + @fields [:period, :user_id] schema "trainings" do - field :start_date, :date - field :end_date, :date + field :period, DateRange, default: DateRange.new(Date.utc_today(), nil) belongs_to :user, User @@ -25,7 +24,8 @@ defmodule Wabanex.Training do def changeset(params) do %__MODULE__{} |> cast(params, @fields) - |> validate_required(@required_fields) + |> validate_required(@fields) + |> exclusion_constraint(:period, name: :non_overlap_period) |> cast_assoc(:exercises) end end diff --git a/priv/repo/migrations/20210627114504_create_gist_extension.exs b/priv/repo/migrations/20210627114504_create_gist_extension.exs new file mode 100644 index 0000000..fa43b3d --- /dev/null +++ b/priv/repo/migrations/20210627114504_create_gist_extension.exs @@ -0,0 +1,11 @@ +defmodule Wabanex.Repo.Migrations.CreateGistExtension do + use Ecto.Migration + + def up do + execute("CREATE EXTENSION IF NOT EXISTS \"btree_gist\";") + end + + def down do + execute("DROP EXTENSION \"btree_gist\";") + end +end diff --git a/priv/repo/migrations/20210627114539_alter_trainings_add_period.exs b/priv/repo/migrations/20210627114539_alter_trainings_add_period.exs new file mode 100644 index 0000000..94fd97e --- /dev/null +++ b/priv/repo/migrations/20210627114539_alter_trainings_add_period.exs @@ -0,0 +1,46 @@ +defmodule Wabanex.Repo.Migrations.AlterTrainingsAddPeriod do + use Ecto.Migration + + def up do + alter table(:trainings) do + add :period, :daterange + end + + execute(""" + update trainings set + period=daterange(start_date, end_date, '[)') + , updated_at=date_trunc('second', current_timestamp::timestamp) + """) + + alter table(:trainings) do + remove :start_date + remove :end_date + modify :period, :daterange, null: false + end + + create constraint(:trainings, :non_overlap_period, + exclude: "gist (user_id WITH =, period with &&)" + ) + end + + def down do + alter table(:trainings) do + add :start_date, :date + add :end_date, :date + end + + execute(""" + update trainings set + start_date=lower(period) + , end_date=upper(period) + , update_at=date_trunc('second', current_timestamp::timestamp) + """) + + drop constraint(:trainings, :non_overlap_period) + + alter table(:trainings) do + remove :period + modify :start_date, :date, null: false + end + end +end