Packages

phoenix_kit

1.7.56
1.7.208 1.7.207 1.7.206 1.7.205 1.7.204 1.7.203 1.7.202 1.7.201 1.7.200 1.7.199 1.7.198 1.7.197 1.7.196 1.7.194 1.7.193 1.7.192 1.7.191 1.7.190 1.7.189 1.7.187 1.7.186 1.7.185 1.7.184 1.7.183 1.7.182 1.7.181 1.7.180 1.7.179 1.7.178 1.7.177 1.7.176 1.7.175 1.7.174 1.7.173 1.7.172 1.7.171 1.7.170 1.7.169 1.7.168 1.7.167 1.7.166 1.7.165 1.7.164 1.7.162 1.7.161 1.7.160 1.7.159 1.7.157 1.7.156 1.7.155 1.7.154 1.7.153 1.7.152 1.7.151 1.7.150 1.7.149 1.7.146 1.7.145 1.7.144 1.7.143 1.7.138 1.7.133 1.7.132 1.7.131 1.7.130 1.7.128 1.7.126 1.7.125 1.7.121 1.7.120 1.7.119 1.7.118 1.7.117 1.7.116 1.7.115 1.7.114 1.7.113 1.7.112 1.7.111 1.7.110 1.7.109 1.7.108 1.7.107 1.7.106 1.7.105 1.7.104 1.7.103 1.7.102 1.7.101 1.7.100 1.7.99 1.7.98 1.7.97 1.7.96 1.7.95 1.7.94 1.7.93 1.7.92 1.7.91 1.7.90 1.7.89 1.7.88 1.7.87 1.7.86 1.7.85 1.7.84 1.7.83 1.7.82 1.7.81 1.7.80 1.7.79 1.7.78 1.7.77 1.7.76 1.7.75 1.7.74 1.7.71 1.7.70 1.7.69 1.7.66 1.7.65 1.7.64 1.7.63 1.7.62 1.7.61 1.7.59 1.7.58 1.7.57 1.7.56 1.7.55 1.7.54 1.7.53 1.7.52 1.7.51 1.7.49 1.7.44 1.7.43 1.7.42 1.7.41 1.7.39 1.7.38 1.7.37 1.7.36 1.7.34 1.7.33 1.7.31 1.7.30 1.7.29 1.7.28 1.7.27 1.7.26 1.7.25 1.7.24 1.7.23 1.7.22 1.7.21 1.7.20 1.7.19 1.7.18 1.7.17 1.7.16 1.7.15 1.7.14 1.7.13 1.7.12 1.7.11 1.7.10 1.7.9 1.7.8 1.7.7 1.7.6 1.7.5 1.7.4 1.7.3 1.7.2 1.7.1 1.7.0 1.6.20 1.6.19 1.6.18 1.6.17 1.6.16 1.6.15 1.6.14 1.6.13 1.6.12 1.6.11 1.6.10 1.6.9 1.6.8 1.6.7 1.6.6 1.6.5 1.6.4 1.6.3 1.5.2 1.5.1 1.5.0 1.4.9 1.4.8 1.4.7 1.4.6 1.4.5 1.4.4 1.4.3 1.4.2 1.4.1 1.4.0 1.3.2 1.3.1 1.3.0 1.2.10 1.2.9 1.2.8 1.2.7 1.2.5 1.2.4 1.2.2 1.2.1 1.2.0 1.1.0 1.0.0

A foundation for building Elixir Phoenix apps — SaaS, social networks, ERP systems, marketplaces, and more

Current section

Files

Jump to
phoenix_kit lib modules tickets ticket_comment.ex
Raw

lib/modules/tickets/ticket_comment.ex

