> For the complete documentation index, see [llms.txt](https://help.resouris.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://help.resouris.com/run-the-roster/cancel-a-session.md).

# Cancel a session

Practical walk-through of the v1.6.8.3 session-cancellation flow (enhancement #55). Cancellations are session-instance scoped — you cancel ONE (room, day, half) slot at a time. Whole-clinic retirement is a separate concept, tracked as enhancement #56.

**Who can do this**: any role holding `roster.update` (default: `rostering_manager`, `platform_admin`, `tenant_admin`). No new permission was added.

***

## Cancel a single session

1. Go to **Rosters → Rooms grid** (`/ui/rosters/{roster_id}/spaces`).
2. Find the cell you want to cancel — a filled cell (with staff) or an empty cell both work.
3. **Right-click the cell** OR **click the `⋯` button** in the top-right corner.
4. Pick **⊗ Cancel this session…**
5. In the modal:
   * **Reason** — pick from the closed set (see below). The reason drives a default for the "Release staff" checkbox.
   * **Release staff from this slot** — the tick is pre-set from your reason; you can always override.
   * **Notes** — optional (≤500 chars), captured for audit but never surfaced to affected staff.
6. Click **Cancel session**.

The cell renders greyed-out with a red **⊗ CANCELLED** banner + the reason label. If you preserved staff, their names appear crossed-out under the banner.

## The 6 reasons + their default staff-handling

| Reason                | Default action  | When to use                                                                                               |
| --------------------- | --------------- | --------------------------------------------------------------------------------------------------------- |
| **Equipment broken**  | ✓ release staff | The room's equipment is out of service; staff can be redeployed same-day.                                 |
| **No staff cover**    | preserve        | You tried to fill the slot but couldn't; the shortage IS why the session isn't running — keep the record. |
| **Low demand**        | preserve        | Patient list didn't fill; staff still came in (typical NHS payment applies).                              |
| **Venue unavailable** | ✓ release staff | Room is closed (maintenance, deep clean, contamination) — staff can be redeployed.                        |
| **Operator decision** | preserve        | Ad-hoc management decision. Safest default: preserve the record.                                          |
| **Other**             | preserve        | Catch-all. Safest default.                                                                                |

**Preserve semantics** — assignment rows stay in place. UI renders them crossed-out under the CANCELLED banner. Payroll can decide whether to pay. SUS/PBR reporting sees the originally-scheduled staff.

**Release semantics** — assignment rows are DELETED. The cancellation record retains a copy of the originally-scheduled `staff_ids` in a JSONB field for audit + potential restoration.

## Un-cancel a session

Made a mistake? Or the equipment came back sooner than expected?

1. Right-click the cancelled cell → **↺ Un-cancel this session**.
2. Done. The cancellation flips (its `un_cancelled_utc` is stamped) and the cell renders normally again.

**Note**: un-cancel does NOT restore assignments you previously released. If you had staff, ticked "Release staff", and then un-cancelled, you have to re-add them via the manual-add flow (right-click → ⋯ → **Add another person…**).

## What gets audited

Every cancellation emits a `roster.slot.cancelled` audit event with payload:

* `revision_id`, `room_id`, `iso_date`, `half`
* `reason`
* `release_staff` (bool — was the checkbox ticked?)
* `notes` (first 200 chars)

Every un-cancel emits a `roster.slot.un_cancelled` event.

## When cancellations disappear

Cancellations are tied to the **published roster revision**. When a roster is re-solved and re-published, the new revision starts with a clean slate — cancellations from the previous revision don't carry over.

This is deliberate. A re-solve may have already accounted for the reason (moved the staff, re-scheduled the session elsewhere). If the new solve still has the problem slot, the operator re-cancels — with fresh reason + fresh audit trail — on the new revision.

## Related surfaces

* **Availability view** and **My Team calendar** — do not currently render cancellation markers (cancellations are a rooms-grid concept). The affected staff's availability status is unchanged (they're still "rostered" from those views' perspective if you chose to preserve; they revert to "available" if you released). Future enhancement.
* **Trust Admin sessions** — cancellation does NOT auto-update the Trust Admin status for the affected service\_line. If you cancel a session that had status='started\_incomplete', the status stays until you separately update it.

## Rejected alternatives (for context)

* **Clinic-flag placeholder** — creating one "Session Cancelled" clinic per tenant and using it as an assignment SL — rejected because it pollutes the clinic catalogue, can't cancel a slot with pre-existing staff without a two-step delete, and semantically conflates "type of clinical work" with "state of a session".
* **Extending `assignments.origin` with 'cancelled'** — would require nullable `staff_id`, which ripples too far through the solver + readers.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://help.resouris.com/run-the-roster/cancel-a-session.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
