Skip to content

Assignments Workflow

1. Executive Summary

Purpose

The assignments workflow provides the mechanism by which UTA staff are connected to the entities they are accountable for — whether those are long-lived organizational entities (departments, clients, buyers, deals, sales items, payment terms) or transient financial work items (cash receipts, cash receipt splits, outbound payments). There are two structurally different kinds of assignment: a responsibility establishes lasting single-owner accountability for a business entity and resolves upward through a four-level organizational hierarchy when no direct owner exists; a task tracks a specific piece of work that needs to be done against a transactional entity, progresses through a forward-only status lifecycle, and may have multiple concurrent holders. Together these two mechanisms ensure that every open receivable, unprocessed receipt, and pending payment can be traced to a responsible person, and that ad-hoc work is explicitly handed off rather than silently dropped.

Scope

Covered:

  • Creating and transferring responsibility assignments for departments, clients, buyers, deals, meta-data pairs, sales items, and payment terms
  • Creating, updating, and progressing task assignments for cash receipts, cash receipt splits, and payment items
  • Viewing all assignments for a given person (By Person view)
  • Viewing the responsibility chain and tasks for a specific entity (By Entity view)
  • Identifying unassigned entities with open receivables or work needing attention (Unassigned view)
  • Hierarchy resolution: automatically determining the accountable person by walking up from the most specific entity to the broadest when no direct assignment exists
  • Full audit trail via assignment_history

Not covered (documented separately):

Key Objectives

  • Ensure every open billing item can be traced to a responsible UTA staff member, either through a direct assignment or through the hierarchy fallback chain.
  • Provide a unified work queue so individuals can see all tasks and responsibilities assigned to them in one place.
  • Surface unassigned entities to supervisors so ownership gaps are detected and corrected quickly.
  • Maintain a tamper-resistant audit trail of every assignment creation, transfer, and status change.

2. Process Overview

mermaid
flowchart TD
    A[Open Assignments screen] --> B{Choose view}
    B --> |By Person| C[Select person]
    B --> |By Entity| D[Select entity type & entity]
    B --> |Unassigned| E[Browse unassigned entities]

    C --> F[View responsibilities + tasks]
    F --> G{Action needed?}
    G --> |Transfer responsibility| H[Open Transfer dialog]
    G --> |Progress task status| I[Update task status]
    G --> |Edit task| J[Edit title / assignee / due date]
    G --> |View history| K[Open History dialog]
    H --> L[Service: transferResponsibility]
    I --> M[Service: updateTaskStatus]
    J --> N[Service: updateTask]

    D --> O[Load responsibility chain + tasks]
    O --> P{Hierarchy gap?}
    P --> |Yes, assign| Q[Open Assign Responsibility dialog]
    P --> |Yes, transfer| R[Open Transfer dialog]
    O --> S[View entity tasks]
    S --> T[Progress or cancel tasks]

    E --> U[Load unassigned summary counts]
    U --> V[Select entity type]
    V --> W[View unassigned list]
    W --> X{Quick assign?}
    X --> |Quick assign person selected| Y[One-click assign responsibility or task]
    X --> |No| Z[Open Assign/Create Task dialog]
    Y & Z --> AA[assignment created / refreshed]

    subgraph New Assignment
        AB[Open Assign Responsibility dialog] --> AC[Select person + entity type + entity]
        AC --> AD[Service: createResponsibility]
        AE[Open Create Task dialog] --> AF[Title + person + entity type + entity + due date]
        AF --> AG[Service: createTask]
    end

Walkthrough

  1. Enter the Assignments screen — The screen loads at /assignments with three tabs: By Person, By Entity, and Unassigned. An "Assign" dropdown in the header allows creating a new Responsibility or Task from any tab.

  2. By Person view — The user selects a person from the dropdown. The system loads all active responsibilities and all tasks (filtered to OPEN, WORKING, WAITING by default) for that person in two separate tables. Summary counts show how many responsibilities, open tasks, working tasks, and waiting tasks the person holds. From this view the user can transfer a responsibility, progress a task status, edit a task, or view the audit history for any assignment.

  3. By Entity view — The user selects an entity type and then searches for a specific entity. The system loads the full responsibility chain for that entity (all hierarchy levels from L1 Department to L4 Sales Item / Payment Term, showing who is assigned at each level and who the effective responsible person is) together with a list of active tasks against that entity. The user can assign or transfer responsibility at any chain level and create or progress tasks.

  4. Unassigned view — The system displays summary counts of unassigned entities across all nine entity types. The user selects an entity type (e.g., CLIENT, DEAL, CASH_RECEIPT) and optionally filters by department or coverage level. The table shows entities that have no active assignment and still need attention (open receivables for responsibility types; unprocessed receipts/splits or pending/failed payments for task types). The user can assign inline via a quick-assign person selector or open a dialog.

  5. Create Responsibility — User selects entity type and specific entity via autocomplete, selects the responsible person, and saves. The service validates that no active responsibility already exists for that entity before creating the record.

  6. Transfer Responsibility — User opens the Transfer dialog for an existing responsibility, selects the new person, and optionally enters a reason. The service deactivates the old assignment and creates a new one, recording both a DEACTIVATED history entry on the old record and a REASSIGNED entry on the new record.

  7. Create Task — User enters a title, selects the entity type and specific entity, selects an assignee, and optionally sets a due date. Tasks are always initialized to OPEN. Multiple tasks can exist for the same entity simultaneously.

  8. Progress Task Status — Assignees use inline action buttons (Start, Complete, Pause, Resume) or the status dropdown to move a task through its lifecycle: OPENWORKINGCOMPLETE (or WAITINGWORKINGCOMPLETE). Each transition records a STATUS_CHANGED history entry.

  9. Sibling cancellation — When a task is completed, the caller may invoke sibling cancellation to cancel all other active tasks for the same entity, preventing duplicate work.


3. Business Rules

3.1 Exactly One Active Responsibility Per Entity

Business rule: At any point in time, exactly one active responsibility may exist for a given entity. Attempting to directly create a second responsibility for an entity that already has one is rejected; the Transfer procedure must be used instead.

Foundation reference: One-active-responsibility-per-entity constraint — enforced at the application layer in createResponsibility Step 1 (check for existing active record).

