defmodule Glific.Tags.Tag do
@moduledoc """
The minimal wrapper for the base Tag structure
"""
use Ecto.Schema
import Ecto.Changeset
alias Glific.{
Contacts.Contact,
Messages.Message,
Partners.Organization,
Settings.Language,
Tags.Tag
}
@required_fields [:label, :language_id, :organization_id, :shortcode]
@optional_fields [
:description,
:is_active,
:is_reserved,
:is_value,
:parent_id,
:keywords,
:ancestors,
:color_code
]
@type t() :: %__MODULE__{
__meta__: Ecto.Schema.Metadata.t(),
id: non_neg_integer | nil,
label: String.t() | nil,
shortcode: String.t() | nil,
description: String.t() | nil,
color_code: String.t() | nil,
is_active: boolean(),
is_reserved: boolean(),
is_value: boolean(),
keywords: list(),
language_id: non_neg_integer | nil,
language: Language.t() | Ecto.Association.NotLoaded.t() | nil,
organization_id: non_neg_integer | nil,
organization: Organization.t() | Ecto.Association.NotLoaded.t() | nil,
parent_id: non_neg_integer | nil,
parent: Tag.t() | Ecto.Association.NotLoaded.t() | nil,
ancestors: list() | [],
inserted_at: :utc_datetime | nil,
updated_at: :utc_datetime | nil
}
schema "tags" do
field :label, :string
field :shortcode, :string
field :description, :string
field :ancestors, {:array, :integer}, default: []
field :color_code, :string, default: "#0C976D"
field :is_active, :boolean, default: false
field :is_reserved, :boolean, default: false
field :is_value, :boolean, default: false
field :keywords, {:array, :string}, default: []
belongs_to :language, Language
belongs_to :organization, Organization
belongs_to :parent, Tag, foreign_key: :parent_id
has_many :child, Tag, foreign_key: :parent_id
many_to_many :contacts, Contact, join_through: "contacts_tags", on_replace: :delete
many_to_many :messages, Message, join_through: "messages_tags", on_replace: :delete
timestamps(type: :utc_datetime)
end
@doc """
Standard changeset pattern we use for all data types
"""
@spec changeset(Tag.t(), map()) :: Ecto.Changeset.t()
def changeset(tag, attrs) do
tag
|> cast(attrs, @required_fields ++ @optional_fields)
|> validate_required(@required_fields)
|> lowercase_keywords(attrs[:keywords])
|> foreign_key_constraint(:language_id)
|> foreign_key_constraint(:parent_id)
|> unique_constraint([:shortcode, :language_id, :organization_id])
|> Glific.validate_shortcode()
end
@spec lowercase_keywords(Ecto.Changeset.t(), list()) :: Ecto.Changeset.t()
defp lowercase_keywords(changeset, keywords) do
case keywords do
nil -> changeset
_ -> put_change(changeset, :keywords, Enum.map(keywords, &String.downcase(&1)))
end
end
end