[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.
This commit is contained in:
Joao P Dubas 2021-06-28 00:15:52 +00:00
parent 553eca56df
commit a69b771847
3 changed files with 62 additions and 5 deletions

View File

@ -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

View File

@ -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

View File

@ -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