Task: Let the booking form state a draft
Table of Contents
This page documents a task in the Book a trade as a draft story. It captures the goal, current status, acceptance, and any notes or results.
1. Goal
(Describe what user-visible-or-internal change this task produces.)
2. Status
| Field | Value |
|---|---|
| State | DONE |
| Parent story | Book a trade as a draft |
| Now | Nothing. |
| Waiting on | Nothing. |
| Next | Nothing. |
| Last touched | 2026-11-01 |
3. Acceptance
- The booking form takes a draft reason from the lookup, and books live when none is chosen.
- A draft booking writes the
draft_captureactivity and the reason on the trade. - The reasons are read through a route of their own, so the form offers what the store holds.
4. Plan
Three small pieces. A route that reads the draft reasons, because a form must
offer what the store holds rather than a list written into the screen. A field on
the booking body, and the trade's own column behind it. And the activity: a
booking that states a reason is captured with draft_capture, which is the
transition that stops the state machine at draft.
The rule lives where it already lived. The trading service refuses a
draft_capture with no reason and refuses a reason on a trade that goes live, so
the form states a reason or nothing, and the service decides.
5. Measurements
Every number this task claims about a tree, with the command that produced it
and the commit it was measured at. A number without both is not a measurement,
because a clean-up record describes a tree and trunk moves under a branch: a
consumer count, a gate's component count and a suite's size all change with no
code changing, and the reader of a bare number cannot tell which tree it came
from. Where the raw output matters, put it in an evidence/ file beside the
task and name that file in the Command column.
| What | Value | Command | Commit |
|---|---|---|---|
6. Notes
7. Test Scenarios
Manual QA scenarios (scaffolded via compass add test_scenario)
that verify this task. Link
new ones here as they're created; the scenario doc itself links back
via its "Verifies task" field.
| Scenario | State | Notes |
|---|---|---|
8. PRs
9. Review
| Comment summary | File | Decision | Notes |
|---|---|---|---|
10. Result
A booking states whether the deal it captures is a draft, and why it waits.
| Piece | Where |
|---|---|
| The reasons | GET /api/draft-reasons reads the lookup: the code, what it waits on, and the desk |
| The body | draftReasonCode, absent means the trade goes live at once |
| The activity | draft_capture when a reason is stated, new_booking otherwise |
| The trade | the reason on the anchor, so a report of aged drafts reads it beside the deal |
| The cases | a draft booking writes the draft activity and the reason; a booking with no reason still writes new_booking and none |
The rule is the trading service's, where it already lived: a draft_capture with
no reason is refused, and a reason on a trade that goes live is refused.
What this unblocks: the completion executes drafts, and until now no screen could make one, so the path it exists for — capture two deals as drafts, group them, and watch each one ask Operations — had no way in.