03 · Helpdesk
The helpdesk is where staff handle support tickets. Every ticket carries
a source, one of three values:
- EMAIL — created from an inbound email
- PORTAL — raised by a customer at
support.kwgroup.uk - AGENT — created internally by staff (the default for tickets
raised from the portal
+ Newform)
Where to find it
Sidebar → Helpdesk or /helpdesk. Any staff role (SUPER_ADMIN,
ADMIN, MANAGER, AGENT) can open it.
Layout
+--------------------------------------------------------------+
| Helpdesk. [Reports] [+ New] |
| [Tickets open] [SLA breached] [Avg open] [Avg close] [Avg rsp]|
|--------------------------------------------------------------|
| [All][OPEN][IN PROGRESS][RESOLVED][CLOSED] 🔍search N total |
|--------------------------------------------------------------|
| ☐ Subject Type Status Pri SLA Assignee Age |
| ☐ Server down 🎫 Inc. OPEN HIGH ⚠ Mitch 2h |
| ☐ Email bounce — RESOLVED LOW met — 4d |
+--------------------------------------------------------------+
The page opens with a stat strip of five tabular metrics — tickets open, SLA breached, average time open, average time to close, average response. The Tickets open and SLA breached cards are clickable and filter the queue below; the three averages are informational only.
The Type column shows the ticket's ticket-type chip (icon +
colour-coded label) when one is set, or — when untyped. Status pulls
the per-type status name when one's defined; legacy enum-only tickets
fall back to the OPEN/IN_PROGRESS/RESOLVED/CLOSED labels. Above the
table a status pill row (All / OPEN / IN PROGRESS / RESOLVED /
CLOSED) filters by the legacy enum status.
📷 Screenshot placeholder: screenshots/helpdesk-list.png
The platform sidebar's Helpdesk section carries five built-in views,
each a /helpdesk?filter=<id> link with a live count badge:
- All open — every OPEN/IN_PROGRESS ticket
- Assigned to me (
filter=mine) — open tickets assigned to you - SLA breached (
filter=sla) — open tickets past their SLA resolution deadline and not yet met - Awaiting reply (
filter=awaiting) — open tickets where the most recent public comment is unauthored (an email/portal intake), or that have no staff reply yet - Closed · 7d (
filter=closed) — RESOLVED/CLOSED in the last 7 days
Below those, two kinds of saved views appear, each linking to
/helpdesk?view=<slug>:
- Shared views — admins create these at
/admin/helpdesk/views. They show up in every operator's sidebar. - Personal views — you create these at
/profile/settings/views. Only you see them.
A saved view bundles a base view + status + priority + assignee + customer + project + ticket type + free-text search. Click one to apply all filters at once. The status pill row disables while a named view is active so the two filter sets don't fight.
📷 Screenshot placeholder: screenshots/helpdesk-views.png
Ticket detail view
The detail page uses a three-zone layout. Top bar runs full-width across the page; everything else splits into a wider left column for the conversation and a right sidebar for linkage and metadata.
+----------------------------------------------------------+
| #A1B2C3D4 Server down — Acme Ltd [OPEN] [HIGH] [🎫] |
| Linked: [🏢 Acme] [👤 John Doe] [📁 SNAG-014] |
+--------------------------------+-------------------------+
| 📨 Original message | 🏷 Classification |
| "Server is unreachable…" | Type [Incident ▾] |
| | Status [Open ▾] |
| ┌────────┬────────┐ | Priority [HIGH ▾] |
| │ 📧Pub. │ 🔒Int. │ ◀ chooser +-------------------------+
| └────────┴────────┘ | ⏱ SLA |
| [textarea — sends to picked] | Resolution: 35m left |
| [Send] [⏱ Log time] +-------------------------+
| | 👥 People |
| 💬 Conversation (4) ⬇ Newest | Assignee Mitch |
| ─ John, 11:14 — public | Customer [Acme ▾] |
| ─ Mitch, 10:30 — internal | Contact [John ▾] |
| ─ John, 10:05 — public +-------------------------+
| | 📁 Linkage |
| | Project [SNAG-014 ▾] |
| | Contract [Gold ▾] |
| +-------------------------+
| | 🔗 Linked items |
| | 🔐 Open vault → |
| | 📦 Customer assets → |
| +-------------------------+
| 📎 Attachments | ⏱ Time on this ticket |
+--------------------------------+-------------------------+
📷 Screenshot placeholder: screenshots/helpdesk-ticket.png
Top bar (full width)
- Ticket number (short ID, e.g.
#A1B2C3D4) - Title
- Inline pills for status / priority / type / merged-into status
- Quick links — chips for any linked record. Only renders the chips that exist: customer, contact, project, contract. Hidden entirely if none are linked. Each chip is a hyperlink to the linked record's page.
Left column
- 📨 Original message — the description from the original email / form submission. Displayed as a card with the contact's email address shown in the header.
- Reply box — two full-width buttons at the top covering 50/50
of the reply card width:
- 📧 Public reply — blue. The customer sees the message; it's emailed via the inbound-email reply alias.
- 🔒 Internal note — amber. Staff-only. The textarea background flips to amber so it's impossible to confuse with a public reply. The textarea, send button, and ⏱ Log time affordance are below the toggle. The send button colour matches the active mode so sender + receive intent stay in sync.
- 💬 Conversation — every comment in the ticket. By default
newest-first; toggle
⬇ Newest first↔⬆ Oldest firstfrom the card header. Each comment has a clear PUBLIC / INTERNAL pill so the audience is unambiguous, plus the author and timestamp. - 📎 Attachments — drag-drop file uploads bound to the ticket.
Right column
- 🏷 Classification — Ticket type / Status / Priority. When a ticket type is set, the status dropdown filters to that type's configured statuses (otherwise falls back to the legacy enum).
- ⏱ SLA — current response + resolution status with countdown. Hidden when the ticket has no SLA deadlines set.
- 👥 People — Customer and Contact pickers, plus a read-only
Assignee line (name + email, or "Unassigned") and the contact
email when one is set. The customer and contact rows each get a
small
↗ Openlink. - 📁 Linkage — Project + Contract pickers.
- 🔗 Linked items — quick deep-links to the vault and, when a customer is linked, the customer's assets, devices, and contacts. The customer page is the single source of truth for those — the ticket doesn't try to embed them.
- ⏱ Time on this ticket — last 8 entries with totals. Log an entry from the ⏱ Log time affordance under the reply box.
Creating a ticket
Click + New ticket on the helpdesk dashboard (or open /helpdesk/new).
The form has two cards:
- Basics — Title (required), Description, Type (defaults to "— default —", i.e. untyped), and Priority chosen from a LOW / MEDIUM / HIGH / URGENT pill group.
- Scope — Customer, Project, Assignee, and Support contract, all optional dropdowns. The contract dropdown filters to contracts belonging to the chosen customer. A Contact email field records where reply emails should go.
Then click Create ticket.
The ticket fires the SLA clock as soon as it's created — deadlines are
computed from the org's SLA policy for the chosen priority. Tickets
created from this form have source = AGENT.
Replying
Two reply modes — pick the full-width tab at the top of the reply box:
- 📧 Public reply (blue) — the customer sees this. The send button reads 📧 Send reply.
- 🔒 Internal note (amber) — staff-only. The textarea background turns amber and the send button reads 🔒 Add note.
The send button is disabled until the textarea has content. Attach files to the ticket from the 📎 Attachments card.
Status, priority, type
| Field | Notes |
|---|---|
| Type | Tenant-defined (Incident, Change, Quote, …) |
| Status | The set of options depends on the type — each type owns its own status list |
| Priority | LOW / MEDIUM / HIGH / URGENT (fixed) |
When you pick a type at ticket-creation time, the status dropdown filters to the statuses configured on that type. So a Change ticket might cycle through Submitted → Approved → Implemented → Closed, while an Incident moves through Open → Investigating → Resolved → Closed — without bleeding statuses across types.
Configure types and per-type statuses in Admin → Ticket types.
SLA
When a ticket is created, the platform looks up the org's SLA policy for the ticket's priority and stamps a response deadline and a resolution deadline onto the ticket. (The policy is keyed on org + priority — there is one policy row per LOW / MEDIUM / HIGH / URGENT.) If no policy is configured for that priority, the ticket simply has no SLA deadlines.
- Response — marked met on the first public (non-internal) reply, comparing the reply time against the response deadline.
- Resolution — marked met when the ticket moves to RESOLVED or CLOSED, comparing the close time against the resolution deadline.
The SLA card and the queue's SLA column show, for an open ticket, "Nh remaining" / "⚠ Overdue", and for a closed ticket, "SLA met" / "SLA breached". There is no pause/resume — the deadlines are fixed absolute timestamps set at creation time.
→ Configure: Helpdesk admin → SLA
Linking projects and customers
The right sidebar of a ticket lets you link:
- Customer — a CRM company. Optional, but it drives the Linked-items deep links and surfaces the ticket on the customer record.
- Contact — the person on the other side of the conversation.
- Project — links the ticket to a project.
- Contract — a support contract, used for time-entry billing.
All four are dropdowns in the right sidebar and can be changed at any time. There is no device (RMM) picker on the ticket itself.
Attachments
The 📎 Attachments card sits below the conversation thread. Click + Attach file to pick one or more files; they upload to object storage and are listed on the card with size and type, where you can download or delete them. The card is bound to the ticket, not to an individual reply.
Search
The search box at the top of the queue does a case-insensitive
contains search across title, description body, and
contact email, debounced 300 ms. Hits show with a "X matches"
indicator next to the box. Tickets that have been merged into another
are hidden by default — pass ?includeMerged=1 on the API if you
want them back.
Multi-select & merge
Each row has a checkbox; the header has a select-all-visible. With 2 or more selected, an action bar appears at the top with 🔀 Merge selected….
Clicking it opens a modal where you pick the survivor — the
oldest selected ticket is pre-selected because it's usually the
original report. The other tickets' comments and time entries are
moved into the survivor (an internal "🔀 Merged from …" note marks
each insertion point), the originals are flipped to CLOSED with
mergedIntoId set, and the queue refreshes.
⚠️ Caution. The merge is one-way and atomic (it runs in a single
database transaction). There's no "unmerge" button — by design, you'd
have to manually re-create the source ticket. Each source ticket gets
a 🔀 Merged from … internal note in the survivor, authored by the
operator who performed the merge.
Email handover
Replies are sent from helpdesk@<your-domain> and Reply-To is set to a
ticket-specific alias so customer replies thread back automatically.
→ Configure email under Admin → Email settings.
Public customer view
Customers can see their own tickets at support.kwgroup.uk. They see
only the Reply stream — internal notes are hidden.
Common workflows
Triage incoming inbox
- Open the helpdesk and click the OPEN status pill, or use the sidebar's Awaiting reply view to find tickets the customer last touched.
- Skim subjects, open each ticket, set the assignee, type, and priority from the right sidebar.
Resolve and close
- Send a public reply with the resolution.
- Set the status to RESOLVED (or CLOSED). Both stamp
resolvedAtand evaluate the resolution SLA. - If a SCHEDULED rule is configured, RESOLVED tickets can be auto-closed after a delay — see Helpdesk rules.
See also
- CRM — for customer records
- Projects — link a ticket to a project
- Helpdesk rules — automate ticket workflows
- Admin → Helpdesk config — SLA policies, contracts