defmodule PhoenixKit.Modules.Tickets.TicketComment do
@moduledoc """
Schema for ticket comments with internal notes support.
Supports nested comment threads (like PostComment) with self-referencing
parent/child relationships. The `is_internal` flag distinguishes between
public comments (visible to customer) and internal notes (staff only).
## Comment Types
- **Public comments** (`is_internal: false`) - Visible to customer and staff
- **Internal notes** (`is_internal: true`) - Visible only to support staff
## Fields
- `ticket_uuid` - Reference to the ticket
- `user_uuid` - Reference to the commenter
- `parent_uuid` - Reference to parent comment (nil for top-level)
- `content` - Comment text
- `is_internal` - True for internal notes, false for public comments
- `depth` - Nesting level (0=top, 1=reply, 2=reply-to-reply, etc.)
## Examples
# Public comment from support
%TicketComment{
ticket_uuid: "018e3c4a-9f6b-7890-abcd-ef1234567890",
user_uuid: "018e3c4a-9f6b-7890-abcd-ef1234567890",
parent_uuid: nil,
content: "Thank you for contacting us. We're looking into this.",
is_internal: false,
depth: 0
}
# Internal note (hidden from customer)
%TicketComment{
ticket_uuid: "018e3c4a-9f6b-7890-abcd-ef1234567890",
user_uuid: "018e3c4a-9f6b-7890-abcd-ef1234567890",
parent_uuid: nil,
content: "Customer seems frustrated. Need to escalate to senior support.",
is_internal: true,
depth: 0
}
# Customer reply
%TicketComment{
ticket_uuid: "018e3c4a-9f6b-7890-abcd-ef1234567890",
user_uuid: "018e3c4a-9f6b-7890-abcd-ef1234567890",
parent_uuid: "018e3c4a-1234-5678-abcd-ef1234567890",
content: "Thanks, I've tried that but it still doesn't work.",
is_internal: false,
depth: 1
}
"""
use Ecto.Schema
import Ecto.Changeset
@primary_key {:uuid, UUIDv7, autogenerate: true}
@type t :: %__MODULE__{
uuid: UUIDv7.t() | nil,
ticket_uuid: UUIDv7.t(),
user_uuid: UUIDv7.t() | nil,
parent_uuid: UUIDv7.t() | nil,
content: String.t(),
is_internal: boolean(),
depth: integer(),
ticket: PhoenixKit.Modules.Tickets.Ticket.t() | Ecto.Association.NotLoaded.t(),
user: PhoenixKit.Users.Auth.User.t() | Ecto.Association.NotLoaded.t(),
parent: t() | Ecto.Association.NotLoaded.t() | nil,
children: [t()] | Ecto.Association.NotLoaded.t(),
attachments:
[PhoenixKit.Modules.Tickets.TicketAttachment.t()] | Ecto.Association.NotLoaded.t(),
inserted_at: DateTime.t() | nil,
updated_at: DateTime.t() | nil
}
schema "phoenix_kit_ticket_comments" do
field :content, :string
field :is_internal, :boolean, default: false
field :depth, :integer, default: 0
belongs_to :ticket, PhoenixKit.Modules.Tickets.Ticket,
foreign_key: :ticket_uuid,
references: :uuid,
type: UUIDv7
belongs_to :user, PhoenixKit.Users.Auth.User,
foreign_key: :user_uuid,
references: :uuid,
type: UUIDv7
belongs_to :parent, __MODULE__,
foreign_key: :parent_uuid,
references: :uuid,
type: UUIDv7
has_many :children, __MODULE__, foreign_key: :parent_uuid
has_many :attachments, PhoenixKit.Modules.Tickets.TicketAttachment, foreign_key: :comment_uuid
timestamps(type: :utc_datetime)
end
@doc """
Changeset for creating or updating a comment.
## Required Fields
- `ticket_uuid` - Reference to ticket
- `user_uuid` - Reference to commenter
- `content` - Comment text
## Validation Rules
- Content must be 1-10000 characters
- is_internal defaults to false
- Depth automatically calculated from parent
"""
def changeset(comment, attrs) do
comment
|> cast(attrs, [
:ticket_uuid,
:user_uuid,
:parent_uuid,
:content,
:is_internal,
:depth
])
|> validate_required([:ticket_uuid, :user_uuid, :content])
|> validate_length(:content, min: 1, max: 10_000)
|> foreign_key_constraint(:ticket_uuid)
|> foreign_key_constraint(:user_uuid)
|> foreign_key_constraint(:parent_uuid)
end
@doc """
Check if comment is an internal note.
"""
def internal?(%__MODULE__{is_internal: true}), do: true
def internal?(_), do: false
@doc """
Check if comment is public (visible to customer).
"""
def public?(%__MODULE__{is_internal: false}), do: true
def public?(_), do: false
@doc """
Check if comment is a reply (has parent).
"""
def reply?(%__MODULE__{parent_uuid: nil}), do: false
def reply?(%__MODULE__{}), do: true
@doc """
Check if comment is top-level (no parent).
"""
def top_level?(%__MODULE__{parent_uuid: nil}), do: true
def top_level?(%__MODULE__{}), do: false
end