Skip to content

Invoicing Workflow

1. Executive Summary

Purpose

The Invoicing workflow enables UTA finance staff to generate formal payment request documents from billing items and transmit them to buyers or clients. An invoice is the mechanism by which UTA communicates what is owed: either a Commission invoice sent to a client for UTA's revenue share (REV), or a Total Due invoice sent to a buyer for the full amount owed under a deal (PAY). This workflow sits downstream of deal and billing item creation and upstream of cash receipt matching — once billing items have been created and their amounts confirmed from the deal engine, invoicing converts those receivables into outbound payment requests. Generated invoices are tracked through a lifecycle (DRAFTISSUEDPAIDVOID) and produce PDF documents that include payment instructions drawn from bank detail configuration.

Scope

Covered:

  • Browsing billing item details that have not yet been invoiced, filtered by recipient type and invoice type
  • Selecting billing item details for invoicing, individually or in bulk
  • Generating invoice records with automatic grouping by UTA entity, currency, recipient, and (where applicable) client
  • Automatic sequential invoice number generation per UTA entity per calendar year
  • PDF generation and download for any existing invoice
  • Viewing the full list of generated invoices with status filtering

Not covered (documented separately):

Key Objectives

  • Produce unique, well-formatted invoice documents for each UTA entity's outstanding billing items
  • Enforce grouping rules that keep each invoice scoped to one entity, one currency, and (for UK entities) one client
  • Prevent the same billing item detail from being invoiced twice under the same document type
  • Provide downloadable PDF invoices with the correct bank payment instructions for the issuing entity and currency

2. Process Overview

mermaid
flowchart TD
    A([Billing items exist without billing_item_document links]) --> B[User opens Generate Invoices screen]
    B --> C[User selects Invoice Recipient and Invoice Type filters]
    C --> D[System loads uninvoiced billing item details matching the filter]
    D --> E[User selects one or more billing item details]
    E --> F{Items selected?}
    F -->|No| E
    F -->|Yes| G[System previews invoice count based on grouping]
    G --> H[User clicks Generate Invoice]
    H --> I[System validates all selected details match invoice type]
    I --> J{Validation passed?}
    J -->|No| K[Error returned — generation aborted]
    J -->|Yes| L[System groups items into invoice batches by entity, currency, recipient, client]
    L --> M[For each batch: generate invoice number, calculate totals, insert invoice record]
    M --> N[For each batch: insert billing_item_document links]
    N --> O[Invoice records created with status DRAFT]
    O --> P[Selected items removed from available-for-invoicing list]
    P --> Q([User downloads PDF from Invoice List])

Walkthrough

  1. Filter and load — The user opens the Generate Invoices screen and selects an Invoice Recipient (CLIENT or BUYER) and an Invoice Type (COMMISSION or TOTAL_DUE). The system loads only billing item details of the corresponding billing_item_detail_type_cd (REV for Commission, PAY for Total Due) that have no existing billing_item_document link of the matching document type.

  2. Browse the grouped table — Loaded billing items are displayed in a collapsible hierarchy: Level 1 groups by client or buyer (matching the selected recipient), Level 2 sub-groups by UTA entity and currency, and Level 3 (for Buyer recipient without Multi-Client, or for UK entities regardless) further sub-groups by client. Each level has a checkbox for bulk selection. The system shows a live count of how many invoices the current selection will produce.

  3. Select items — The user checks individual rows, client sub-group rows (Level 3), entity/currency sub-group rows (Level 2), or recipient group rows (Level 1). The live invoice count updates to reflect how many discrete invoice batches the selection spans.

  4. Generate — The user clicks Generate Invoice. The system validates that all selected details match the chosen invoice type, groups them into batches by entity/currency/recipient/client rules, generates a sequential invoice number per batch, inserts each invoice record with status_cd = 'DRAFT', and writes billing_item_document bridge rows to mark those billing items as invoiced.

  5. View and download — The user navigates to the Invoice List screen, optionally filters by status, and downloads a PDF for any invoice. The PDF renders line items, totals, payment instructions, and addresses.


3. Business Rules

3.1 Each Invoice Covers Exactly One UTA Entity

Business rule: All billing item details on a single invoice must belong to the same UTA entity (billing_item.uta_entity_id). Items from different entities cannot be combined.

Foundation reference: Generate Invoices — Step 3: Group Items into Invoice Batches

Workflow context: The billing item table groups automatically by UTA entity at Level 2 (the sub-group row). Selecting items across multiple entity sub-groups under the same Level 1 recipient group produces multiple invoices, one per entity.


3.2 Each Invoice Covers Exactly One Currency

Business rule: All billing item details on a single invoice must share the same currency_cd. Items in different currencies generate separate invoices.

Foundation reference: Generate Invoices — Step 3: Group Items into Invoice Batches

