defmodule ComponentsElixir.Inventory.Category do @moduledoc """ Schema for component categories. Categories can be hierarchical with parent-child relationships. """ use Ecto.Schema import Ecto.Changeset alias ComponentsElixir.Inventory.{Category, Component} schema "categories" do field :name, :string field :description, :string belongs_to :parent, Category has_many :children, Category, foreign_key: :parent_id has_many :components, Component timestamps() end @doc false def changeset(category, attrs) do category |> cast(attrs, [:name, :description, :parent_id]) |> validate_required([:name]) |> validate_length(:name, min: 1, max: 255) |> validate_length(:description, max: 1000) |> unique_constraint([:name, :parent_id]) |> foreign_key_constraint(:parent_id) end @doc """ Returns the full path of the category including parent names. """ def full_path(%Category{parent: nil} = category), do: category.name def full_path(%Category{parent: %Category{} = parent} = category) do "#{full_path(parent)} > #{category.name}" end def full_path(%Category{parent: %Ecto.Association.NotLoaded{}} = category) do category.name end end