diff --git a/lib/arrow/disruptions/limit.ex b/lib/arrow/disruptions/limit.ex index 294979b20..58b1f3ef2 100644 --- a/lib/arrow/disruptions/limit.ex +++ b/lib/arrow/disruptions/limit.ex @@ -44,7 +44,7 @@ defmodule Arrow.Disruptions.Limit do ]) |> put_change(:check_for_overlap, true) |> validate_required([:start_date, :end_date, :route_id, :start_stop_id, :end_stop_id]) - |> validate_start_date_before_end_date() + |> Arrow.Util.Validation.validate_start_date_before_end_date() |> cast_assoc_day_of_weeks() |> exclusion_constraint(:end_date, name: :no_overlap, @@ -73,23 +73,6 @@ defmodule Arrow.Disruptions.Limit do |> struct!(attrs) end - @spec validate_start_date_before_end_date(Ecto.Changeset.t(t())) :: Ecto.Changeset.t(t()) - defp validate_start_date_before_end_date(changeset) do - start_date = get_field(changeset, :start_date) - end_date = get_field(changeset, :end_date) - - cond do - is_nil(start_date) or is_nil(end_date) -> - changeset - - Date.compare(start_date, end_date) == :gt -> - add_error(changeset, :start_date, "start date should not be after end date") - - true -> - changeset - end - end - @spec cast_assoc_day_of_weeks(Ecto.Changeset.t(t())) :: Ecto.Changeset.t(t()) defp cast_assoc_day_of_weeks(changeset) do start_date = get_field(changeset, :start_date) diff --git a/lib/arrow/disruptions/replacement_service.ex b/lib/arrow/disruptions/replacement_service.ex index 2fd406191..b48c43dd4 100644 --- a/lib/arrow/disruptions/replacement_service.ex +++ b/lib/arrow/disruptions/replacement_service.ex @@ -52,28 +52,11 @@ defmodule Arrow.Disruptions.ReplacementService do :disruption_id, :shuttle_id ]) - |> validate_start_date_before_end_date() + |> Arrow.Util.Validation.validate_start_date_before_end_date() |> assoc_constraint(:shuttle) |> assoc_constraint(:disruption) end - @spec validate_start_date_before_end_date(Ecto.Changeset.t(t())) :: Ecto.Changeset.t(t()) - defp validate_start_date_before_end_date(changeset) do - start_date = get_field(changeset, :start_date) - end_date = get_field(changeset, :end_date) - - cond do - is_nil(start_date) or is_nil(end_date) -> - changeset - - Date.compare(start_date, end_date) == :gt -> - add_error(changeset, :start_date, "start date should not be after end date") - - true -> - changeset - end - end - def add_timetable(%__MODULE__{} = replacement_service) do timetable = schedule_service_types() diff --git a/lib/arrow/gtfs/calendar.ex b/lib/arrow/gtfs/calendar.ex index d0ce45da8..696e3f986 100644 --- a/lib/arrow/gtfs/calendar.ex +++ b/lib/arrow/gtfs/calendar.ex @@ -33,18 +33,7 @@ defmodule Arrow.Gtfs.Calendar do ~w[service_id monday tuesday wednesday thursday friday saturday sunday start_date end_date]a ) |> assoc_constraint(:service) - |> validate_start_date_not_after_end_date() - end - - defp validate_start_date_not_after_end_date(changeset) do - start_date = fetch_field!(changeset, :start_date) - end_date = fetch_field!(changeset, :end_date) - - if Date.compare(start_date, end_date) in [:lt, :eq] do - changeset - else - add_error(changeset, :dates, "start date should not be after end date") - end + |> Arrow.Util.Validation.validate_start_date_before_end_date() end @impl Arrow.Gtfs.Importable diff --git a/lib/arrow/gtfs/feed_info.ex b/lib/arrow/gtfs/feed_info.ex index 6f36e6974..f6d792bc3 100644 --- a/lib/arrow/gtfs/feed_info.ex +++ b/lib/arrow/gtfs/feed_info.ex @@ -32,18 +32,7 @@ defmodule Arrow.Gtfs.FeedInfo do |> validate_required( ~w[id publisher_name publisher_url lang start_date end_date version contact_email]a ) - |> validate_start_date_before_end_date() - end - - defp validate_start_date_before_end_date(changeset) do - start_date = fetch_field!(changeset, :start_date) - end_date = fetch_field!(changeset, :end_date) - - if Date.compare(start_date, end_date) == :lt do - changeset - else - add_error(changeset, :dates, "start date should be before end date") - end + |> Arrow.Util.Validation.validate_start_date_before_end_date() end @impl Arrow.Gtfs.Importable diff --git a/lib/arrow/hastus/service_date.ex b/lib/arrow/hastus/service_date.ex index 2d11ab910..764d64e4a 100644 --- a/lib/arrow/hastus/service_date.ex +++ b/lib/arrow/hastus/service_date.ex @@ -17,7 +17,7 @@ defmodule Arrow.Hastus.ServiceDate do service_date |> cast(attrs, [:start_date, :end_date, :service_id]) |> validate_required([:start_date, :end_date]) - |> validate_start_date_before_end_date() + |> Arrow.Util.Validation.validate_start_date_before_end_date() |> assoc_constraint(:service) end @@ -31,21 +31,4 @@ defmodule Arrow.Hastus.ServiceDate do |> Stream.take(7) |> MapSet.new(&Date.day_of_week/1) end - - @spec validate_start_date_before_end_date(Ecto.Changeset.t(t())) :: Ecto.Changeset.t(t()) - defp validate_start_date_before_end_date(changeset) do - start_date = get_field(changeset, :start_date) - end_date = get_field(changeset, :end_date) - - cond do - is_nil(start_date) or is_nil(end_date) -> - changeset - - Date.compare(start_date, end_date) == :gt -> - add_error(changeset, :start_date, "start date must be less than or equal to end date") - - true -> - changeset - end - end end diff --git a/lib/arrow/trainsformer/service.ex b/lib/arrow/trainsformer/service.ex index 46e08bff9..a31539235 100644 --- a/lib/arrow/trainsformer/service.ex +++ b/lib/arrow/trainsformer/service.ex @@ -23,8 +23,12 @@ defmodule Arrow.Trainsformer.Service do def changeset(service, attrs) do service |> cast(attrs, [:name, :export_id]) + |> cast_assoc(:service_dates, + with: &ServiceDate.changeset/2, + sort_param: :service_dates_sort, + drop_param: :service_dates_drop + ) |> validate_required([:name]) - |> cast_assoc(:service_dates, with: &ServiceDate.changeset/2) |> assoc_constraint(:export) end end diff --git a/lib/arrow/trainsformer/service_date.ex b/lib/arrow/trainsformer/service_date.ex index 948db3b90..9d4f4cdf4 100644 --- a/lib/arrow/trainsformer/service_date.ex +++ b/lib/arrow/trainsformer/service_date.ex @@ -6,8 +6,8 @@ defmodule Arrow.Trainsformer.ServiceDate do alias Arrow.Trainsformer.ServiceDateDayOfWeek typed_schema "trainsformer_service_dates" do - field :start_date, :date - field :end_date, :date + field :start_date, :date, default: Date.utc_today() + field :end_date, :date, default: Date.utc_today() belongs_to :service, Arrow.Trainsformer.Service, on_replace: :delete has_many :service_date_days_of_week, ServiceDateDayOfWeek, @@ -39,6 +39,7 @@ defmodule Arrow.Trainsformer.ServiceDate do |> cast(transformed_attrs, [:start_date, :end_date, :service_id]) |> cast_assoc(:service_date_days_of_week, with: &ServiceDateDayOfWeek.changeset/2) |> validate_required([:start_date, :end_date]) + |> Arrow.Util.Validation.validate_start_date_before_end_date() |> assoc_constraint(:service) end end diff --git a/lib/arrow/util/validation.ex b/lib/arrow/util/validation.ex new file mode 100644 index 000000000..fcde4e06c --- /dev/null +++ b/lib/arrow/util/validation.ex @@ -0,0 +1,26 @@ +defmodule Arrow.Util.Validation do + @moduledoc """ + Utilities for validating changesets in Arrow. Note that many these functions make assumptions + about the field names / error messages in your changeset that are specific to this project. + """ + @spec validate_start_date_before_end_date(Ecto.Changeset.t(any())) :: Ecto.Changeset.t(any()) + def validate_start_date_before_end_date(changeset) do + start_date = Ecto.Changeset.get_field(changeset, :start_date) + end_date = Ecto.Changeset.get_field(changeset, :end_date) + + cond do + is_nil(start_date) or is_nil(end_date) -> + changeset + + Date.compare(start_date, end_date) == :gt -> + Ecto.Changeset.add_error( + changeset, + :start_date, + "start date must be less than or equal to end date" + ) + + true -> + changeset + end + end +end diff --git a/lib/arrow_web/components/core_components.ex b/lib/arrow_web/components/core_components.ex index 37e9a98a6..3fdfbf028 100644 --- a/lib/arrow_web/components/core_components.ex +++ b/lib/arrow_web/components/core_components.ex @@ -77,7 +77,7 @@ defmodule ArrowWeb.CoreComponents do