Workflow context: Currency is part of the Level 2 sub-group display label (e.g., "UTA US Entity — USD"). Items in USD and GBP for the same buyer produce two invoices.


3.3 UK Entity: Always One Client Per Invoice

Business rule: When the issuing UTA entity is the UK entity (entity ID = 2), each invoice may contain billing items for only one client, regardless of the Multi-Client Invoice setting.

Foundation reference: Generate Invoices — Step 3: Group Items into Invoice Batches

Workflow context: For UK entity sub-groups in Buyer recipient mode, the table always shows a Level 3 client sub-group layer. The Multi-Client Invoice checkbox has no effect on UK entity batches. This is enforced both in the UI grouping logic and in the server-side batching logic.


3.4 US Entity Buyer Mode: Multi-Client Is Optional

Business rule: For US entities in Buyer recipient mode, the user may choose to combine multiple clients into a single buyer invoice by enabling Multi-Client Invoice. When disabled (default), each client gets its own invoice from a given buyer.

Foundation reference: Generate Invoices — Step 3: Group Items into Invoice Batches

Workflow context: The Multi-Client Invoice checkbox appears on the filter bar only when BUYER is selected as the recipient. Toggling it resets the current selection and regroups the table. When enabled, client sub-groups collapse into the entity/currency sub-group level; when disabled, client sub-groups reappear.


3.5 Invoice Type Must Match Billing Item Detail Type

Business rule: A Commission invoice (COMMISSION) may only contain REV-type billing item details (billing_item_detail_type_cd = 'REV'). A Total Due invoice (TOTAL_DUE) may only contain PAY-type details. Mixing types is not permitted.

Foundation reference: Generate Invoices — Step 2: Fetch and Validate Selected Billing Item Details

Workflow context: The filter bar enforces this at the query level: selecting COMMISSION loads only REV details; selecting TOTAL_DUE loads only PAY details. The validation is re-checked server-side at generation time as a safeguard against concurrent filter changes or direct API calls.


3.6 Client Recipient Always Gets Commission Invoices Only

Business rule: When the recipient is CLIENT, the invoice type is always COMMISSION. The system defaults Invoice Type to COMMISSION when the user selects CLIENT as the recipient and hides the TOTAL_DUE option.

Foundation reference: Invoice Type Code Master — INVOICE_TYPE_CD

Workflow context: The Invoice Type dropdown filters its options based on the selected recipient. When CLIENT is selected, only the COMMISSION option is shown and the dropdown is effectively pre-set.


3.7 A Billing Item Cannot Be Invoiced Twice for the Same Document Type

Business rule: Once a billing item is linked to an invoice of a given type (Commission or Buyer), it no longer appears in the available-for-invoicing list for that type and cannot be added to a new invoice of the same type.

Foundation reference: Get Billing Items Available for Invoicing — Exclusion Filter

Workflow context: After generation succeeds, the screen refreshes and the invoiced items disappear from the table. The uq_billing_item_document_item_type_doc unique constraint on billing_item_document (billing_item_id, document_type_cd, document_id) enforces this at the database level — concurrent inserts for the same billing item and document type will fail with a constraint violation.


3.8 Invoice Number Is Sequential Per Entity Per Calendar Year

Business rule: Invoice numbers follow the format {prefix}-{year}-{sequence} (e.g., UTA_US-2026-000001). The sequence resets to 1 at the start of each new calendar year and increments atomically for each new invoice within a year. The prefix is derived from uta_entity.invoice_prefix.

Foundation reference: Invoice Number Generation — Procedure 2.2

WARNING

The PoC uses a read-then-write pattern for sequence generation (SELECT then UPDATE), which is not safe under concurrent invoice creation. Production must use an atomic increment (e.g., UPDATE ... SET current_sequence = current_sequence + 1 RETURNING) or a serializable transaction to prevent duplicate invoice numbers.


3.9 Due Date Is Derived from Billing Terms

Business rule: invoice.due_date is always calculated by adding the billing_terms_cd offset to invoice.issue_date. The issue date defaults to the current date (PST) at generation time, and the billing terms default to DUE_RECEIPT (0 days offset) when not overridden.

Foundation reference: Generate Invoices — Step 4: Calculate Due Date


3.10 Bank Details Are Selected Automatically for PDF Generation

Business rule: When generating a PDF, the system resolves payment instructions by matching invoice.uta_entity_id and invoice.currency_cd to the invoice_bank_details table. If no active matching record exists, the PDF is generated without payment instructions.

Foundation reference: invoice_bank_details Table Definition


3.11 Invoice Lifecycle Is Forward-Only

Business rule: Invoices follow the lifecycle DRAFTISSUEDPAIDVOID. PAID and VOID are terminal states. No backward transition is permitted.

Foundation reference: Invoice Status Lifecycle — INVOICE_STATUS_CD

