# Wrap-up codes and dispositions

> Define the after-call disposition list agents pick from: categories, the FCR and follow-up flags, hotline scoping, picker order, and what deactivation does to history.

A wrap-up code is one row in the `dim_wrap_up_code` dimension. Together,
the active rows are the dropdown an agent picks from when a call ends —
the disposition list. TeleQuick stores the agent's choice on the call
record, and the fields you set here are what downstream QA and
first-call-resolution reporting reads.

Manage the list in the console under **Wrap-up codes**. The screen is a
straight CRUD surface over four procedures:

| Procedure                    | Input                                                        |
| ---------------------------- | ------------------------------------------------------------ |
| `adminWrapupCodes.list`      | `{ orgId, search?, includeInactive, page, perPage }`         |
| `adminWrapupCodes.create`    | `{ orgId, row }`                                             |
| `adminWrapupCodes.update`    | `{ orgId, id, patch }`                                       |
| `adminWrapupCodes.remove`    | `{ orgId, id }`                                              |

## What a wrap-up code is

Each code carries these fields:

| Field                | Type                    | Notes                                                                 |
| -------------------- | ----------------------- | --------------------------------------------------------------------- |
| `id`                 | string                  | Server-assigned. This is what call records reference.                 |
| `code`               | string, up to 40 chars  | The stable short key, e.g. `RESOLVED`. Required.                      |
| `name`               | string, up to 120 chars | The label agents read, e.g. `Resolved · billed`. Required.            |
| `category`           | enum                    | One of eight reporting buckets. See below.                            |
| `is_fcr`             | boolean                 | "Counts toward FCR".                                                  |
| `requires_follow_up` | boolean                 | Marks the call as needing follow-up work.                             |
| `hotline_id`         | string or `null`        | `null` means the code is offered on any hotline.                       |
| `sort_order`         | integer, 0–9999         | Sort key for the list. New codes default to `100`.                    |
| `active`             | boolean                 | Inactive codes are hidden from the list unless you ask for them.      |

The console normalises the `code` field as you type: it upper-cases the
input and replaces runs of whitespace with `_`. Both `code` and `name`
are trimmed and must be non-empty before the form will submit.

`active` is only editable on an existing code — the create form does not
send it, and the Active toggle appears in the drawer in edit mode only.

## The category vocabulary

`category` is a fixed enum. It is a reporting bucket: the console renders
it as a coloured chip and the empty-state copy on the screen states that
categories roll up to the QA / FCR reports. The category itself drives no
behaviour on the call — the two flags below do that.

| `category`   | Label in the picker | Chip treatment            |
| ------------ | ------------------- | ------------------------- |
| `resolved`   | Resolved            | Success (green)           |
| `unresolved` | Unresolved          | Error (red)               |
| `callback`   | Callback            | Info (blue)               |
| `escalated`  | Escalated           | Warning (amber)           |
| `invalid`    | Invalid             | Muted / neutral           |
| `promise`    | Promise             | Purple                    |
| `refused`    | Refused             | Error (red)               |
| `other`      | Other               | Neutral                   |

You can define many codes in the same category — that is the normal
shape. The `code` and `name` give the agent the specific reason
(`RESOLVED_BILLED`, `RESOLVED_NO_CHARGE`); the category is what a report
groups by so that the bucket totals stay stable as you add and rename
individual codes.

## The FCR flag and first-call resolution

`is_fcr` is a per-code boolean, exposed in the drawer as **Counts toward
FCR**. Codes with the flag set show an `FCR` chip in the list; codes
without it show a dash.

The flag is independent of `category`. Nothing forces a `resolved` code
to count toward FCR, and nothing stops a code in another category from
counting. That is deliberate: a `resolved` code that you use for
"resolved by transferring to the carrier" can be excluded from FCR while
still reporting as resolved, and a `promise` code can count as a
first-call resolution if your team treats it as one.

Because the flag lives on the dimension row and the call record points at
the row by `id`, flipping `is_fcr` changes how the code is treated
without touching any stored call. Treat a change to this flag as a change
to your reporting definition, not to your data.

## Requires follow-up

`requires_follow_up` is the second boolean on the row. Codes with it set
show a **Yes** chip in the Follow-up column.

Use it on codes that mean the interaction is not finished: callbacks,
promises, escalations. Like `is_fcr`, it is independent of `category`, so
you can have a `callback` code that does not demand follow-up (the
customer will call back) alongside one that does (the agent must).

## Scoping a code to a hotline

A code with `hotline_id = null` is global — the list renders it as
**Any**. Set `hotline_id` to attach the code to one hotline, and the
list shows that hotline's `code` instead.

The Hotline picker in the drawer is populated from
`adminHotlines.list` for the same org: each option shows the hotline's
name, with the hotline's short code as a hint. The picker is clearable —
clearing it sets `hotline_id` back to `null` and makes the code global
again.

Scoping is how you keep the agent's dropdown short. A collections
hotline and a support hotline can each carry their own specific codes
while sharing the global ones.

## Ordering the agent picker

`sort_order` is a plain integer between 0 and 9999 and is the sort key
for the code list. The console shows it as the leading column, so the
admin table reflects the order the codes sit in.

New codes are created at `100`. Leaving gaps between values — 100, 200,
300 — lets you insert a code later without renumbering the rest.

## Searching and paging the list

The list is paged at 50 rows per page, with the total row count shown in
the page header and in the pager.

- **Search** filters on code or name. Editing the search box resets you
  to page one.
- **Include inactive** sets `includeInactive` on the query. Leave it off
  and you see only the codes agents can currently pick; turn it on to
  find and reactivate a retired code.

## Tagging codes

Wrap-up codes are a taggable resource, under the resource kind
`dim_wrap_up_code`. The console resolves tags for the whole visible page
in one request and the Tags cell writes changes back per row. Tags are
metadata for organising the list — they do not affect what agents see or
how a code reports.

## Deactivating a code without breaking history

**Deactivate** in the drawer calls `adminWrapupCodes.remove`, which is a
soft delete: the row's `active` flag goes to `false` and the row stays in
`dim_wrap_up_code`. The confirmation dialog states this directly —
historical call records that reference the code still resolve.

What changes and what does not:

- The code drops out of the default list, so it is no longer offered for
  selection going forward.
- Completed calls already dispositioned with that code are untouched.
  Reports that join through the dimension row keep resolving its `code`,
  `name`, `category`, `is_fcr` and `requires_follow_up`.
- To bring the code back, search with **Include inactive** on, open it,
  and flip the **Active** toggle in the edit drawer. `update` sends
  `active` as part of the patch.

Because deactivation is reversible and preserves joins, prefer it over
trying to clean up a code you no longer want.

## Reading dispositions off call records

A call record references the wrap-up code by the dimension row's `id`,
not by the `code` string. Two consequences:

- You can rename a code (`code` or `name`) without rewriting history. The
  reference still points at the same row, so old calls pick up the new
  label the next time you read them.
- Two codes that happen to share a `code` string across different
  hotline scopes are still distinct rows, and a call record tells them
  apart.

If you need the human-readable disposition in a report or export, join
the call record's wrap-up code id back to `dim_wrap_up_code` and take
`code`, `name`, `category`, `is_fcr` and `requires_follow_up` from the
dimension row. Do not denormalise the label at write time — that is what
makes the rename and deactivate behaviour above safe.

## Related

- [Telephony Metrics](/glossary/metrics) — the contact-centre metrics
  dispositions feed into
- [Telemetry](/platform/telemetry) — where per-call records are persisted
