User Journey: Draw the reporting line

Table of Contents

This page documents a user journey: A tenant administrator maintains who reports to whom.

A user journey describes what one person is trying to do, before anything is built. It is a design document that outlives any sprint, so it names the screens, the entity fields each screen shows, and the operations and messages each step needs.

1. Goal

"I want to see the shape of my organisation, and fix the line that is wrong." The administrator sets who each person reports to and reads the result as a tree. The journey is done when every person sits under the right manager and the tree has no surprises: no orphan who should have a manager, no loop.

2. Actor and trigger

The tenant administrator, acting inside their tenant. The trigger is a joiner, a leaver, or a person who changed desk. It starts when the administrator opens Reporting lines, and ends when they leave the tree.

The value of the journey is the shape, not the row. Today the field is edited one account at a time, from the account's detail screen, and the shape only appears when the administrator holds it in their head.

3. Steps

  1. Open the reporting view. The administrator chooses Reporting lines. The system reads every account in the tenant and draws one card per person, connected to the account they report to.
  2. Read the shape. The system lays the tree out by reporting depth: roots at the top, each manager above the people who report to them. The administrator sees the branches, and who has no manager.
  3. Pick a person. The administrator selects a card. The system shows the account behind it: full name, job title, current manager, and the party they work in.
  4. Set the manager. The administrator chooses another account in the tenant and saves. The system records the change reason, writes a new account version, and redraws the tree.
  5. Clear a line. When a person leaves a team with no successor, the administrator clears the manager. The system records the same way and the person becomes a root.
  6. Leave. The administrator goes back. The next reader of the account sees the new line.

Every step ends in a reply; nothing is queued. The journey holds no state of its own, and the tree the administrator sees is assembled by the client from a flat read, not fetched as a tree.

4. Screens and wireframes

One screen with three panels: the tree, the selected account, and the save controls with their change reason. The tree is the point of the screen; the other two panels exist to change it.

wireframe_reporting_line.png

Figure 1: Reporting lines: the reporting tree, the selected account's line, and the save controls with a change reason.

The tree panel is drawn from a flat list. The wireframe says so, because it decides what the screen can promise: no subtree can be fetched on its own, so the screen reads the whole roster and nests it.

5. Entities composed

Entity What it contributes Model
account Full name, job title, and the reporting line itself ores.iam.account
account_party The party a person works in, shown on the card as their office ores.iam.account_party

The reporting line is one field on the account: reports_to_account_id is a nullable soft self-reference to another row in the same table. There is no edge table and no separate hierarchy model. The reference is validated by foreign key, so a manager must exist; nothing else about the pair is validated.

The tree this journey draws is the reporting line between people. It is not the business unit tree, which places books and desks rather than people, and the account carries no business unit at all.

6. Operations and messages

Step Operation Subject Status
Open the reporting view Read the tenant roster and every account's manager iam.v1.accounts.list exists
Read the shape Read the party each person works in iam.v1.account_parties.list_by_account_id exists
Set the manager Set reports_to_account_id iam.v1.accounts.update partial
Set the manager Read the change reasons for the picker dq.v1.change_reasons.list exists
Clear a line Clear reports_to_account_id iam.v1.accounts.update partial

iam.v1.accounts.update is the only writer of the field, and it is declared in ores.iam.account_messages.org: reports_to_account_id must be empty or name another account in the same tenant. partial here means the operation exists but covers more than this step: it needs iam::accounts:update, and its body carries the email, full name, default party, job title and image as well. A caller that changes the reporting line alone must send the other fields back unchanged, as projects/ores.http/core/src/routes/iam_routes.cpp does today.

7. What is missing

  1. No tree read. The server answers one flat page of accounts with reports_to_account_id repeated per row. There is no subject that returns the reporting structure: no children-by-manager read, no depth, no root list, no subtree. Everything the screen shows about shape it computes in the browser, and the whole roster has to arrive first. The candidate is a tree read, for example iam.v1.accounts.reporting_tree, returning each account's manager and depth, so a large tenant can page a branch rather than the world.
  2. No cycle check. The handler validates the manager's UUID format and the foreign key validates that the account exists. Nothing refuses A reports to B when B already reports to A. The server accepts the pair, and the result is a loop that has no root. Until a check exists, the client must detect the loop and show it rather than draw it.
  3. No reporting-line-only write. Setting one field means sending the whole update_account_request, so the screen must carry every other field it read. A concurrent edit to the job title is silently overwritten by the stale copy the screen holds. The candidate is either a narrow subject or a stated precondition on the account version.
  4. Nothing in the web client ships the screen. The generated account declaration marks the field as a column, and wire-protocol/src/operations.ts maps it, but no web screen draws a tree or offers a manager picker. The Qt client did: OrgChartWidget, added for Acme staff, read every tenant account and drew one card per person connected by reports_to_account_id, and it was removed with the ores.qt tree. This journey is that screen, rebuilt against the web client and the canonical protocol.
  5. Party names are still unreachable. The card shows the office, which needs the party's name; the account-party read carries party_id alone. This is the same gap as on Choose where I work, and the first branch to fix, because both journeys show a party and neither can name one.
  6. No history of the line. The account is versioned, so a change is recoverable through iam.v1.accounts_versions.list, but the tree screen states none of it. An administrator who is asked "who did this person report to last quarter" has no answer on this screen.

8. Related journeys

  • See who has access — the roster is where a person is picked, and it shows the roles and status the card does not.
  • Change someone's details — the reporting line is a field on that screen, so the rest of the person's record is corrected there.
  • Choose where I work — each card shows the party a person works in, and that party is chosen there.
  • Bring someone in — a joiner arrives with no manager, so the new account is created there before the line is drawn here.

9. Related knowledge

10. See also

Emacs 29.3 (Org mode 9.6.15)