**PoC Artifact:** The PoC does not enforce allowed status transitions in the service layer. The `updateInvoiceStatus` operation accepts any target status. Production must enforce the allowed-transitions table as preconditions before updating `invoice.status_cd`.


4. Data Access & Operations References

4.1 Queries Used

OperationFoundation DocPurpose in This Workflow
getBillingItemDetailsForInvoicingGet Billing Items Available for InvoicingLoads uninvoiced billing item details for display in the grouped table, filtered by billing_item_detail_type_cd
getBillingItemDetailsByIdsGet Billing Items by IDsHydrates the selected detail IDs with full party, entity, address, and deal data at generation time
getBillingItemDetailsByInvoiceIdGet Billing Items by Invoice IDLoads line items for an invoice when generating its PDF
getInvoicesGet All InvoicesPopulates the Invoice List screen with optional invoice.status_cd filter
getInvoiceDisplayByIdGet Invoice by IDLoads a single invoice with enriched display data (entity name, recipient name, type description) for PDF rendering
getNextInvoiceNumber (sequence read)Invoice Number GenerationReads the current invoice_number_sequence.current_sequence for the entity-year before incrementing
getInvoiceBankDetailsInvoice Queries — Bank DetailsResolves payment instructions by uta_entity_id + currency_cd for PDF generation
getUtaEntityWithDetailsTODO: Document in foundation/queries/invoices-and-statements.mdFetches UTA entity name and configuration for PDF header rendering

4.2 Procedures Used

OperationFoundation DocTrigger in This Workflow
generateInvoicesGenerate Invoices from Billing ItemsUser clicks Generate Invoice button with one or more items selected
getNextInvoiceNumberInvoice Number GenerationCalled internally once per invoice batch during generation
createBillingItemDocumentLinksLink Billing Items to InvoiceCalled internally once per invoice batch to write billing_item_document bridge rows
updateInvoiceStatusUpdate Invoice StatusUser transitions an invoice's invoice.status_cd (e.g., Draft → Issued, Issued → Void); not yet surfaced as a distinct UI action in the PoC
generateInvoicePdfGenerate Invoice PDFUser clicks the PDF download icon on any row in the Invoice List
upsertInvoiceBankDetailsAdd or Update Invoice Bank DetailsAdministrator sets up payment instructions for an entity/currency combination before PDF generation (admin workflow, not surfaced in the PoC invoicing screens)

5. Key User Actions

5.1 Load Billing Items Available for Invoicing

Preconditions:

  • User has selected both an Invoice Recipient (CLIENT or BUYER) and an Invoice Type (COMMISSION or TOTAL_DUE) from the filter bar.
  • billing_item_detail records of the corresponding billing_item_detail_type_cd must exist without a matching billing_item_document link of the relevant document type.

Procedure reference: Get Billing Items Available for Invoicing

Steps:

  1. User selects Invoice Recipient; the system defaults Invoice Type to COMMISSION when CLIENT is chosen, or TOTAL_DUE when BUYER is chosen.
  2. User confirms or overrides Invoice Type.
  3. The system fetches uninvoiced billing_item_detail records filtered by the selected billing_item_detail_type_cd.
  4. The grouped table renders with items organized by recipient party (Level 1), UTA entity and currency (Level 2), and client (Level 3 where applicable). All groups are collapsed by default.

Postconditions:

  • The grouped table is populated. Selection state is cleared.

UI trigger: Automatic — fires when both filter dropdowns have non-empty values. A Refresh button in the page header re-runs the fetch manually.


5.2 Select Billing Items for Invoice Generation

Preconditions:

  • The grouped table is populated (both filters are set and data has loaded).

Procedure reference: Not a data mutation — selection is client-side state only until Generate Invoice is submitted.

Steps:

  1. User checks or unchecks individual detail rows, client sub-group rows (Level 3), entity/currency sub-group rows (Level 2), or recipient group rows (Level 1).
  2. Selecting a parent-level checkbox selects all children below it; deselecting a parent deselects all children.
  3. The action bar shows a count of selected items, a preview of how many invoices will be generated, and enables the Generate Invoice button.
  4. User may use Select All to select every visible item or Clear Selection to deselect all.
  5. Expand All / Collapse All controls the visibility of hierarchy levels without affecting selection state.

Postconditions:

  • A set of billing_item_detail.billing_item_detail_id values is held in client state for submission.

UI trigger: Checkboxes on each row and group/sub-group header row. Select All and Clear Selection buttons in the action bar. Enabled when the table is populated.


5.3 Generate Invoices

Preconditions:

  • At least one billing item detail is selected.
  • Both Invoice Recipient and Invoice Type filters are set.
  • All selected details must have billing_item_detail_type_cd matching the selected Invoice Type (REV for Commission, PAY for Total Due).

