Tickets

Manage pipelines, statuses, tickets, activities, notes, and per-workspace ticket configs, including survey-driven ticket automation and client portal access.

Code lives in frontline_api/src/modules/ticket (backend) and frontline_ui/src/modules/{ticket,pipelines,status} (frontend, served at /frontline/tickets).

Concepts

Pipelines

A Pipeline is a named ticket workflow bound to a channel (channelId) with memberIds, visibility (public/private), optional branchIds/departmentIds, and ordering/numbering config (isCheckDate, isCheckUser, isCheckDepartment, isCheckBranch, isHideName, excludeCheckUserIds, propertyIds, name/number fields). propertyIds selects which properties appear on tickets in the pipeline. The ticket property type is registered through meta with systemFields. Private pipelines require membership; isCheckUser/isCheckBranch/isCheckDepartment/isCheckDate further restrict which tickets a member sees.

Statuses

A Status belongs to a pipeline and carries visibilityType, memberIds, canEditMemberIds, canMoveMemberIds, and type. Status visibility feeds PermissionValidator.getHiddenStatusIds: a private status whose memberIds excludes you hides its tickets from lists, and canEditMemberIds/canMoveMemberIds gate edits and status moves per user.

Ticket records

A Ticket carries name, description, pipelineId, statusId, priority, assigneeId, assignedMembers, labelIds, tagIds, branchId, departmentId, channelId, number, state (active, archived, deleted), propertiesData, attachments, companyId/customerIds, dates, and sourceSurvey (the survey snapshot written by ticket automation). Filters on getTickets include search, status/pipeline/channel, assignee, ownership, and state.

Activities, notes, configs

  • Activity rows record ticket events; getTicketActivities lists them.
  • Note rows are user-authored ticket notes: ticketGetNote, ticketGetNotes, ticketCreateNote, ticketUpdateNote, ticketDeleteNote, plus client portal equivalents.
  • TicketConfig records hold per-pipeline/per-ticket settings via ticketConfigs, ticketConfigDetail, ticketConfig, ticketSaveConfig, ticketRemoveConfig.

Queries and mutations

Schema: modules/ticket/graphql/schemas/ticket.ts.

OperationKindPurpose
getTickets / getTicket(_id)queryFiltered list / detail
getTicketPipelines / getTicketPipeline(_id)queryPipeline reads
getTicketStatus(_id) / getAccessibleTicketStatuses / getTicketStatusesChoicesPipeline / getTicketStatusesByTypequeryStatus reads respecting visibility
getTicketActivities / ticketGetNote / ticketGetNotesqueryActivity and note reads
ticketConfigs / ticketConfigDetail / ticketConfigqueryConfig reads
createTicket / updateTicket / removeTicketmutationTicket writes
createPipeline / updatePipeline / removePipelinemutationPipeline management
addTicketStatus / updateTicketStatus / deleteTicketStatusmutationStatus management
ticketCreateNote / ticketUpdateNote / ticketDeleteNotemutationNote writes
ticketSaveConfig / ticketRemoveConfigmutationConfig writes
cpGetTickets / cpGetTicket / cpGetTicketTotalCount / cpGetTicketStatus / cpTicketGetNotesqueryClient portal reads
cpCreateTicket / cpUpdateTicket / cpTicketCreateNotemutationClient portal writes

The widget also exposes widgetTicketCreated, widgetTicketCheckProgress, widgetTicketCheckProgressForget, widgetTicketCommentAdd, widgetTicketCommentRemove, and widgetTicketsByCustomer for embedded ticket widgets (see Inbox & Channels).

mutation {
  createTicket(
    name: "Follow-up: billing dispute"
    pipelineId: "pipe_1"
    statusId: "status_1"
    assigneeId: "user_1"
    channelId: "chan_1"
  ) {
    _id
    number
  }
}

Survey-driven ticket automation

Survey options can arm ticket creation (ticketCreationEnabled, ticketCreationThreshold, ticketPipelineId, ticketStatusId). When a vote lands, runSurveyTicketAutomation (modules/survey/ticketAutomation.ts) counts SurveyVotes for the option, atomically claims it (ticketClaimedAt, 5-minute stale-claim window), and creates exactly one ticket named "<survey title> — <option text>" with a sourceSurvey snapshot. See Forms & Surveys.

Import and export

main.ts registers import/export producers for content type frontline:ticket.ticket (permissions ticketsImportManage / ticketsExportManage). Form submissions export separately under frontline:formSubmission.formSubmission (formSubmissionsExportManage).

tRPC

  • ticket.create: service-side ticket creation (doc + userId), used by the survey automation and inbox conversion.
  • relation.onRelationAdded: when a relation is added to a conversation, its form submissions are logged onto the related entity.

Permissions

The ticket permission module covers showTickets (always granted), createTicket, updateTicket, removeTicket, ticketStatusesManage, ticketsImportManage, and ticketsExportManage. There are no pipeline-level permission actions. Pipeline access is enforced by visibility/memberIds and PermissionValidator (modules/ticket/utils/permissionValidator.ts), which also applies per-status view/edit/move gates on top of those.

Edits and status moves fail with PermissionError when the status's canEditMemberIds/canMoveMemberIds excludes the caller.

Was this helpful?