# `PhoenixKit.Modules.CustomerService.Ticket`
[🔗](https://github.com/BeamLabEU/phoenix_kit/blob/v1.7.87/lib/modules/customer_service/ticket.ex#L1)

Schema for support tickets.

Represents a customer support request with status workflow, assignment,
and comment threads including internal notes.

## Status Flow

- `open` - New ticket, awaiting assignment or response
- `in_progress` - Being worked on by support staff
- `resolved` - Issue resolved, awaiting confirmation
- `closed` - Ticket closed (resolved or abandoned)

## Transitions

- open -> in_progress (when assigned or work begins)
- open -> resolved (direct resolution)
- open -> closed (close without resolution)
- in_progress -> resolved
- in_progress -> open (return/unassign)
- in_progress -> closed
- resolved -> closed (auto or manual)
- resolved -> open (reopen by customer)
- closed -> open (reopen, if allowed)

## Fields

- `user_uuid` - Customer who created the ticket
- `assigned_to_uuid` - Support staff handling the ticket
- `title` - Brief description of the issue
- `description` - Full details of the issue
- `status` - open/in_progress/resolved/closed
- `slug` - URL-friendly identifier
- `comment_count` - Denormalized counter
- `metadata` - Flexible JSONB for future extensions
- `resolved_at` - When ticket was resolved
- `closed_at` - When ticket was closed

## Examples

    # New ticket
    %Ticket{
      uuid: "018e3c4a-9f6b-7890-abcd-ef1234567890",
      user_uuid: "018e3c4a-1111-7890-abcd-ef1234567890",
      assigned_to_uuid: nil,
      title: "Cannot login to my account",
      description: "I get an error when trying to login...",
      status: "open",
      slug: "cannot-login-to-my-account",
      comment_count: 0
    }

    # Ticket being worked on
    %Ticket{
      user_uuid: "018e3c4a-1111-7890-abcd-ef1234567890",
      assigned_to_uuid: "018e3c4a-2222-7890-abcd-ef1234567890",
      title: "Payment failed",
      description: "...",
      status: "in_progress",
      comment_count: 3
    }

    # Resolved ticket
    %Ticket{
      user_uuid: "018e3c4a-1111-7890-abcd-ef1234567890",
      assigned_to_uuid: "018e3c4a-2222-7890-abcd-ef1234567890",
      status: "resolved",
      resolved_at: ~U[2025-01-15 14:30:00Z]
    }

# `t`

```elixir
@type t() :: %PhoenixKit.Modules.CustomerService.Ticket{
  __meta__: term(),
  assigned_to:
    PhoenixKit.Users.Auth.User.t() | Ecto.Association.NotLoaded.t() | nil,
  assigned_to_uuid: UUIDv7.t() | nil,
  attachments:
    [PhoenixKit.Modules.CustomerService.TicketAttachment.t()]
    | Ecto.Association.NotLoaded.t(),
  closed_at: DateTime.t() | nil,
  comment_count: integer(),
  comments:
    [PhoenixKit.Modules.CustomerService.TicketComment.t()]
    | Ecto.Association.NotLoaded.t(),
  description: String.t(),
  inserted_at: DateTime.t() | nil,
  metadata: map(),
  resolved_at: DateTime.t() | nil,
  slug: String.t(),
  status: String.t(),
  status_history:
    [PhoenixKit.Modules.CustomerService.TicketStatusHistory.t()]
    | Ecto.Association.NotLoaded.t(),
  title: String.t(),
  updated_at: DateTime.t() | nil,
  user: PhoenixKit.Users.Auth.User.t() | Ecto.Association.NotLoaded.t(),
  user_uuid: UUIDv7.t(),
  uuid: UUIDv7.t() | nil
}
```

# `assigned?`

Check if ticket is assigned to someone.

# `can_comment?`

Check if ticket can receive comments (not closed).

# `changeset`

Changeset for creating or updating a ticket.

## Required Fields

- `user_uuid` - Customer who created the ticket
- `title` - Brief description
- `description` - Full details
- `status` - Must be: "open", "in_progress", "resolved", or "closed"

## Validation Rules

- Title max 255 characters
- Status must be valid
- Slug auto-generated from title if not provided

# `closed?`

Check if ticket is closed.

# `in_progress?`

Check if ticket is in progress.

# `open?`

Check if ticket is open.

# `resolved?`

Check if ticket is resolved.

# `statuses`

Returns list of valid statuses.

# `valid_transition?`

Check if transition from current to new status is valid.

# `valid_transitions`

Valid transitions from current status.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