Workflow context: The Assign Responsibility dialog returns an error when the service rejects a duplicate creation: "An active responsibility already exists for this entity. Use transfer instead." In the By Entity chain panel, a level that already has an owner shows only a "Transfer" button — there is no second "Assign" button at that level.


3.2 Responsibility Transfer Uses Deactivate-Then-Create Pattern

Business rule: Transferring a responsibility does not update the existing assignment row in place. Instead it deactivates the old record (assignment.is_active_ind set to false) and creates a new one, preserving the full chain of ownership in immutable history.

Foundation reference: Transfer Responsibility procedure

Workflow context: The Transfer dialog shows the current assignee's name alongside the entity context so the user confirms they are transferring the correct record. The new assignee selector explicitly excludes the current assignee to prevent self-transfer. The dialog description reads "The current assignment will be deactivated and a new one created."


3.3 Task Status Transitions Are Forward-Only

Business rule: A task can only move forward through its status lifecycle (OPENWORKINGCOMPLETE; WORKINGWAITING). Once a task reaches COMPLETE or CANCELLED, no further transitions are permitted.

Foundation reference: Task status transition rules — the allowed matrix is enforced in updateTaskStatus Step 1 before any write occurs.

Workflow context: The inline action buttons presented to the user always reflect the current status: only valid next actions are shown. A task in COMPLETE or CANCELLED status shows no action buttons. An attempt to call an invalid transition returns an error toast.


3.4 Multiple Tasks Are Allowed Per Entity

Business rule: Unlike responsibilities, multiple task assignments can be created for the same entity simultaneously. This supports scenarios where several users are independently working on the same receipt, split, or payment.

Foundation reference: Task multiplicity — no uniqueness check is performed during task creation.

Workflow context: The By Entity view shows all active tasks for an entity in a table so supervisors can see concurrent assignments. The Unassigned tab removes a task entity from the list only when the entity has at least one active non-terminal task assignment.


3.5 Hierarchy Resolution Walks From Most Specific to Broadest

Business rule: When the system needs to identify the responsible person for an entity, it checks for a direct assignment first, then walks up the four-level hierarchy until it finds a match. The resolution order is: Level 4 (Sales Item, Payment Term) → Level 3 (Meta-Data Pair, Deal) → Level 2 (Client, Buyer) → Level 1 (Department). The first match found is the effective responsible person.

Foundation reference: Hierarchy Resolution Walk-Up

Workflow context: The Responsibility Chain panel in the By Entity view shows every level in the hierarchy for the selected entity, highlights the effective level with a green indicator, and shows the resolved user name at the bottom. Unassigned entities in the Unassigned tab show a "Coverage" badge indicating the nearest ancestor level that has an assignment (e.g., "via Client", "via Dept", "Unowned").


3.6 Task-Level Entities Do Not Participate in the Hierarchy

Business rule: CASH_RECEIPT, CASH_RECEIPT_SPLIT, and PAYMENT entity types are used only for task assignments. They do not appear in the responsibility hierarchy chain. Responsibility hierarchy resolution applies only to the organizational levels (Department, Client, Buyer, Deal, Meta-Data Pair, Sales Item, Payment Term).

Foundation reference: entity_type_cd code master values


3.7 Sibling Cancellation Is Explicit, Not Automatic

Business rule: Completing a task does not automatically cancel sibling tasks. Sibling cancellation is a separate, explicitly invoked operation. The caller decides whether to trigger it after marking a task COMPLETE.

Foundation reference: Cancel Sibling Tasks procedure

NOTE

PoC Artifact: In the PoC, sibling cancellation is available as a server action (cancelSiblingTasks) but the UI does not explicitly prompt the user to cancel siblings after completing a task. The production system should expose a clear "Cancel sibling tasks?" confirmation after task completion.


3.8 Assignment History Is Immutable

Business rule: Every create, transfer, status change, and cancellation produces exactly one row in assignment_history. These records are never updated or deleted.

Foundation reference: assignment_history table definition

Workflow context: The History dialog (accessible from the task row overflow menu in the By Person view) shows all history entries in reverse chronological order, with action_cd, status transitions, user-to-user transfers, timestamps, and any comment text.


3.9 Unassigned Entities Filter to "Needs Attention" Only

Business rule: The Unassigned tab does not list every entity without an assignment — it lists only those that have open work needing attention. For responsibility types this means entities with at least one open billing item with a positive REV balance. For task types (cash receipts and splits) this means entities whose worksheet status is not fully approved or whose applied amount does not equal the receipt/split amount. For payment tasks this means payments in WAITING, PENDING, or FAILED status.

Foundation reference: Unassigned Entities by Type query — "needs work" determination per entity type.


4. Data Access & Operations References

4.1 Queries Used

OperationFoundation DocPurpose in This Workflow
getAssignmentByIdGet Assignment by IDLoad a specific assignment when opening the Transfer dialog from the By Entity chain panel.
getAssignmentDisplayByIdGet Assignment Display by IDEnrich assignment records with assignee name and email for display.
getAssignmentsForUserGet Assignments for UserLoad all responsibilities and tasks for the selected person in the By Person view.
getAssignmentsForEntityGet Assignments for EntityLoad all tasks for a selected entity in the By Entity view.
findActiveResponsibilityFind Active ResponsibilityCheck for an existing active responsibility before creating a new one; used per-level in chain resolution.
findSiblingTasksFind Sibling TasksIdentify other active tasks for the same entity when performing sibling cancellation.
resolveResponsibleUserHierarchy Resolution Walk-UpDetermine the effective responsible person for an entity by walking up the hierarchy.
buildResponsibilityChainResponsibility ChainBuild the full per-level responsibility picture for the By Entity chain panel.
getHistoryForAssignmentGet History for AssignmentPopulate the History dialog with enriched audit trail entries.
getUnassignedEntitiesByTypeUnassigned Entities by TypePopulate the Unassigned tab data table for the selected entity type.
getUnassignedSummaryUnassigned SummaryLoad the summary chip counts on mount in the Unassigned tab.

4.2 Procedures Used