Procedure reference: Generate Invoices from Billing Items

Steps:

  1. User clicks Generate Invoice.
  2. The system validates that all selected billing_item_detail_id values exist and their billing_item_detail_type_cd matches the invoice type.
  3. The system groups selected items into invoice batches using entity, currency, recipient party, and client rules.
  4. For each batch, the system generates a sequential invoice number via the invoice_number_sequence mechanism.
  5. For each batch, the system inserts an invoice record with invoice.status_cd = 'DRAFT', calculated invoice.total_gross_amt, invoice.total_commission_amt (Commission invoices only), invoice.issue_date (current date in PST), and invoice.due_date (derived from billing_terms_cd).
  6. For each batch, the system inserts billing_item_document rows linking each billing_item_id to the new invoice.invoice_id with the appropriate document_type_cd ('CI' for Commission, 'BI' for Buyer).
  7. On success, a confirmation message shows the count of invoices created. The selection is cleared and the table refreshes, removing the now-invoiced items.

Postconditions:

  • One invoice record exists per batch with invoice.status_cd = 'DRAFT'.
  • billing_item_document rows exist for each billing item in each batch, preventing re-invoicing.
  • Invoiced items no longer appear in the available-for-invoicing table.

UI trigger: Generate Invoice button in the action bar. Visible always. Enabled when at least one item is selected and generation is not in progress. Shows a loading state ("Generating...") while in progress.


5.4 Download Invoice PDF

Preconditions:

  • An invoice record exists in any status (DRAFT, ISSUED, PAID, or VOID).
  • The invoice has at least one billing_item_document link (i.e., at least one line item).
  • A uta_entity record exists for the invoice's uta_entity_id.

Procedure reference: Generate Invoice PDF

Steps:

  1. User navigates to the Invoice List screen.
  2. User clicks the download icon on any invoice row.
  3. The system fetches the invoice header with display data, its linked billing item line items via billing_item_document, the UTA entity details, and the matching invoice_bank_details record by uta_entity_id + currency_cd.
  4. The system generates a PDF buffer containing the invoice number, issue and due dates, recipient name and address, line items with gross and commission amounts, totals, and (if available) payment instructions.
  5. The PDF is returned as a base64-encoded string, decoded in the browser, and downloaded as Invoice_{invoice.invoice_number}.pdf.

Postconditions:

  • No database mutation. invoice.status_cd is not changed by PDF generation.

UI trigger: Download icon (per-row) in the Invoice List table. Always visible and enabled for every invoice row. Shows a loading pulse animation while the PDF is being generated for that row.


5.5 Filter Invoice List by Status

Preconditions:

  • The Invoice List screen is open and invoices have been loaded.

Procedure reference: Get All Invoices

Steps:

  1. User opens the Invoice List screen; all invoices load by default (no status filter applied).
  2. User selects a status from the Status filter dropdown (Draft, Issued, Paid, Void, or All Statuses).
  3. The system re-fetches invoice records filtered by the selected invoice.status_cd.
  4. The table updates to show only invoices matching the filter.

Postconditions:

  • The table reflects only invoices with the selected invoice.status_cd. No database state is changed.

UI trigger: Status dropdown in the Invoice List screen header. Always visible and enabled.


6. Permissions & Role-Based Access

**PoC Artifact:** The PoC does not enforce role-based access control for the invoicing workflow. The `invoice.created_by` field defaults to `'SYSTEM'` because user session resolution is not implemented. The role model below reflects the expected production design based on the existing role definitions in the system.

ActionCASH_MANAGERCASH_PROCESSORSETTLEMENT_APPROVERIT
Load billing items available for invoicingYesYesYesYes
Select items and preview invoice countYesYesYesYes
Generate invoicesYesYes
View Invoice ListYesYesYesYes
Filter Invoice List by statusYesYesYesYes
Download invoice PDFYesYesYesYes
Update invoice status (e.g., Draft → Issued, Issued → Void)YesYesYes

Field-level restrictions:

  • invoice.status_cd transitions are expected to require CASH_MANAGER or SETTLEMENT_APPROVER role in production. The ISSUED → PAID transition is expected to be driven by the cash matching workflow rather than a manual status change.
  • The Multi-Client Invoice option is available only when BUYER is selected as the recipient and is currently unrestricted by role in the PoC.

7. Integration Points

7.1 Upstream

