120 lines
3.1 KiB
Elixir
120 lines
3.1 KiB
Elixir
defmodule ComponentsElixir.Inventory.Component do
|
|
@moduledoc """
|
|
Schema for electronic components.
|
|
|
|
Each component belongs to a category and tracks inventory information
|
|
including count, location, and optional image and datasheet.
|
|
"""
|
|
use Ecto.Schema
|
|
import Ecto.Changeset
|
|
|
|
alias ComponentsElixir.Inventory.{Category, StorageLocation}
|
|
|
|
schema "components" do
|
|
field :name, :string
|
|
field :description, :string
|
|
field :keywords, :string
|
|
field :position, :string
|
|
field :legacy_position, :string
|
|
field :count, :integer, default: 0
|
|
field :datasheet_url, :string
|
|
field :datasheet_filename, :string
|
|
field :image_filename, :string
|
|
|
|
belongs_to :category, Category
|
|
belongs_to :storage_location, StorageLocation
|
|
|
|
timestamps(type: :naive_datetime_usec)
|
|
end
|
|
|
|
@doc false
|
|
def changeset(component, attrs) do
|
|
component
|
|
|> cast(attrs, [
|
|
:name,
|
|
:description,
|
|
:keywords,
|
|
:position,
|
|
:count,
|
|
:datasheet_url,
|
|
:datasheet_filename,
|
|
:image_filename,
|
|
:category_id,
|
|
:storage_location_id
|
|
])
|
|
|> validate_required([:name, :category_id])
|
|
|> validate_length(:name, min: 1, max: 255)
|
|
|> validate_length(:description, max: 2000)
|
|
|> validate_length(:keywords, max: 500)
|
|
|> validate_length(:position, max: 100)
|
|
|> validate_number(:count, greater_than_or_equal_to: 0)
|
|
|> validate_url(:datasheet_url)
|
|
|> foreign_key_constraint(:category_id)
|
|
|> foreign_key_constraint(:storage_location_id)
|
|
end
|
|
|
|
@doc """
|
|
Changeset for updating component count.
|
|
"""
|
|
def count_changeset(component, attrs) do
|
|
component
|
|
|> cast(attrs, [:count])
|
|
|> validate_required([:count])
|
|
|> validate_number(:count, greater_than_or_equal_to: 0)
|
|
end
|
|
|
|
@doc """
|
|
Changeset for updating component image.
|
|
"""
|
|
def image_changeset(component, attrs) do
|
|
component
|
|
|> cast(attrs, [:image_filename])
|
|
end
|
|
|
|
@doc """
|
|
Changeset for updating component datasheet.
|
|
"""
|
|
def datasheet_changeset(component, attrs) do
|
|
component
|
|
|> cast(attrs, [:datasheet_filename])
|
|
end
|
|
|
|
defp validate_url(changeset, field) do
|
|
validate_change(changeset, field, fn ^field, url ->
|
|
cond do
|
|
is_nil(url) or url == "" -> []
|
|
valid_url?(url) -> []
|
|
true -> [{field, "must be a valid URL"}]
|
|
end
|
|
end)
|
|
end
|
|
|
|
defp valid_url?(url) do
|
|
case URI.parse(url) do
|
|
%URI{scheme: scheme} when scheme in ["http", "https"] -> true
|
|
_ -> false
|
|
end
|
|
end
|
|
|
|
@doc """
|
|
Returns true if the component has an image.
|
|
"""
|
|
def has_image?(%__MODULE__{image_filename: filename}) when is_binary(filename), do: true
|
|
def has_image?(_), do: false
|
|
|
|
@doc """
|
|
Returns true if the component has a datasheet file.
|
|
"""
|
|
def has_datasheet?(%__MODULE__{datasheet_filename: filename}) when is_binary(filename), do: true
|
|
def has_datasheet?(_), do: false
|
|
|
|
@doc """
|
|
Returns the search text for this component.
|
|
"""
|
|
def search_text(%__MODULE__{} = component) do
|
|
[component.name, component.description, component.keywords]
|
|
|> Enum.filter(&is_binary/1)
|
|
|> Enum.join(" ")
|
|
end
|
|
end
|