OperationFoundation DocTrigger in This Workflow
createResponsibilityCreate Responsibility AssignmentUser submits the Assign Responsibility dialog (from header dropdown, By Entity assign button, or Unassigned tab assign button).
transferResponsibilityTransfer Responsibility AssignmentUser submits the Transfer Responsibility dialog (from By Person "Transfer" button or By Entity chain "Transfer" button).
createTaskCreate Task AssignmentUser submits the Create Task dialog (from header dropdown, By Entity "Create Task" button, Unassigned tab "Assign Task" button, or quick-assign).
updateTaskStatusUpdate Task StatusUser clicks Start / Complete / Pause / Resume action buttons or selects a status from the status dropdown on a task row.
updateTaskUpdate Task FieldsUser submits the Edit Task dialog (from the overflow menu on a task row in the By Person view).
cancelSiblingTasksCancel Sibling TasksExplicitly invoked after a task is completed via the cancelSiblingTasks server action.
resolveResponsibilityChainResponsibility Chain ResolutionTriggered when the user selects an entity in the By Entity tab to load the full hierarchy chain.

5. Key User Actions

5.1 Assign Responsibility

Preconditions:

  • No active responsibility exists for the target entity. (If one exists, the Transfer action must be used instead.)
  • A valid entity type and specific entity must be selected.
  • A person to assign must be selected.

Procedure reference: Create Responsibility Assignment

Steps:

  1. User opens the "Assign Responsibility" dialog from the "Assign" dropdown in the page header, from an "Assign" button in the By Entity chain panel, or from an "Assign" button in the Unassigned tab.
  2. User selects the assignee from the person dropdown.
  3. User selects the entity type (e.g., CLIENT (L2), DEAL (L3)). If the dialog was opened from a chain or unassigned row, entity type and entity are pre-filled and locked.
  4. User searches for and selects the specific entity via the autocomplete field. For META_DATA_PAIR entity types the user enters a meta type code and meta value manually.
  5. User clicks "Assign Responsibility". The service checks for an existing active responsibility and rejects with an error if one is found; otherwise it inserts the new assignment row and its ASSIGNED history entry.

Postconditions:

  • New assignment row with assignment_type_cd = 'RESPONSIBILITY', is_active_ind = true, assigned_to_user_id = selected user.
  • New assignment_history row with action_cd = 'ASSIGNED', to_user_id = selected user.
  • Success toast; dialog closes; parent view refreshes.

UI trigger: "Assign Responsibility" item in the "Assign" dropdown. Visible always in the page header. "Assign" button in the Responsibility Chain panel: visible for hierarchy levels that have no current assignment. "Assign" button in the Unassigned tab responsibility rows: visible for all unassigned responsibility-type entities.


5.2 Transfer Responsibility

Preconditions:

  • An active RESPONSIBILITY assignment (assignment.is_active_ind = true) must exist for the entity.
  • The new assignee must differ from assignment.assigned_to_user_id.

Procedure reference: Transfer Responsibility Assignment

Steps:

  1. User clicks the "Transfer" button on a responsibility row in the By Person view, or the "Transfer" button on a populated level in the By Entity chain panel.
  2. The Transfer Responsibility dialog opens showing the current entity context and the current assignee's name.
  3. User selects the new assignee (the current assignee is excluded from the dropdown).
  4. User optionally enters a transfer reason in the text area.
  5. User clicks "Transfer". The service deactivates the old assignment, records a DEACTIVATED history entry, creates the new assignment, and records a REASSIGNED history entry.

Postconditions:

  • Old assignment row: is_active_ind = false.
  • New assignment_history row on old assignment: action_cd = 'DEACTIVATED', from_user_id = previous owner.
  • New assignment row: is_active_ind = true, assigned_to_user_id = new owner.
  • New assignment_history row on new assignment: action_cd = 'REASSIGNED', from_user_id = previous owner, to_user_id = new owner.
  • Success toast; dialog closes; parent view refreshes.

UI trigger: "Transfer" button in the By Person responsibilities table. Visible for every active responsibility row. "Transfer" button inside each populated level row in the Responsibility Chain panel: visible when assignment is not null at that level.


5.3 Create Task

Preconditions:

  • A task title must be provided (minimum 1 character).
  • An assignee must be selected.
  • An entity type and specific entity must be identified.

Procedure reference: Create Task Assignment

Steps:

  1. User opens the "Create Task" dialog from the "Assign" → "Create Task" dropdown, from the "Create Task" button in the By Entity tasks section, or from the "Assign Task" button in the Unassigned tab for task-type entities.
  2. User enters a task title. When pre-filled from the Unassigned tab, the title defaults to "Clear Cash Receipt", "Clear Cash Split", or "Process Payment" based on entity type.
  3. User selects the assignee.
  4. User selects the entity type and specific entity (pre-filled and locked when launched from context).
  5. User optionally sets a due date (assignment.end_dt).
  6. User clicks "Create Task". The service inserts the new assignment row (task_status_cd initialized to 'OPEN') and its ASSIGNED history entry.

Postconditions:

  • New assignment row with assignment_type_cd = 'TASK', task_status_cd = 'OPEN', is_active_ind = true, assigned_to_user_id = selected user.
  • New assignment_history row with action_cd = 'ASSIGNED', to_user_id = selected user.
  • Success toast; dialog closes; parent view refreshes.

UI trigger: "Create Task" item in the "Assign" dropdown (always visible). "Create Task" button in the By Entity tasks section (visible when an entity is selected). "Assign Task" button in Unassigned tab task-type rows. Quick-assign path: if a person is selected in "Quick Assign To", clicking "Assign Task" creates the task immediately without opening the dialog.


5.4 Update Task Status

Preconditions:

  • assignment.assignment_type_cd = 'TASK'.
  • Requested transition must be valid per the task status state machine.
  • Task must not be in a terminal state (COMPLETE or CANCELLED).

Procedure reference: Update Task Status

Steps:

  1. User clicks an inline action button (Start / Complete / Pause / Resume) or selects a status from the status dropdown on the task row.
  2. The service validates the transition against the allowed matrix, updates assignment.task_status_cd, and inserts a STATUS_CHANGED history entry.

