Context for managing support tickets, comments, and attachments.
Provides complete API for the customer support ticketing system including CRUD operations, status workflow, comment threading with internal notes, file attachments, and audit trail.
Features
- Ticket Management: Create, update, delete tickets
- Status Workflow: open → in_progress → resolved → closed
- Assignment: Assign tickets to support staff
- Comment System: Public comments and internal notes
- File Attachments: Multiple files per ticket/comment
- Audit Trail: Complete status change history
Status Flow
open- New ticket, awaiting assignment or responsein_progress- Being worked on by support staffresolved- Issue resolved, awaiting confirmationclosed- Ticket closed (resolved or abandoned)
Examples
# Create a ticket
{:ok, ticket} = Tickets.create_ticket(user_id, %{
title: "Cannot login",
description: "I get an error when trying to login..."
})
# Assign to support staff
{:ok, ticket} = Tickets.assign_ticket(ticket, staff_user_id, current_user)
# Start working on it
{:ok, ticket} = Tickets.start_progress(ticket, current_user)
# Add a public comment
{:ok, comment} = Tickets.create_comment(ticket.uuid, staff_user_id, %{
content: "We're looking into this issue."
})
# Add an internal note (hidden from customer)
{:ok, note} = Tickets.create_internal_note(ticket.uuid, staff_user_id, %{
content: "Customer seems frustrated. Need to escalate."
})
# Resolve the ticket
{:ok, ticket} = Tickets.resolve_ticket(ticket, current_user, "Fixed in v2.0.1")
Summary
Functions
Attaches a file to a comment.
Attaches a file to a ticket.
Assigns a ticket to a support staff member.
Closes a ticket.
Creates a public comment on a ticket.
Creates an internal note on a ticket (visible only to support staff).
Creates a new ticket.
Deletes a comment.
Deletes a ticket and all related data.
Disables the Tickets module.
Enables the Tickets module.
Checks if the Tickets module is enabled.
Gets a comment by ID.
Gets the current Tickets module configuration and stats.
Gets ticket statistics.
Gets the status history for a ticket.
Gets a single ticket by ID. Returns nil if not found.
Gets a single ticket by ID with optional preloads.
Gets a single ticket by slug.
Lists all comments for a ticket (includes internal notes). For staff use only.
Lists attachments for a comment.
Lists only internal notes for a ticket.
Lists public comments for a ticket (excludes internal notes).
Lists attachments for a ticket.
Lists tickets with optional filtering and pagination.
Lists tickets assigned to a specific handler.
Lists unassigned tickets (where assigned_to_id is nil).
Lists tickets created by a specific user.
Removes an attachment.
Reopens a closed or resolved ticket.
Resolves a ticket.
Moves ticket to in_progress status.
Updates a comment.
Updates an existing ticket.
Functions
Attaches a file to a comment.
Attaches a file to a ticket.
Parameters
ticket_id- ID of the ticketfile_id- ID of the uploaded fileopts- Options:position- Display order (default: auto-calculated):caption- Optional caption
Examples
iex> add_attachment_to_ticket(ticket.uuid, file.uuid, caption: "Error screenshot")
{:ok, %TicketAttachment{}}
Assigns a ticket to a support staff member.
If the ticket is open, it will be moved to in_progress.
Parameters
ticket- Ticket to assignhandler_id- User ID of the support staffchanged_by- User making the change
Examples
iex> assign_ticket(ticket, 5, current_user)
{:ok, %Ticket{assigned_to_id: 5}}
Closes a ticket.
Parameters
ticket- Ticket to closechanged_by- User making the changereason- Optional close reason
Examples
iex> close_ticket(ticket, current_user, "No response from customer")
{:ok, %Ticket{status: "closed"}}
Creates a public comment on a ticket.
Parameters
ticket_id- ID of the ticketuser_id- ID of the commenterattrs- Comment attributes (content, optional parent_id)
Examples
iex> create_comment(ticket.uuid, user_id, %{content: "Thanks for looking into this!"})
{:ok, %TicketComment{}}
Creates an internal note on a ticket (visible only to support staff).
Parameters
ticket_id- ID of the ticketuser_id- ID of the staff memberattrs- Note attributes (content)
Examples
iex> create_internal_note(ticket.uuid, staff_id, %{content: "Customer seems frustrated"})
{:ok, %TicketComment{is_internal: true}}
Creates a new ticket.
Parameters
user_id- Customer who created the ticketattrs- Ticket attributes (title, description)
Examples
iex> create_ticket(42, %{title: "Bug report", description: "Something is wrong"})
{:ok, %Ticket{}}
iex> create_ticket(42, %{title: ""})
{:error, %Ecto.Changeset{}}
Deletes a comment.
Deletes a ticket and all related data.
Parameters
ticket- Ticket struct to delete
Examples
iex> delete_ticket(ticket)
{:ok, %Ticket{}}
Disables the Tickets module.
Examples
iex> disable_system()
{:ok, %Setting{}}
Enables the Tickets module.
Examples
iex> enable_system()
{:ok, %Setting{}}
Checks if the Tickets module is enabled.
Examples
iex> enabled?()
false
Gets a comment by ID.
Gets the current Tickets module configuration and stats.
Examples
iex> get_config()
%{enabled: false, total_tickets: 0, open_tickets: 0, ...}
Gets ticket statistics.
Gets the status history for a ticket.
Gets a single ticket by ID. Returns nil if not found.
Gets a single ticket by ID with optional preloads.
Raises Ecto.NoResultsError if ticket not found.
Parameters
id- Ticket ID (UUIDv7)opts- Options:preload- List of associations to preload
Examples
iex> get_ticket!("018e3c4a-...")
%Ticket{}
iex> get_ticket!("018e3c4a-...", preload: [:user, :assigned_to, :comments])
%Ticket{user: %User{}, assigned_to: %User{}, comments: [...]}
Gets a single ticket by slug.
Parameters
slug- Ticket slugopts- Options:preload- List of associations to preload
Examples
iex> get_ticket_by_slug("cannot-login-123456")
%Ticket{}
Lists all comments for a ticket (includes internal notes). For staff use only.
Lists attachments for a comment.
Lists only internal notes for a ticket.
Lists public comments for a ticket (excludes internal notes).
Lists attachments for a ticket.
Lists tickets with optional filtering and pagination.
Parameters
opts- Options:user_id- Filter by customer (ticket creator):assigned_to_id- Filter by assigned handler:status- Filter by status (open/in_progress/resolved/closed):search- Search in title and description:page- Page number (default: 1):per_page- Items per page (default: 20):preload- Associations to preload
Examples
iex> list_tickets()
[%Ticket{}, ...]
iex> list_tickets(status: "open", assigned_to_id: nil)
[%Ticket{}, ...]
Lists tickets assigned to a specific handler.
Lists unassigned tickets (where assigned_to_id is nil).
Lists tickets created by a specific user.
Removes an attachment.
Reopens a closed or resolved ticket.
Parameters
ticket- Ticket to reopenchanged_by- User making the changereason- Optional reopen reason
Examples
iex> reopen_ticket(ticket, current_user, "Issue still occurring")
{:ok, %Ticket{status: "open"}}
Resolves a ticket.
Parameters
ticket- Ticket to resolvechanged_by- User making the changereason- Optional resolution reason
Examples
iex> resolve_ticket(ticket, current_user, "Fixed in version 2.0.1")
{:ok, %Ticket{status: "resolved"}}
Moves ticket to in_progress status.
Parameters
ticket- Ticket to updatechanged_by- User making the change
Examples
iex> start_progress(ticket, current_user)
{:ok, %Ticket{status: "in_progress"}}
Updates a comment.
Updates an existing ticket.
Parameters
ticket- Ticket struct to updateattrs- Attributes to update
Examples
iex> update_ticket(ticket, %{title: "Updated Title"})
{:ok, %Ticket{}}