SourceData ProvidedMechanism
Deal Engine (via Revenue Sync)revenue_item and billing_item records created from deal payment termsInbound data sync writes billing_item and billing_item_detail rows that become available for invoicing
Billing Items workflowbilling_item and billing_item_detail records with REV/PAY amounts, entity, currency, client, and buyer associationsFK lookup: billing_item_detail.billing_item_idbilling_itemrevenue_item (sales_item) → deal
UTA Entity ConfigurationInvoice prefix from uta_entity.invoice_prefix; entity name for PDF headerFK lookup: billing_item.uta_entity_iduta_entity
Invoice Bank DetailsPayment instructions (bank_name, account_number, swift_code, iban, sort_code, aba_routing_number) for PDF renderingFK lookup: invoice.uta_entity_id + invoice.currency_cdinvoice_bank_details
Party AddressesRecipient and contracted party mailing addresses for PDFFK lookup: billing_item.buyer_id / client_idparty_addresses (primary address)

7.2 Downstream

ConsumerData ConsumedMechanism
Cash Receipts / Worksheets workflowbilling_item_document bridge rows identify which billing items have been invoiced; invoice.status_cd transitions to PAID when cash is matchedFK lookup: billing_item_document.document_id = invoice.invoice_id
Statements workflowinvoice records associated with billing items may be referenced in client and deal statement generationFK lookup via billing_item_document
AR Aging reportsbilling_item_document links indicate which receivables have been invoiced, used as a status indicator in aging viewsFK lookup via billing_item_document

7.3 External Integrations

No external integrations for this workflow. Invoice PDFs are generated in-process and returned directly to the browser. No outbound transmission to buyer or client systems is currently implemented; PDF delivery is manual (the user downloads and sends separately).


8. Functional Screen Requirements

8.1 Generate Invoices Screen

Route: /invoices

Data loading:

  • No data is loaded on initial page entry — the grouped table remains hidden until both filter dropdowns are set.
  • getBillingItemDetailsForInvoicingGet Billing Items Available for Invoicing — triggered automatically when both Invoice Recipient and Invoice Type are selected, and manually via the Refresh button.

Filter Bar Region

The filter bar collects the two required parameters that control which billing items are loaded and how they are grouped and invoiced.

Field / ColumnSourceEditable?Condition
Invoice RecipientClient state (maps to invoice.invoice_recipient_cd: CLIENT or BUYER)YesAlways visible
Invoice TypeClient state (maps to invoice.invoice_type_cd: COMMISSION or TOTAL_DUE)YesAlways visible; filtered to COMMISSION only when recipient is CLIENT
Multi-Client InvoiceClient state (boolean; maps to multiClientInvoice parameter on the generate request)YesVisible only when Invoice Recipient = BUYER

Conditional display:

  • The Multi-Client Invoice checkbox is visible only when Invoice Recipient = BUYER.
  • When Invoice Recipient = CLIENT, the Invoice Type dropdown shows only Commission and is auto-selected.
  • When Invoice Recipient = BUYER, the Invoice Type dropdown defaults to Total Due but allows Commission as well.
  • The billing item table and action bar are hidden and a placeholder is shown until both Invoice Recipient and Invoice Type are set.

Action Bar Region

The action bar shows selection statistics, a live invoice count preview, and the generate trigger.

Field / ColumnSourceEditable?Condition
Selected items countComputed: count of billing_item_detail_id values in client selection stateNoVisible when filter is complete and data has loaded
Total items countComputed: total count of loaded billing_item_detail rowsNoVisible when filter is complete and data has loaded
Invoice count previewComputed: number of distinct invoice batches the current selection will produceNoVisible when at least one item is selected

Grid features:

  • Sortable columns: none
  • Filters: driven by filter bar dropdowns only
  • Row selection: multi-checkbox with hierarchy-aware Select All / Clear Selection
  • Pagination: none

Conditional display:

  • Select All button: always enabled when filter is complete and data has loaded.
  • Clear Selection button: enabled only when at least one item is selected.
  • Expand All / Collapse All: always enabled when data has loaded.
  • Generate Invoice button: enabled only when at least one item is selected and generation is not in progress.
  • The invoice count preview sentence ("Will generate N invoices") appears only when at least one item is selected.

Grouped Billing Items Table Region

The grouped table presents billing items in a collapsible hierarchy. Each level has a checkbox for bulk selection and a row count and total amount summary.

Level 1 — Recipient Group Row

Groups items by the recipient party name (client name for CLIENT mode; buyer name for BUYER mode).

Field / ColumnSourceEditable?Condition
Group nameparty.party_name (client or buyer depending on recipient mode)NoAlways visible
Item countComputed: total billing_item_detail rows in the groupNoAlways visible
Group selection checkboxClient stateYesAlways visible
Expand/collapse toggleClient stateYesAlways visible

Level 2 — UTA Entity + Currency Sub-Group Row

Groups items within a recipient group by billing_item.uta_entity_id and billing_item.currency_cd.

Field / ColumnSourceEditable?Condition
Sub-group labeluta_entity.uta_entity_name + billing_item.currency_cdNoVisible when parent group is expanded
Item countComputed: count of billing_item_detail rows in the sub-groupNoVisible when parent group is expanded
Total amountComputed: SUM(billing_item_detail.billing_item_detail_amt) for sub-group itemsNoVisible when parent group is expanded
Sub-group selection checkboxClient stateYesVisible when parent group is expanded

