defmodule Microwaveprop.RoverPlanning.Path do @moduledoc """ A computed (or pending) path-profile result for one rover-location → station pairing inside a mission. `result` holds the same shape produced by `MicrowavepropWeb.PathLive`'s synchronous compute, so the show page can render it identically. """ use Ecto.Schema import Ecto.Changeset alias Microwaveprop.Rover.Location alias Microwaveprop.RoverPlanning.Mission alias Microwaveprop.RoverPlanning.Station @statuses [:pending, :computing, :complete, :failed] @primary_key {:id, :binary_id, autogenerate: true} @foreign_key_type :binary_id schema "rover_mission_paths" do field :band_mhz, :integer field :status, Ecto.Enum, values: @statuses, default: :pending field :result, :map field :error, :string field :computed_at, :utc_datetime belongs_to :mission, Mission belongs_to :rover_location, Location belongs_to :station, Station timestamps(type: :utc_datetime) end @type t :: %__MODULE__{} @spec statuses() :: [atom()] def statuses, do: @statuses @spec changeset(t() | Ecto.Changeset.t(), map()) :: Ecto.Changeset.t() def changeset(path, attrs) do path |> cast(attrs, [ :band_mhz, :status, :result, :error, :computed_at, :mission_id, :rover_location_id, :station_id ]) |> validate_required([:mission_id, :rover_location_id, :station_id, :band_mhz, :status]) |> validate_inclusion(:status, @statuses) |> validate_number(:band_mhz, greater_than: 0) |> unique_constraint([:mission_id, :rover_location_id, :station_id, :band_mhz], name: :rover_mission_paths_unique ) end end