Postconditions:

  • assignment.task_status_cd updated to the new status.
  • New assignment_history row with action_cd = 'STATUS_CHANGED', from_status_cd = previous status, to_status_cd = new status.
  • Success toast; task row reflects new status.

UI trigger: "Start Working" (play icon) — visible when task_status_cd = 'OPEN'. "Complete" (check icon) and "Pause" (pause icon) — visible when task_status_cd = 'WORKING'. "Resume" (play icon) — visible when task_status_cd = 'WAITING'. Status dropdown — clickable on any non-terminal status badge. "Cancel Task" in overflow menu — visible for OPEN, WORKING, or WAITING statuses.


5.5 Edit Task

Preconditions:

  • assignment.assignment_type_cd = 'TASK'.
  • A non-empty task title and an assignee must be provided.

Procedure reference: Update Task Fields

Steps:

  1. User selects "Edit Task" from the overflow menu on a task row in the By Person view.
  2. The Edit Task dialog opens pre-populated with current assignment.task_title, assignment.assigned_to_user_id, and assignment.end_dt. Entity type and entity are displayed read-only and cannot be changed.
  3. User modifies the title, assignee, and/or due date.
  4. User clicks "Save Changes". The service updates the editable fields. If the assignee changed, a REASSIGNED history entry is recorded.

Postconditions:

  • assignment row updated with new task_title, assigned_to_user_id, and/or end_dt.
  • If assignee changed: new assignment_history row with action_cd = 'REASSIGNED', from_user_id = old assignee, to_user_id = new assignee.
  • If only title or due date changed: no history entry is created.

UI trigger: "Edit Task" item in the overflow (three-dot) menu on task rows in the By Person view. Visible for all task assignments.

NOTE

PoC Artifact: Title and due date changes do not produce a history entry in the PoC. The production system should audit all field changes for compliance.


5.6 View Assignment History

Preconditions:

  • An assignment record must exist.

Procedure reference: Get History for Assignment

Steps:

  1. User selects "View History" from the overflow menu on a task row in the By Person view.
  2. The History dialog loads all assignment_history rows for the selected assignment in reverse chronological order, enriched with from_user_name, to_user_name, and action_by_user_name.
  3. Each entry shows action_cd, status transitions, user-to-user moves, the acting user's name, the timestamp (action_dt), and any comment_text.

Postconditions:

  • No data is mutated. Read-only display.

UI trigger: "View History" item in the overflow menu on task rows in the By Person view. Visible for all task assignments.


5.7 Quick Assign (Unassigned Tab)

Preconditions:

  • A person must be selected in the "Quick Assign To" selector in the Unassigned tab.
  • The target entity must appear in the unassigned list for the selected entity type.

Procedure reference: For responsibility types: Create Responsibility Assignment. For task types: Create Task Assignment.

Steps:

  1. User selects a person in the "Quick Assign To" dropdown. The assign buttons in the table change visual style to indicate quick-assign mode is active.
  2. User clicks "Assign" (responsibility types) or "Assign Task" (task types) on a row.
  3. The system creates the assignment immediately without opening a dialog. For task types, a default title is used ("Clear Cash Receipt", "Clear Cash Split", or "Process Payment").
  4. The row disappears from the unassigned list; summary chip counts update.

Postconditions:

  • Same postconditions as "Assign Responsibility" (5.1) or "Create Task" (5.3) depending on entity type.
  • Success toast with entity display name.

UI trigger: "Assign" / "Assign Task" buttons in the Unassigned table rows. When no Quick Assign person is selected, the same buttons open the full dialog instead.


6. Permissions & Role-Based Access

NOTE

PoC Artifact: The PoC does not implement role-based access control on the Assignments screens. All authenticated users can perform all actions. The table below describes the intended production access model based on the role definitions and the nature of each action.

ActionCASH_MANAGERCASH_PROCESSORSETTLEMENT_APPROVERIT
View assignments (By Person, By Entity, Unassigned)YesYesYesYes
Assign responsibility (any entity type)Yes
Transfer responsibilityYes
Create task (any entity type)YesYesYesYes
Update task statusYesYesYesYes
Edit task (title, assignee, due date)YesYesYesYes
View assignment historyYesYesYesYes
Quick assign (Unassigned tab)YesYesYesYes
Cancel sibling tasksYesYesYesYes

Field-level restrictions:

  • The entity type and specific entity on a task assignment cannot be changed after creation; only task_title, assigned_to_user_id, and end_dt are editable.
  • Responsibility assignment and transfer are restricted to IT/Admin in the intended production model, reflecting that changing long-lived ownership of clients, deals, and departments is an administrative act rather than a daily operational one.

7. Integration Points

7.1 Upstream

SourceData ProvidedMechanism
Cash Receipts workflowcash_receipt.cash_receipt_id and cash_receipt_split.cash_receipt_split_id used as entity keys for task assignmentsPolymorphic FK via assignment.entity_id when entity_type_cd = 'CASH_RECEIPT' or 'CASH_RECEIPT_SPLIT'
Worksheets workflowcash_receipt_worksheet.worksheet_status_cd used in the "needs work" determination for unassigned receipts and splitsLEFT JOIN in unassigned gap-detection query
Settlements / Payments workflowpayment_item.payment_item_id used as entity key for payment task assignments; payment_item.payment_execution_status_cd used to filter actionable paymentsPolymorphic FK via assignment.entity_id when entity_type_cd = 'PAYMENT'
Deals and Bookingsdeal.deal_reference, revenue_items.sales_item_ref, billing_item.payment_term_ref used as string-based entity keys for Level 3 and Level 4 responsibility assignmentsassignment.entity_reference
Partiesparty.party_id used as entity key for CLIENT and BUYER responsibility assignmentsassignment.entity_id
Departmentsdepartment.department_id used as entity key for DEPARTMENT responsibility assignmentsassignment.entity_id
Billing Itemsbilling_item and billing_item_detail used in REV balance calculation for unassigned gap detectionJOIN in open_rev_details CTE across billing_item, billing_item_detail, cash_receipt_application, cash_receipt_application_deduction

7.2 Downstream