Level 3 — Client Sub-Group Row (Buyer mode without Multi-Client, or UK entity)

Groups items within an entity/currency sub-group by billing_item.client_id. Each client sub-group represents one invoice that will be created.

Field / ColumnSourceEditable?Condition
Client nameparty.party_name (client)NoVisible when sub-group is expanded and has client grouping
Item countComputed: count of items for this clientNoVisible when sub-group is expanded and has client grouping
Total amountComputed: SUM(billing_item_detail.billing_item_detail_amt) for this client's itemsNoVisible when sub-group is expanded and has client grouping
Client sub-group selection checkboxClient stateYesVisible when sub-group is expanded and has client grouping

Detail Row (Individual Billing Item Detail)

One row per billing_item_detail record.

Field / ColumnSourceEditable?Condition
Row selection checkboxClient stateYesVisible when parent row is expanded
UTA Entityuta_entity.uta_entity_nameNoAlways shown
Currencybilling_item.currency_cdNoAlways shown
Clientparty.party_name (client via billing_item.client_id)NoAlways shown
Buyerparty.party_name (buyer via billing_item.buyer_id)NoAlways shown
Dealdeal.deal_nameNoAlways shown
Billing Descriptionbilling_item.billing_item_nameNoAlways shown
Due Datebilling_item.billing_item_due_dtNoAlways shown
Typebilling_item_detail.billing_item_detail_type_cd displayed as a badge (REV or PAY)NoAlways shown
Grossbilling_item_detail.billing_item_detail_gross_amtNoAlways shown
Commission / Netbilling_item_detail.billing_item_detail_amtNoShown only when Invoice Type = COMMISSION; column header is "Commission" for CLIENT recipient, "Net" for BUYER recipient
Service Periodrevenue_item.revenue_item_start_dt to revenue_item.revenue_item_end_dtNoAlways shown

Conditional display:

  • The entire table and action bar are hidden until both filter dropdowns have values.
  • When data loads with zero results, an empty state message ("No billing items available for invoicing with the selected criteria") is shown.
  • The Level 3 client sub-group layer is shown only in Buyer mode when Multi-Client Invoice is unchecked, or when the entity is the UK entity regardless of the Multi-Client checkbox.
  • The Commission/Net column is hidden entirely when Invoice Type = TOTAL_DUE.
  • Selecting any item automatically expands its parent group, sub-group, and client sub-group (if applicable) to make the selection visible.

8.2 Invoice List Screen

Route: /invoices/list

Data loading:

  • getInvoicesGet All Invoices — loads on mount; re-runs when the status filter changes.

Header Region

Shows page title, record count, a Refresh button, and a Generate Invoice navigation link.

Field / ColumnSourceEditable?Condition
Invoice count labelComputed: count of displayed invoice rows after filteringNoAlways visible
Status filterClient state (maps to invoice.status_cd filter parameter; 'all' = no filter)YesAlways visible

Conditional display:

  • The Generate Invoice button navigates to /invoices (the Generate Invoices screen).
  • When the list is empty and no status filter is active, an empty state with an icon and a Generate Invoice call-to-action is shown.
  • When the list is empty with a status filter active, a message prompts the user to change the filter.

Invoice Table Region

One row per invoice record.

Field / ColumnSourceEditable?Condition
Invoice #invoice.invoice_numberNoAlways visible
Statusinvoice.status_cd displayed as a status badgeNoAlways visible
Typeinvoice.invoice_type_cd (display description)NoAlways visible
Recipientparty.party_name via invoice.recipient_party_idNoAlways visible
Entityuta_entity.uta_entity_name via invoice.uta_entity_idNoAlways visible
Issue Dateinvoice.issue_dateNoAlways visible
Due Dateinvoice.due_dateNoAlways visible
Amountinvoice.total_gross_amt formatted with invoice.currency_cdNoAlways visible
PDF download button— triggers generateInvoicePdf for the row's invoice.invoice_idAlways visible; per-row

Grid features:

  • Sortable columns: none (invoices are sorted by creation date descending from the query)
  • Filters: status filter dropdown in the header filters by invoice.status_cd
  • Row selection: none
  • Pagination: none in the PoC

Conditional display:

  • The PDF download button shows a loading animation while the PDF is being generated for that specific invoice row.
  • Status badge appearance varies by invoice.status_cd: DRAFT = muted/secondary, ISSUED = default/primary, PAID = outline, VOID = destructive.

9. Additional Diagrams

Invoice Grouping Logic (Generate Invoices)

The following diagram shows how selected billing item details are partitioned into invoice batches during generation.

mermaid
flowchart TD
    A([Selected billing_item_detail IDs]) --> B{Recipient type?}
    B -->|CLIENT| C["Batch key: uta_entity_id + currency_cd + client_party_id"]
    B -->|BUYER| D{Is UK entity ID = 2?}
    D -->|Yes — UK restriction| E["Batch key: uta_entity_id + currency_cd + buyer_party_id + client_party_id"]
    D -->|No — US entity| F{multiClientInvoice = true?}
    F -->|No — one client per invoice| G["Batch key: uta_entity_id + currency_cd + buyer_party_id + client_party_id"]
    F -->|Yes — combine clients| H["Batch key: uta_entity_id + currency_cd + buyer_party_id"]
    C --> I([One invoice record per batch key])
    E --> I
    G --> I
    H --> I

All diagrams for this workflow are included in the sections above.


10. Cross-References

DocumentRelationship
Invoices and Statements Data ModelDefines invoice, invoice_number_sequence, invoice_bank_details, billing_item_document, and generated_statement tables used in this workflow
Invoices and Statements QueriesSpecifies all data retrieval operations used in this workflow
Invoices and Statements ProceduresSpecifies all data mutation operations used in this workflow
Billing Items Data Modelbilling_item and billing_item_detail are the source records displayed and invoiced in this workflow; billing_item_document is the bridge table (owned by Billing Items) that marks items as invoiced
Billing Items WorkflowUpstream: billing items are created from deal engine revenue sync before they appear in the invoicing queue
Statements WorkflowSibling: statements summarize financial activity for clients and settlements; invoices are payment requests. Both workflows produce PDF documents but serve different purposes
Worksheets WorkflowDownstream: cash receipts are applied against billing item details in worksheets; matching a receipt to an invoice transitions invoice.status_cd to PAID
Write-Offs WorkflowAdjacent: REV billing item details that are written off have billing_item_detail.write_off_status_cd = 'WRITTEN_OFF'; written-off items may still be invoiced but represent amounts deemed uncollectable

11. Gherkin Scenarios

gherkin
Feature: Invoicing - Generate Commission Invoices for Clients

  Scenario: User generates a single commission invoice for a client
    Given billing_item_detail records exist for client "Taylor Swift" with billing_item_detail_type_cd = 'REV'
    And no billing_item_document row exists for those billing_item rows with document_type_cd = 'CI'
    And the billing items have billing_item.uta_entity_id = 1 (UTA US) and billing_item.currency_cd = 'USD'
    When the user selects Invoice Recipient = 'CLIENT' and Invoice Type = 'COMMISSION'
    And the user selects all billing item details for "Taylor Swift"
    And the user clicks Generate Invoice
    Then one invoice record is created with invoice.status_cd = 'DRAFT'
    And invoice.invoice_type_cd = 'COMMISSION' and invoice.invoice_recipient_cd = 'CLIENT'
    And invoice.uta_entity_id = 1 and invoice.currency_cd = 'USD'
    And invoice.invoice_number matches the pattern 'UTA_US-2026-{6-digit zero-padded sequence}'
    And invoice.total_gross_amt = SUM(billing_item_detail.billing_item_detail_gross_amt) for selected items
    And invoice.total_commission_amt = SUM(billing_item_detail.billing_item_detail_amt) for selected items
    And billing_item_document rows are created with document_type_cd = 'CI' linking each billing_item_id to the new invoice.invoice_id
    And the selected items no longer appear in the available-for-invoicing list

  Scenario: UK entity always produces separate invoices per client even when Multi-Client is checked
    Given billing_item_detail records exist for two clients "Ed Sheeran" and "Adele"
    And both clients have billing items with billing_item.uta_entity_id = 2 (UTA UK) and currency_cd = 'GBP'
    And Invoice Recipient = 'BUYER' and Multi-Client Invoice checkbox is checked
    When the user selects all billing item details for both clients under the same buyer
    And the user clicks Generate Invoice
    Then two invoice records are created — one for "Ed Sheeran" and one for "Adele"
    And both invoices have invoice.uta_entity_id = 2 and invoice.currency_cd = 'GBP'
    And invoice.multi_client_ind = false for both invoices
    And billing_item_document links with document_type_cd = 'BI' are created for each invoice separately

  Scenario: US entity in Buyer mode with Multi-Client enabled combines clients into one invoice
    Given billing_item_detail records exist for clients "Imagine Dragons" and "The Weeknd"
    And both have billing_item.buyer_id pointing to buyer "Live Nation" under billing_item.uta_entity_id = 1 (UTA US) with currency_cd = 'USD'
    And Invoice Recipient = 'BUYER', Invoice Type = 'TOTAL_DUE', Multi-Client Invoice = true
    When the user selects all items for both clients and clicks Generate Invoice
    Then one invoice record is created for recipient "Live Nation"
    And invoice.multi_client_ind = true
    And billing_item_document links with document_type_cd = 'BI' cover billing items from both clients

  Scenario: Items across two currencies produce separate invoices
    Given billing_item_detail records exist for buyer "Netflix" under billing_item.uta_entity_id = 1 (UTA US)
    And some items have billing_item.currency_cd = 'USD' and others have billing_item.currency_cd = 'EUR'
    And Invoice Recipient = 'BUYER', Invoice Type = 'TOTAL_DUE', Multi-Client Invoice = true
    When the user selects all items for Netflix and clicks Generate Invoice
    Then two invoice records are created — one with invoice.currency_cd = 'USD' and one with invoice.currency_cd = 'EUR'
    And both invoice.invoice_number values are globally unique

  Scenario: Generate Invoice button is disabled until items are selected
    Given the user has selected Invoice Recipient = 'CLIENT' and Invoice Type = 'COMMISSION'
    And the billing item table is loaded with results
    And no items are currently selected
    Then the Generate Invoice button is disabled
    And the invoice count preview is not shown in the action bar