ConsumerData ConsumedMechanism
Cash Receipts workflowActive assignment records for CASH_RECEIPT and CASH_RECEIPT_SPLIT entity types — used to identify who is responsible for processing a receipt or splitFK lookup via assignment.entity_id
Payments workflowActive assignment records for PAYMENT entity type — used to identify who is following up on pending or failed paymentsFK lookup via assignment.entity_id
System-wide hierarchy resolutionActive RESPONSIBILITY assignments at all four hierarchy levels — consulted whenever any downstream service needs to route work or notifications to the correct staff memberresolveResponsibleUser service call

7.3 External Integrations

No external integrations for this workflow. Assignment data is entirely internal to the Client Processing system.


8. Functional Screen Requirements

8.1 Assignments Main Screen

Route: /assignments

Data loading:

  • No initial server-side data fetch on page load. All data is loaded client-side upon tab selection or person/entity selection.

Header Region

The page header shows the page title and an "Assign" dropdown for creating new assignments.

Field / ColumnSourceEditable?Condition
Page title "Assignments"StaticNoAlways visible
"Assign" dropdown buttonStaticNoAlways visible
"Assign Responsibility" menu itemStaticNoAlways visible in dropdown
"Create Task" menu itemStaticNoAlways visible in dropdown

Tab Region

Field / ColumnSourceEditable?Condition
"By Person" tabStaticNoAlways visible
"By Entity" tabStaticNoAlways visible
"Unassigned" tabStaticNoAlways visible

Conditional display:

  • Active tab content is rendered below the tab list. All three tabs are always visible; content loads only for the active tab.

8.2 By Person Tab

Route: /assignments (active tab: By Person)

Data loading:

  • getAssignmentsForUserGet Assignments for User — called twice in parallel when a person is selected: once with assignmentTypeCd = 'RESPONSIBILITY' and isActiveInd = true; once with assignmentTypeCd = 'TASK'.

Person Selector Region

Field / ColumnSourceEditable?Condition
Person dropdownAll active users from users tableYesAlways visible
"N Resp" summary chipComputed: responsibilities.lengthNoVisible once a person is selected
"N Open" summary chipComputed: tasks where task_status_cd = 'OPEN'NoVisible once a person is selected
"N Working" summary chipComputed: tasks where task_status_cd = 'WORKING'NoVisible once a person is selected
"N Waiting" summary chipComputed: tasks where task_status_cd = 'WAITING'NoVisible only when waitingCount > 0

Responsibilities Table

Field / ColumnSourceEditable?Condition
Levelassignment.entity_type_cd (rendered as a badge)NoAlways in table
Entityassignment.entity_reference or #assignment.entity_idNoAlways in table
Sinceassignment.created_dtNoAlways in table
Transfer buttonNo (action)Always in table

Grid features:

  • Sortable columns: none (PoC)
  • Filters: none
  • Row selection: none
  • Pagination: no (max 300px height with scroll)

Conditional display:

  • Responsibilities table is visible when a person is selected and responsibilities.length > 0.
  • "No responsibilities assigned" placeholder shown when the responsibilities list is empty.
  • "+ Assign" button visible at the top right of the section when a person is selected.

Tasks Table

Field / ColumnSourceEditable?Condition
Statusassignment.task_status_cd (clickable dropdown)YesAlways in table
Taskassignment.task_titleNoAlways in table
Entityassignment.entity_type_cd badge + entity key (with hyperlink for certain types)NoAlways in table
Dueassignment.end_dtNoAlways in table; shown in red with warning indicator when overdue
AgeComputed: days since assignment.created_dtNoAlways in table
Action buttonsNo (actions)Context-dependent by task_status_cd
Overflow menuNo (actions)Always in table

Grid features:

  • Sortable columns: none (PoC)
  • Filters: status multi-select; defaults to ['OPEN', 'WORKING', 'WAITING']
  • Row selection: none
  • Pagination: yes when filteredTasks.length > 20

Conditional display:

  • "Start Working" (play icon) button visible when assignment.task_status_cd = 'OPEN'.
  • "Complete" (check icon) and "Pause" (pause icon) buttons visible when assignment.task_status_cd = 'WORKING'.
  • "Resume" (play icon) button visible when assignment.task_status_cd = 'WAITING'.
  • "Cancel Task" menu item in overflow visible when task_status_cd IN ('OPEN', 'WORKING', 'WAITING').
  • "Edit Task" and "View History" always present in overflow menu.
  • Entity link: CLIENT links to /clients/{entityId}; SALES_ITEM and PAYMENT_TERM link to /revenue?salesItemRef=...; CASH_RECEIPT_SPLIT resolves a worksheet link asynchronously.
  • "+ Task" button visible at the top right of the tasks section when a person is selected.

8.3 By Entity Tab

Route: /assignments (active tab: By Entity)

Data loading:

Entity Selector Region

Field / ColumnSourceEditable?Condition
Entity type dropdownStatic list of all 10 entity typesYesAlways visible
Entity autocomplete / search fieldSearches the appropriate table per entity typeYesVisible once an entity type is selected

Responsibility Chain Panel

Field / ColumnSourceEditable?Condition
Level badgeassignment.entity_type_cdNoOne row per resolved hierarchy level
Entity labelResolved from parent entity tables (department.department_name, party.display_name, deal.deal_name, etc.)NoOne row per resolved hierarchy level
Assignee nameassignment.assigned_to_user_name (joined from users)NoVisible when assignment is not null at this level
"(none)" indicatorStaticNoVisible when no active responsibility at this level
"Transfer" buttonNo (action)Visible when assignment is not null at this level
"Assign" buttonNo (action)Visible when assignment is null at this level
Effective responsible person summaryComputed: most specific level with an active assignmentNoAlways visible at the bottom of the chain panel

Conditional display:

  • Chain panel visible when an entity is selected and chain data is loaded.
  • The level row holding the effective assignment is highlighted distinctly (green left border).
  • "No responsible person found" message shown when all levels are unassigned.
  • "No hierarchy data available for this entity type" shown for task-level entity types.

Tasks Section (By Entity)

Field / ColumnSourceEditable?Condition
Statusassignment.task_status_cd (badge only)NoAlways in table
Taskassignment.task_titleNoAlways in table
Assigneeassignment.assigned_to_user_nameNoAlways in table
Dueassignment.end_dtNoAlways in table
Action buttonsNo (actions)Context-dependent by task_status_cd