Feature: Invoicing - Error Handling

  Scenario: Generation fails due to invoice type mismatch
    Given billing_item_detail record ID 2001 has billing_item_detail_type_cd = 'PAY'
    And Invoice Type = 'COMMISSION' is selected (which requires billing_item_detail_type_cd = 'REV')
    When a generate request is submitted including billing_item_detail_id = 2001
    Then the service rejects the request with an error indicating invoice type mismatch
    And no invoice records are created
    And no billing_item_document rows are inserted

  Scenario: Concurrent generation blocked by unique constraint on billing_item_document
    Given billing_item_id = 501 has billing_item_detail_type_cd = 'REV' and no billing_item_document row with document_type_cd = 'CI'
    And two users simultaneously select billing_item_detail for billing_item_id = 501 and click Generate Invoice
    When both requests reach the billing_item_document INSERT step
    Then the first request succeeds and inserts billing_item_document with document_type_cd = 'CI' for billing_item_id = 501
    And the second request fails with a uq_billing_item_document_item_type_doc constraint violation
    And only one invoice record is committed

Feature: Invoicing - PDF Download

  Scenario: User downloads a PDF for a Draft invoice with bank details configured
    Given invoice record with invoice_id = 500 exists with invoice.status_cd = 'DRAFT'
    And billing_item_document rows link billing items to invoice_id = 500
    And invoice_bank_details exists for invoice.uta_entity_id and invoice.currency_cd with is_active = true
    When the user clicks the download icon for invoice_id = 500 on the Invoice List screen
    Then the system fetches invoice display data, line items, entity details, and bank details
    And generates a PDF containing invoice.invoice_number, invoice.issue_date, invoice.due_date, line items, totals, and payment instructions
    And the browser downloads a file named 'Invoice_{invoice.invoice_number}.pdf'
    And invoice.status_cd remains 'DRAFT' — no database mutation occurs

  Scenario: PDF generated without payment instructions when no bank details exist
    Given invoice record with invoice_id = 501 exists for invoice.uta_entity_id = 3 and invoice.currency_cd = 'CAD'
    And no invoice_bank_details row exists with uta_entity_id = 3 and currency_cd = 'CAD' and is_active = true
    When the user clicks the download icon for invoice_id = 501
    Then the system generates a PDF without a payment instructions section
    And the download succeeds with the correct invoice header and line item content

Feature: Invoicing - Invoice List Management

  Scenario: User filters the Invoice List to show only Issued invoices
    Given multiple invoice records exist with invoice.status_cd values of 'DRAFT', 'ISSUED', and 'PAID'
    When the user selects 'Issued' from the Status filter dropdown on the Invoice List screen
    Then the table shows only invoice rows where invoice.status_cd = 'ISSUED'
    And the invoice count label reflects only the filtered count

  Scenario: Invoice sequence increments correctly within the same year
    Given invoice_number_sequence exists for uta_entity_id = 1 and current_year = 2026 with current_sequence = 5
    When a new invoice is generated for uta_entity_id = 1
    Then invoice_number_sequence.current_sequence for uta_entity_id = 1 and current_year = 2026 is updated to 6
    And the new invoice.invoice_number = 'UTA_US-2026-000006'

  Scenario: Invoice sequence resets at the start of a new calendar year
    Given invoice_number_sequence exists for uta_entity_id = 1 and current_year = 2025 with current_sequence = 999
    And the current system date is in 2026
    When a new invoice is generated for uta_entity_id = 1
    Then a new invoice_number_sequence row is created with uta_entity_id = 1, current_year = 2026, current_sequence = 1
    And the new invoice.invoice_number = 'UTA_US-2026-000001'

Confidential. For internal use only.