Grid features:

  • Sortable columns: none (PoC)
  • Filters: only active tasks shown (task_status_cd NOT IN 'COMPLETE', 'CANCELLED')
  • Row selection: none
  • Pagination: yes when activeTasks.length > 20

Conditional display:

  • Tasks section visible when an entity is selected.
  • "No active tasks for this entity" placeholder when the list is empty.
  • "Create Task" button always visible at top right of tasks section when an entity is selected.
  • Action buttons follow the same rules as the By Person tasks table.

8.4 Unassigned Tab

Route: /assignments (active tab: Unassigned)

Data loading:

Summary Chips Region

Field / ColumnSourceEditable?Condition
Responsibility type chips (Department, Client, Buyer, Deal, Sales Item, Payment Term)getUnassignedSummary count per entity_type_cdNo (clickable filter)Always visible after summary loads
Task type chips (Cash Receipt, Cash Split, Payment)getUnassignedSummary count per entity_type_cdNo (clickable filter)Always visible after summary loads

Clicking a chip sets the active entity type and reloads the data table.

Filters Region

Field / ColumnSourceEditable?Condition
Entity Type dropdownStatic list of all entity typesYesAlways visible
Filter by Department autocompletedepartment table searchYesVisible for CLIENT, BUYER, DEAL, SALES_ITEM, PAYMENT_TERM entity types
Quick Assign To person selectorAll active usersYesAlways visible
Coverage filter chipsStatic per entity typeYesVisible when coverage options exist for the selected entity type

Unassigned Entities Table — Responsibility Types

Field / ColumnSourceEditable?Condition
EntityEntity display name from the appropriate source table; assignment.entity_reference shown as sub-labelNoAlways in table
Departmentdepartment.department_name resolved via billing_itemNoVisible for non-DEPARTMENT entity types
CoverageComputed: nearest_assignment_level, nearest_assignment_entity_type_cd, nearest_assigned_user_nameNoVisible for non-DEPARTMENT entity types
Open ItemsComputed: COUNT(DISTINCT billing_item_id) with positive REV balanceNoAlways in table
Open AmountComputed: SUM(rev_balance) across open billing item detailsNoAlways in table
Assign buttonNo (action)Always in table

Unassigned Entities Table — Task Types (Cash Receipts, Splits)

Field / ColumnSourceEditable?Condition
Receipt / Splitcash_receipt.cash_receipt_ref or Split #{cash_receipt_split_id}NoAlways in table
Deposit Datecash_receipt.deposit_dtNoAlways in table
Amountcash_receipt.net_receipt_amt or cash_receipt_split.split_amtNoAlways in table
AppliedComputed: sum of cash_receipt_application.cash_receipt_amt_applied on active worksheetsNoAlways in table
BalanceComputed: Amount − AppliedNoAlways in table; highlighted amber when > $0.005
Worksheetcash_receipt_worksheet.worksheet_status_cd (worst status across splits)NoAlways in table
CoverageComputed: nearest responsible ancestor via reference-based coverageNoAlways in table
Assign Task buttonNo (action)Always in table

Unassigned Entities Table — Task Types (Payments)

Field / ColumnSourceEditable?Condition
Paymentpayment_item.payment_item_idNoAlways in table
Pay Datepayment_item scheduled or creation dateNoAlways in table
Amountpayment_item.payment_amtNoAlways in table
Statuspayment_item.payment_execution_status_cdNoAlways in table
OriginDerived from payment_item.payment_item_type_cd (Settlement, Ledger, Refund, Other)No (clickable — opens payment detail drawer)Always in table
Payment Partyparty.display_name for payment_item.party_idNoAlways in table
ClientClient party display nameNoAlways in table
Dealdeal.deal_nameNoAlways in table
CoverageComputed: nearest responsible ancestorNoAlways in table
Departmentdepartment.department_nameNoAlways in table
Assign Task buttonNo (action)Always in table

Grid features (all Unassigned tables):

  • Sortable columns: none (PoC; server sorts by open_receivable_amount descending for responsibility types; by entity date descending for task types)
  • Filters: entity type selector, optional department filter, optional coverage level chips
  • Row selection: none
  • Pagination: enabled when results.length > 20

Conditional display:

  • "No unassigned [entity type]s needing attention" placeholder when no results match the selected type and filters.
  • When coverage filter is active and no results match, placeholder appends "matching this coverage filter".
  • When Quick Assign person is selected, "Assign" / "Assign Task" buttons change to filled style to indicate active quick-assign mode.
  • Clicking the Origin cell on a payment row opens a Payment Execution Drawer showing full payment detail.

9. Additional Diagrams

Task Status State Machine

mermaid
stateDiagram-v2
    [*] --> OPEN : Task created (task_status_cd = 'OPEN')
    OPEN --> WORKING : Begin work
    OPEN --> CANCELLED : Cancel before starting
    WORKING --> WAITING : Blocked on dependency
    WORKING --> COMPLETE : Finish
    WORKING --> CANCELLED : Abandon
    WAITING --> WORKING : Unblocked / Resume
    WAITING --> CANCELLED : Abandon
    COMPLETE --> [*] : Terminal
    CANCELLED --> [*] : Terminal

Responsibility Lifecycle

mermaid
stateDiagram-v2
    [*] --> Active : createResponsibility\nassignment.is_active_ind = true
    Active --> Inactive : transferResponsibility\nis_active_ind set to false\nnew assignment created with is_active_ind = true
    Inactive --> [*] : Preserved for audit

Hierarchy Resolution Sequence

mermaid
sequenceDiagram
    participant UI as User / System
    participant Svc as AssignmentService
    participant DB as Database

    UI->>Svc: resolveResponsibleUser(salesItemRef, dealRef, clientId, deptId)
    Svc->>DB: findActiveResponsibility(SALES_ITEM, salesItemRef)
    DB-->>Svc: null (no match)
    Svc->>DB: findActiveResponsibility(DEAL, dealRef)
    DB-->>Svc: null (no match)
    Svc->>DB: findActiveResponsibility(CLIENT, clientId)
    DB-->>Svc: assignment row (match found)
    Svc-->>UI: resolved_from_entity_type_cd = 'CLIENT', resolved_from_level = 2, assigned_to_user_id = 7
    Note over Svc: Short-circuits -- DEPARTMENT level not queried

10. Cross-References

DocumentRelationship
Assignments Data ModelDefines the assignment and assignment_history tables, all code master values (assignment_type_cd, entity_type_cd, task_status_cd, action_cd), status lifecycles, and validation constraints used throughout this workflow.
Assignments QueriesSpecifies all data retrieval operations: CRUD lookups, hierarchy resolution queries, gap-detection queries with REV balance and coverage level calculations, and the unassigned summary query.
Assignments ProceduresSpecifies all data mutation operations: create/transfer responsibility, create/update/cancel tasks, hierarchy resolution walk-up, and responsibility chain resolution.
Cash Receipts WorkflowTask assignments for CASH_RECEIPT and CASH_RECEIPT_SPLIT entity types are created when receipts or splits need processing work. The Unassigned tab surfaces these entities using worksheet status and applied-amount data from the Cash Receipts domain.
Worksheets WorkflowWorksheet status (D, P, T, A, R) and current_item_ind drive the "needs work" determination for unassigned cash receipt and split entities in the Unassigned tab.
Settlements WorkflowTask assignments for PAYMENT entity type are created when payment items need follow-up. payment_item.payment_execution_status_cd determines which payment entities surface in the Unassigned tab.
Billing Items WorkflowThe REV balance calculation in gap-detection queries derives from billing_item and billing_item_detail; open billing items determine which responsibility-type entities appear in the Unassigned tab.
Deals WorkflowDeal, sales item, and payment term identifiers form the Level 3 and Level 4 entity keys for responsibility assignments. The four-level responsibility hierarchy reflects the deal structure.

11. Gherkin Scenarios

gherkin
Feature: Assignments - Responsibility Management

  Scenario: Assign responsibility to a department for the first time
    Given no active assignment exists where assignment.entity_type_cd = 'DEPARTMENT'
      AND assignment.entity_id = 42 AND assignment.is_active_ind = true
    And user "Sarah Chen" has user_id = 7 in the users table
    When a supervisor opens the Assign Responsibility dialog and selects
      entity type "Department (L1)", department "Music Department" (department_id = 42),
      and assignee "Sarah Chen"
    And the supervisor clicks "Assign Responsibility"
    Then a new assignment row is created with assignment_type_cd = 'RESPONSIBILITY',
      entity_type_cd = 'DEPARTMENT', entity_id = 42, assigned_to_user_id = 7,
      is_active_ind = true
    And a new assignment_history row is created with action_cd = 'ASSIGNED', to_user_id = 7
    And "Music Department" no longer appears in the Unassigned tab for DEPARTMENT

  Scenario: Transfer responsibility when accountable person changes
    Given an active assignment exists where assignment.assignment_id = 'abc-123',
      entity_type_cd = 'CLIENT', entity_id = 501, assigned_to_user_id = 7,
      is_active_ind = true
    And user "James Park" has user_id = 12 in the users table
    When a supervisor opens the Transfer dialog for assignment 'abc-123',
      selects new assignee "James Park", and enters reason "Sarah on leave"
    And the supervisor clicks "Transfer"
    Then assignment 'abc-123' is updated to is_active_ind = false
    And a new assignment_history row is inserted for 'abc-123' with
      action_cd = 'DEACTIVATED', from_user_id = 7, comment_text = 'Sarah on leave'
    And a new assignment row is created with entity_type_cd = 'CLIENT',
      entity_id = 501, assigned_to_user_id = 12, is_active_ind = true
    And a new assignment_history row is inserted for the new assignment with
      action_cd = 'REASSIGNED', from_user_id = 7, to_user_id = 12

  Scenario: Reject duplicate responsibility creation
    Given an active assignment exists where entity_type_cd = 'DEAL',
      entity_reference = 'DEAL-2024-001', is_active_ind = true, assigned_to_user_id = 7
    When a user attempts to create a new responsibility for
      entity_type_cd = 'DEAL' and entity_reference = 'DEAL-2024-001'
    Then the service rejects the operation with error
      "An active responsibility already exists for this entity. Use transfer instead."
    And no new assignment row is created

  Scenario: Self-transfer rejected
    Given an active assignment exists where assignment.assignment_id = 'abc-123',
      assigned_to_user_id = 7, is_active_ind = true
    When user 7 attempts to transfer assignment 'abc-123' to new_user_id = 7
    Then the service rejects the operation
    And assignment 'abc-123' remains unchanged with is_active_ind = true,
      assigned_to_user_id = 7

Feature: Assignments - Task Management

  Scenario: Create and progress a cash receipt task through to completion
    Given cash_receipt with cash_receipt_id = 1001 has posting_status_cd = 'U'
      and no active task assignment exists for entity_type_cd = 'CASH_RECEIPT',
      entity_id = 1001
    And user "Alex Rivera" has user_id = 5
    When a cash manager opens the Create Task dialog for receipt 1001 from the
      Unassigned tab, selects assignee "Alex Rivera", and submits with
      task_title = 'Clear Cash Receipt' and end_dt = '2026-03-05'
    Then a new assignment row is created with assignment_type_cd = 'TASK',
      entity_type_cd = 'CASH_RECEIPT', entity_id = 1001, assigned_to_user_id = 5,
      task_status_cd = 'OPEN', end_dt = '2026-03-05'
    And receipt 1001 no longer appears in the Unassigned tab for CASH_RECEIPT
    When "Alex Rivera" clicks the "Start Working" button on the task
    Then assignment.task_status_cd is updated to 'WORKING'
    And a new assignment_history row is inserted with action_cd = 'STATUS_CHANGED',
      from_status_cd = 'OPEN', to_status_cd = 'WORKING'
    When "Alex Rivera" clicks the "Complete" button on the task
    Then assignment.task_status_cd is updated to 'COMPLETE'
    And a new assignment_history row is inserted with action_cd = 'STATUS_CHANGED',
      from_status_cd = 'WORKING', to_status_cd = 'COMPLETE'

  Scenario: Task paused while waiting for external information
    Given a task assignment with assignment_id = 'task-789', task_status_cd = 'WORKING',
      entity_type_cd = 'CASH_RECEIPT_SPLIT', entity_id = 55
    When the assignee clicks "Pause" on the task
    Then assignment.task_status_cd is updated to 'WAITING'
    And a new assignment_history row is inserted with action_cd = 'STATUS_CHANGED',
      from_status_cd = 'WORKING', to_status_cd = 'WAITING'
    When the external dependency resolves and the assignee clicks "Resume"
    Then assignment.task_status_cd is updated to 'WORKING'
    And a new assignment_history row is inserted with action_cd = 'STATUS_CHANGED',
      from_status_cd = 'WAITING', to_status_cd = 'WORKING'

  Scenario: Invalid task status transition rejected
    Given a task assignment with assignment_id = 'task-456', task_status_cd = 'COMPLETE'
    When a user attempts to transition the task to status 'OPEN'
    Then the service rejects the operation
    And assignment.task_status_cd remains 'COMPLETE'
    And no assignment_history row is inserted

  Scenario: Multiple concurrent tasks on same entity with sibling cancellation
    Given cash_receipt with cash_receipt_id = 2002 has two active task assignments:
      task-A with task_status_cd = 'WORKING' assigned to user 3
      task-B with task_status_cd = 'OPEN' assigned to user 5
    When task-A is completed (task_status_cd updated to 'COMPLETE')
    Then task-B still has task_status_cd = 'OPEN' (unaffected without explicit cancellation)
    When cancelSiblingTasks is invoked with assignment_id = 'task-A'
    Then task-B is updated to task_status_cd = 'CANCELLED'
    And a new assignment_history row is inserted for task-B with
      action_cd = 'CANCELLED', from_status_cd = 'OPEN', to_status_cd = 'CANCELLED'

  Scenario: Edit task reassigns to a different person
    Given a task assignment with assignment_id = 'task-999',
      task_title = 'Review deposit', assigned_to_user_id = 3
    When a supervisor opens the Edit Task dialog and changes the assignee to user_id = 8
    And submits the form
    Then assignment.assigned_to_user_id is updated to 8
    And a new assignment_history row is inserted with action_cd = 'REASSIGNED',
      from_user_id = 3, to_user_id = 8

  Scenario: Edit task title only produces no history entry
    Given a task assignment with assignment_id = 'task-999',
      task_title = 'Review deposit', assigned_to_user_id = 3
    When a supervisor edits only the task_title to 'Review deposit - urgent'
      without changing the assignee
    Then assignment.task_title is updated to 'Review deposit - urgent'
    And no new assignment_history row is inserted for this change

Feature: Assignments - Hierarchy Resolution

  Scenario: Resolve responsible person via hierarchy walk-up when direct assignment missing
    Given the following active responsibility assignments exist:
      | entity_type_cd | entity_key         | assigned_to_user_id |
      | DEPARTMENT     | entity_id = 10     | 2                   |
      | CLIENT         | entity_id = 501    | 7                   |
    And no active assignment exists for entity_type_cd = 'DEAL'
      AND entity_reference = 'DEAL-2024-007'
    And deal 'DEAL-2024-007' belongs to client_id = 501 and department_id = 10
    When resolveResponsibleUser is called with
      dealReference = 'DEAL-2024-007', clientId = 501, departmentId = 10
    Then the service checks DEAL level and finds no match
    Then the service checks CLIENT level and finds assignment where entity_id = 501,
      assigned_to_user_id = 7
    And the service returns resolved_from_entity_type_cd = 'CLIENT',
      resolved_from_level = 2, assigned_to_user_id = 7
    And the DEPARTMENT level is not queried (short-circuit on first match)

  Scenario: Fully unowned entity shows correct Unassigned tab badge
    Given a department with department_id = 99 has open billing items
      with positive rev_balance
    And no active assignment exists for entity_type_cd = 'DEPARTMENT',
      entity_id = 99, assignment_type_cd = 'RESPONSIBILITY', is_active_ind = true
    When the Unassigned tab loads for entity type DEPARTMENT
    Then department 99 appears in the results with nearest_assignment_level = 0
    And the Coverage badge displays "Unowned"

  Scenario: Unassigned deal shows coverage badge for ancestor client assignment
    Given a deal entity_reference = 'DEAL-2024-010' has no active deal-level responsibility
    And the parent client (entity_id = 600) has an active responsibility
      assigned to user_id = 9 (display name "Maria Torres")
    When the Unassigned tab loads for entity type DEAL
    Then deal 'DEAL-2024-010' appears in the results
      with nearest_assignment_level = 2 and nearest_assignment_entity_type_cd = 'CLIENT'
    And the Coverage badge displays "via Client (Maria Torres)"

Feature: Assignments - Unassigned Gap Detection

  Scenario: Cash receipt disappears from Unassigned tab after task assigned
    Given cash_receipt with cash_receipt_id = 3003 has posting_status_cd != 'V'
      and the worst worksheet status rank < 4 (needs work)
    And no active task assignment exists for entity_type_cd = 'CASH_RECEIPT',
      entity_id = 3003 where task_status_cd NOT IN ('COMPLETE', 'CANCELLED')
    When a cash manager selects "Alex Rivera" in Quick Assign To and clicks
      "Assign Task" on cash_receipt 3003
    Then a new assignment row is created with entity_type_cd = 'CASH_RECEIPT',
      entity_id = 3003, assigned_to_user_id = 5, task_status_cd = 'OPEN',
      task_title = 'Clear Cash Receipt'
    And cash_receipt 3003 no longer appears in the Unassigned CASH_RECEIPT list
    And the CASH_RECEIPT summary chip count decrements by 1

  Scenario: Failed payment appears in Unassigned payment task list
    Given payment_item with payment_item_id = 7777 has
      payment_execution_status_cd = 'FAILED'
    And no active task assignment exists for entity_type_cd = 'PAYMENT',
      entity_id = 7777 where task_status_cd NOT IN ('COMPLETE', 'CANCELLED')
    When the Unassigned tab loads for entity type PAYMENT
    Then payment 7777 appears in the results with statusCd = 'FAILED'
    And an "Assign Task" button is visible on the row

Confidential. For internal use only.