Statements Workflow
1. Executive Summary
Purpose
The Statements workflow provides the ability to generate, preview, and download PDF financial summary documents for clients, deals, revenue items, and accounts-receivable aging. Statements consolidate payment activity from the worksheet and settlement lifecycle into human-readable documents delivered to clients and their parties. Unlike invoices (which are formal payment requests sent outbound to buyers or clients), statements are informational summaries: they confirm what was received, how it was split, what UTA retained as commission, and what was paid out. The workflow sits downstream of the full cash flow — it can only report on posted payment_item and approved participant_settlement records, meaning all upstream processes (receipt, worksheet, settlement, approval, bank transmission, GL posting) must be complete before the activity appears on a statement.
Scope
Covered:
- Generating Client (Artist) Statements showing all posted payments received for a client within a date range, with commission breakdown and third-party payout detail
- Previewing client statement transaction data and selectively excluding individual payment items before generating the PDF
- Generating Settlement Statements (deal-engagement view) summarizing guarantee, overage, commission, and net amounts per engagement for a client over a date range
- Generating Deal Statements showing all revenue items and billing item (receivable) details for a single deal with payee allocations
- Generating Settlement Statements V2 (revenue-item view) showing cash receipts, receivables, and settlement distributions for a specific revenue item within a deal
- Generating AR Aging Statements for all or a specific client, classifying open receivables into aging buckets as of a given date
- Generating Invoices for clients (commission invoices) or buyers (total-due invoices) from selected billing items
- Storing all generated PDF artifacts in object storage with metadata in
generated_statement - Viewing and re-downloading previously generated statements from the statement history
Not covered (documented separately):
- Invoice lifecycle management (issue, void, mark paid) — see Invoicing Workflow
- Worksheet creation and cash application — see Worksheets Workflow
- Settlement creation and approval — see Settlements Workflow
- Payment transmission to banks — see Payments Workflow
Key Objectives
- Provide clients, artists, and their representatives with accurate, printable summaries of financial activity
- Allow cash processors and settlement approvers to generate and review settlement documentation before or after payment transmission
- Maintain a persistent, downloadable history of all generated PDFs with storage coordinates for retrieval and audit
2. Process Overview
flowchart TD
A[User opens Statement Generator] --> B{Select statement type}
B --> C[Client Statement]
B --> D[Settlement Statement\n Engagement view]
B --> E[Deal Statement]
B --> F[Settlement Statement V2\n Revenue Item view]
B --> G[Invoice]
B --> H[AR Aging Statement]
C --> C1[Select client,\ndate range, currency]
C1 --> C2[Preview transactions\nOptionally exclude items]
C2 --> C3[Generate PDF]
D --> D1[Select client,\ndate range, currency]
D1 --> D2[Generate PDF\ndirectly]
E --> E1[Select deal]
E1 --> E2[Generate PDF\ndirectly]
F --> F1[Select deal,\nthen revenue item]
F1 --> F2[Generate PDF\ndirectly]
G --> G1[Select invoice type\nClient or Buyer]
G1 --> G2[Select UTA entity\nUS or UK]
G2 --> G3[Select party,\ncheck billing items]
G3 --> G4[Generate PDF]
H --> H1[Optional client filter\nand as-of date]
H1 --> H2[Generate PDF]
C3 --> I[PDF returned to browser]
D2 --> I
E2 --> I
F2 --> I
G4 --> I
H2 --> I
I --> J{Save to storage?}
J -->|Yes| K[Upload PDF to object storage\nInsert generated_statement record]
J -->|No| L[Return PDF only]
K --> M[Statement History updated]
M --> N[User can re-download\nfrom history tab]Walkthrough
Select statement type — The user selects one of six statement types on the Generate tab: Client Statement, Settlement Statement (engagement view), Deal Statement, Settlement Statement V2 (revenue-item view), Invoice, or AR Aging Statement. Each type has its own parameter form.
Supply parameters — For client-scoped statements, the user selects a client (party), date range, and currency. For deal-scoped statements, the user selects a deal and optionally a specific revenue item. For invoices, the user selects whether the target is a client or buyer, the UTA entity (US or UK), and the billing items to include.
Preview (Client Statement only) — Before generating a Client Statement, the user can preview the transaction list. The preview shows each posted
payment_itemrecord as a row with gross amount, agency commission, and net amount. The user can uncheck individual rows to exclude them from the final PDF. Running totals update in real time to reflect excluded items.Generate PDF — The user triggers generation. The service queries posted payment and settlement data, aggregates it, renders a PDF using the appropriate template, and returns the result. For all statement types, the PDF is uploaded to object storage and a
generated_statementrecord is inserted.Download or preview — After generation, the PDF is available for immediate browser preview (opens in a new tab) or download. The generated
statement_refis displayed so the user can track the document.Statement History — All previously generated and stored statements appear in the History tab. Any stored statement can be re-downloaded by retrieving the PDF from object storage using the stored
generated_statement.s3_key.
3. Business Rules
3.1 Client Statement Reports Posted Payment Items Only
Business rule: A Client Statement includes only payment_item records where payment_item.payment_item_posting_status_cd = 'P' (Posted) and payment_item.client_id matches the selected client, within the selected date range (payment_item.posting_dt between date_from and date_to inclusive). Unposted, cancelled, or failed payment items are excluded.
Foundation reference: Get Client Statement Payment Items
Workflow context: If no posted payment items exist for the selected client and date range, the generated PDF contains the message "No transactions found for the selected date range." The "Generate Statement" button in the preview panel is disabled when all transactions have been excluded via checkboxes (zero included items).
3.2 Transaction Exclusion Is a User-Controlled Filter
Business rule: When previewing a Client Statement, any payment items the user unchecks are excluded from the generated PDF only — the underlying payment_item records are not modified. The exclusion is applied in-memory at generation time and recorded in generated_statement.metadata.excludedPaymentItemIds for audit purposes.
Foundation reference: Generate Client Statement
Workflow context: The statement preview table shows a master checkbox in the header that selects or deselects all rows at once. Individual rows can be toggled. The count of excluded items is shown in the card header. The "Generate Statement" button label includes the count of included items, e.g., "Generate Statement (5 items)".
3.3 Settlement Statement Aggregates by Deal Engagement
Business rule: A Settlement Statement (engagement view) groups participant_settlement_item records by payment_item.deal_id to create one engagement row per deal. The query joins participant_settlement_item to payment_item via participant_settlement_item.payment_item_id, filters by participant_settlement_item.payment_party_id = the selected client, and restricts payment_item.posting_dt to the date range. Each engagement accumulates guarantee (payment amount), commission due (from participant_settlement_item.participant_settlement_commission_amt or computed as amount × commission percentage), and deposit received.
Foundation reference: Get Settlement Engagements
3.4 Deal Statement Aggregates Billing Items Across All Revenue Items
Business rule: A Deal Statement is generated for a single deal.deal_id. It retrieves all sales_item (revenue item) records linked to the deal, then all billing_item records under each revenue item, with their REV and PAY billing_item_detail amounts and cash-applied amounts from cash_receipt_application. The statement shows both open (uncollected) and closed (collected) receivables. Payee allocations are derived from deal_party records.
Foundation reference: Get Deal Statement Data
3.5 Settlement Statement V2 Scopes to a Single Revenue Item
Business rule: A Settlement Statement V2 is scoped to a single sales_item.sales_item_id (revenue item), not to a client or date range. It shows all billing_item records under that revenue item, the cash_receipt records applied to them (via cash_receipt_split and cash_receipt_worksheet), and how the PAY portion was distributed among payees via cash_receipt_payout linked to participant_settlement_item. The revenue item is always selected within the context of a deal (user first picks a deal, then a revenue item within it).
Foundation reference: Get Settlement Statement V2 Data
3.6 Invoice Generation Creates an invoice Record and Bridge Rows
Business rule: Generating an invoice from the statements page creates an invoice record (status 'DRAFT') and links the selected billing_item records to it via billing_item_document rows. The invoice_number is generated sequentially per entity per calendar year using the invoice_number_sequence table. Once a billing item is linked to an invoice via billing_item_document, it is excluded from future "available for invoicing" queries for the same document type.
Foundation reference: Generate Invoices from Billing Items
Workflow context: The invoice UI surfaces a simplified form: the user selects whether the invoice is for a client (COMMISSION type, using REV billing item detail amounts) or for a buyer (TOTAL_DUE type, using PAY billing item detail amounts), then selects a party and billing items. Billing items are auto-selected on party selection. A preview below the selection table shows the subtotal, applicable tax (UK VAT at 20% or US NRA withholding at 30%), and total due. These tax previews are display-only calculations in the UI and do not write to any table.
IMPORTANT
The 20% VAT and 30% WHT amounts shown in the Invoice Generator UI are display estimates only. They are not persisted or applied to the invoice record. Production invoice tax handling must be driven by the authoritative tax calculation engine via WithholdingTaxService — see Worksheets Workflow for the production tax flow.
3.7 AR Aging Statement Classifies Open Receivables Into Aging Buckets
Business rule: An AR Aging Statement computes the age of open billing_item records as of a given date. Receivables are classified into standard aging buckets (Current: 0–30 days, 31–60 days, 61–90 days, 91–120 days, Over 120 days) based on billing_item.billing_item_due_dt relative to the as-of date. When the "Open items only" flag is set, only billing_item records without complete cash application are included.
Foundation reference: Get AR Aging Data
3.8 All Generated Statements Are Persisted to Object Storage
Business rule: Every PDF generated through the statements workflow is uploaded to object storage and a generated_statement record is inserted with generation_status_cd = 'COMPLETED'. The s3_bucket and s3_key values are stored so the PDF can be retrieved later via the history tab. The statement_ref is a unique identifier prefixed by type: CS- for client statements, SS- for settlement statements, DS- for deal statements.
Foundation reference: Persist Generated Statement
Workflow context: The history tab queries generated_statement filtering for generation_status_cd = 'COMPLETED' and shows the 50 most recent records ordered by generated_statement.generated_dt descending. Re-download retrieves the file using the stored s3_key.
3.9 Statement History Is Read-Only
Business rule: Previously generated statements in the history tab cannot be deleted, recalled, or regenerated in place. Each generation creates a new record. If a user needs an updated statement, they generate a new one; the old records remain for audit purposes.
Foundation reference: Get Generated Statements
4. Data Access & Operations References
4.1 Queries Used
| Operation | Foundation Doc | Purpose in This Workflow |
|---|---|---|
getClientsForStatement | TODO: Document in foundation/queries/invoices-and-statements.md | Load the client dropdown on page mount. Queries party where active_ind = true, ordered by display_name, limit 100. |
getClientStatementPreview | Get Client Statement Payment Items | Fetch the transaction list for the Client Statement preview panel before PDF generation. |
getGeneratedStatements | Get Generated Statements | Load the history tab with metadata for all completed generated_statement records. Joins party for client name. |
downloadStatement | Get Generated Statement by ID | Retrieve s3_key and file_name for a stored statement to initiate a download from object storage. |
getDealsForStatement | TODO: Document in foundation/queries/invoices-and-statements.md | Load the deal dropdown for Deal Statement and Settlement Statement V2 cards. Queries deal ordered by deal_id descending, limit 100. Supports optional name/reference search. |
getRevenueItemsForStatement | TODO: Document in foundation/queries/invoices-and-statements.md | Load revenue items for a selected deal for Settlement Statement V2. Queries sales_item joined to deal, filtered by deal_id, limit 100. |
getPartiesForInvoice | TODO: Document in foundation/queries/invoices-and-statements.md | Load the client or buyer party dropdown for the Invoice Generator. Queries deal_party joined to party, grouped by party, ordered by deal count descending, limit 100. |
getBillingItemsForInvoice | Get Billing Item Details Available for Invoicing | Load billing items for the selected party in the Invoice Generator. Uses REV amounts for CLIENT invoices, PAY amounts for BUYER invoices. Filters out zero-amount items. |
getSettlementEngagements | Get Settlement Engagements | Aggregate settlement items by deal for the Settlement Statement (engagement view) PDF. |
getClientTransactions | Get Client Statement Payment Items | Aggregate posted payment items by posting date and deal for the Client Statement PDF. Groups by posting_dt and deal_id. |
getDealStatementData | Get Deal Statement Data | Retrieve deal header, revenue items, receivables, cash applications, and payee allocations for the Deal Statement PDF. |
getSettlementStatementV2Data | Get Settlement Statement V2 Data | Retrieve revenue item, cash receipts, receivables, and distribution data for Settlement Statement V2. |
getARAgingData | Get AR Aging Data | Retrieve open billing items classified into aging buckets for the AR Aging Statement PDF. |
getDefaultUTAEntity | TODO: Document in foundation/queries/invoices-and-statements.md | Fetch the first uta_entity record with address and contact methods for use in PDF statement headers. |
4.2 Procedures Used
| Operation | Foundation Doc | Trigger in This Workflow |
|---|---|---|
generateClientStatement | Generate Client Statement | User clicks "Generate Statement" after previewing and optionally excluding transactions on the Client Statement card. |
generateSettlementStatement | Generate Settlement Statement | User clicks "Generate Settlement Statement" on the Settlement Statement (engagement view) card. |
generateDealStatement | Generate Deal Statement | User clicks "Generate Deal Statement" after selecting a deal on the Deal Statement card. |
generateSettlementStatementV2 | Generate Settlement Statement V2 | User clicks "Generate Settlement Statement" after selecting a deal and revenue item on the Settlement Statement V2 card. |
generateInvoice | Generate Invoices from Billing Items | User clicks "Generate Invoice" after selecting party, billing items, and entity type on the Invoice Generator card. Creates invoice, increments invoice_number_sequence, and inserts billing_item_document rows. |
generateARAgingStatement | Generate AR Aging Statement | User clicks "Generate AR Aging Statement" on the AR Aging card. |
persistGeneratedStatement | Persist Generated Statement | Called automatically after every successful PDF generation. Uploads PDF to object storage and inserts generated_statement row with generation_status_cd = 'COMPLETED'. |
5. Key User Actions
5.1 Preview Client Statement Transactions
Preconditions:
- A client (
party) must be selected from the dropdown. date_fromanddate_tomust both be populated.- Currency must be selected (defaults to
'USD').
Procedure reference: Get Client Statement Payment Items
Steps:
- User selects a client, date range, and currency in the Client Statement card.
- User clicks "Preview & Edit Transactions".
- The service fetches all posted
payment_itemrecords for the client within the date range and returns them as a transaction list with gross, commission, and net amounts. - The transaction list appears in the preview panel below the form with per-row amounts and a running summary footer.
Postconditions:
- Transaction data is loaded into client-side state. No
generated_statementrecord is created. - Each transaction row represents one
payment_itemrecord, grouped byposting_dtanddeal_id, showingpayment_item.payment_item_id, posting date, deal reference, project name, memo, gross amount, agency commission, and net amount.
UI trigger: "Preview & Edit Transactions" button. Visible at all times on the Client Statement card. Enabled when a client, date_from, and date_to are all populated.
5.2 Generate Client Statement
Preconditions:
- A client, date range, and currency must be selected.
- Preview mode must be active (user has clicked "Preview & Edit Transactions").
- At least one transaction must remain included (not all unchecked).
Procedure reference: Generate Client Statement
Steps:
- User reviews the transaction list in preview mode and optionally unchecks transactions to exclude.
- User clicks "Generate Statement (N items)".
- The service re-queries the full transaction set, filters out excluded
payment_item.payment_item_idvalues, aggregates totals, renders the PDF using the Client Statement template, uploads the PDF to object storage, and inserts agenerated_statementrecord. - The PDF is returned as a base64-encoded string for immediate browser preview or download.
Postconditions:
- A
generated_statementrow is inserted withstatement_type_cd = 'CLIENT_STATEMENT',generation_status_cd = 'COMPLETED',client_idset to the selected party,date_from,date_to,currency_cd,s3_bucket,s3_key,file_name,file_size_bytespopulated, andmetadatacontaining{ totalGross, totalCommission, totalNet, transactionCount, excludedPaymentItemIds }. generated_statement.statement_refis formatted asCS-{timestamp}-{uuid}.- The success panel displays the file name and
statement_ref.
UI trigger: "Generate Statement (N items)" button. Visible only in preview mode. Enabled when at least one transaction is included.
5.3 Generate Settlement Statement (Engagement View)
Preconditions:
- A client, date range, and currency must be selected.
Procedure reference: Generate Settlement Statement
Steps:
- User selects a client, date range, and currency in the Settlement Statement card.
- User clicks "Generate Settlement Statement".
- The service queries
participant_settlement_itemrecords wherepayment_party_id= the client andpayment_item.posting_dtfalls within the date range, groups by deal, calculates per-engagement totals (guarantee, commission, deposit), renders the Settlement Statement PDF in landscape orientation, uploads to storage, and inserts agenerated_statementrecord. - The PDF is returned for immediate browser preview or download.
Postconditions:
- A
generated_statementrow is inserted withstatement_type_cd = 'SETTLEMENT_STATEMENT',statement_refformatted asSS-{timestamp}-{uuid}, andmetadatacontaining{ totalGuarantee, totalNetGross, totalCommissionDue, netAmount, engagementCount }.
UI trigger: "Generate Settlement Statement" button on the Settlement Statement card. Enabled when a client, date_from, and date_to are populated.
5.4 Generate Deal Statement
Preconditions:
- A deal must be selected from the deal dropdown.
Procedure reference: Generate Deal Statement
Steps:
- User selects a deal from the Deal Statement card. An info panel shows the deal name, reference, and active/inactive status.
- User clicks "Generate Deal Statement".
- The service retrieves the full deal structure: deal header, payees from
deal_party, revenue items fromsales_item, billing items with REV/PAY detail amounts and cash-applied amounts fromcash_receipt_application. Renders a landscape legal-size PDF, saves to storage, and returns the result.
Postconditions:
- A
generated_statementrow is inserted withstatement_type_cd = 'SETTLEMENT_STATEMENT'(deal variant),statement_refformatted asDS-{timestamp}-{uuid}, and metadata containing deal totals (total gross, commission, cash applied, payable, payee allocations).
UI trigger: "Generate Deal Statement" button. Enabled when a deal is selected.
5.5 Generate Settlement Statement V2 (Revenue Item View)
Preconditions:
- A deal must be selected.
- A revenue item (
sales_item) within the selected deal must be selected.
Procedure reference: Generate Settlement Statement V2
Steps:
- User selects a deal. Revenue items for that deal load automatically into the revenue item dropdown.
- User selects a revenue item. An info panel shows the item name, reference, deal name, and gross amount.
- User clicks "Generate Settlement Statement".
- The service queries cash receipts applied to billing items under the selected revenue item, retrieves
cash_receipt_payoutandparticipant_settlement_itemrecords to show how PAY was distributed, renders the PDF, saves to storage, and returns the result.
Postconditions:
- A
generated_statementrow is inserted withstatement_type_cd = 'SETTLEMENT_STATEMENT'(V2 variant) and metadata containing settlement distribution totals.
UI trigger: "Generate Settlement Statement" button on the Settlement Statement V2 card. Enabled when a revenue item is selected. Revenue item dropdown is disabled until a deal is selected.
5.6 Generate Invoice
Preconditions:
- Invoice target type must be selected (
'CLIENT'or'BUYER'). - UTA entity must be selected (
'US'or'UK'). - A party (client or buyer) must be selected.
- At least one billing item must be selected.
Procedure reference: Generate Invoices from Billing Items
Steps:
- User selects invoice target type (
CLIENTorBUYER). The party dropdown reloads with parties of that role fromdeal_party. - User selects a UTA entity. The UK flag affects invoice grouping logic and tax display.
- User selects a party. Billing items for the party load automatically and all are pre-selected.
- User reviews the billing item table, toggling checkboxes to include or exclude items. A totals panel shows subtotal, tax estimate, and total due.
- User clicks "Generate Invoice (N items)".
- The service validates item types, groups items into invoice batches by entity/currency/recipient rules (one client per invoice for UK entity), generates sequential invoice numbers, inserts
invoicerecords withstatus_cd = 'DRAFT', insertsbilling_item_documentrows, renders the invoice PDF, and returns the result.
Postconditions:
- One or more
invoicerecords are created withstatus_cd = 'DRAFT'andinvoice_numberformatted as{prefix}-{year}-{sequence}. billing_item_documentrows are inserted:document_type_cd = 'CI'forCOMMISSIONinvoices,'BI'forTOTAL_DUEinvoices.invoice_number_sequence.current_sequenceis incremented for each entity + calendar year combination used.- The success panel displays the file name and invoice number.
UI trigger: "Generate Invoice (N items)" button on the Invoice Generator card. Enabled when a party is selected and at least one billing item is checked.
5.7 Generate AR Aging Statement
Preconditions:
- No required parameters. Client filter and as-of date are optional.
Procedure reference: Generate AR Aging Statement
Steps:
- User optionally selects a client and/or as-of date on the AR Aging card. The "Open Items Only" toggle defaults to enabled.
- User clicks "Generate AR Aging Statement".
- The service queries
billing_itemrecords, computes age relative to the as-of date usingbilling_item.billing_item_due_dt, classifies into aging buckets, renders the PDF, saves to storage, and returns the result.
Postconditions:
- A
generated_statementrow is inserted withstatement_type_cd = 'AR_STATEMENT'.
UI trigger: "Generate AR Aging Statement" button on the AR Aging card. Always enabled.
5.8 Re-Download Statement from History
Preconditions:
- A
generated_statementrecord withgeneration_status_cd = 'COMPLETED'and a populateds3_keymust exist.
Procedure reference: Get Generated Statement by ID
Steps:
- User opens the Statement History tab. History loads automatically, showing the 50 most recent completed statements.
- User locates the statement in the history table and clicks the download icon.
- The service retrieves
generated_statement.s3_keyand fetches the PDF buffer from object storage using the S3 download API. - The PDF is returned as base64 and triggered as a browser file download.
Postconditions:
- No database records are created or updated. The PDF file in object storage is accessed read-only.
UI trigger: Download icon button in the Actions column of the history table. Always visible for completed statements.
6. Permissions & Role-Based Access
NOTE
The PoC statements page does not enforce role-based access. The page is accessible to any authenticated user. Production must restrict invoice generation to appropriate approver roles as described below.
| Action | CASH_MANAGER | CASH_PROCESSOR | SETTLEMENT_APPROVER | IT |
|---|---|---|---|---|
| Preview Client Statement transactions | Yes | Yes | Yes | Yes |
| Generate Client Statement | Yes | Yes | Yes | Yes |
| Generate Settlement Statement (engagement view) | Yes | Yes | Yes | Yes |
| Generate Deal Statement | Yes | Yes | Yes | Yes |
| Generate Settlement Statement V2 | Yes | Yes | Yes | Yes |
| Generate Invoice | — | — | Yes | Yes |
| Generate AR Aging Statement | Yes | Yes | Yes | Yes |
| View Statement History | Yes | Yes | Yes | Yes |
| Re-download from History | Yes | Yes | Yes | Yes |
Field-level restrictions:
- The Invoice Generator UI exposes a UK entity toggle that affects invoice grouping and tax display. Production should derive the entity from
billing_item.uta_entity_idrather than relying on a user-supplied toggle. generated_statement.generated_byshould be populated with the authenticated user's identity. In the PoC, this field defaults to'system'because session resolution is not yet implemented.
7. Integration Points
7.1 Upstream
| Source | Data Provided | Mechanism |
|---|---|---|
| Worksheets workflow | Posted payment_item records with payment_item_posting_status_cd = 'P' and payment_item.posting_dt | FK lookup — payment_item.client_id and payment_item.posting_dt used for client statement transaction queries |
| Settlements workflow | participant_settlement and participant_settlement_item records with commission amounts and payee allocations | FK lookup — participant_settlement_item.payment_party_id and participant_settlement_item.payment_item_id used for settlement engagement queries |
| Billing Items workflow | billing_item, billing_item_detail, and sales_item records with gross amounts, due dates, and detail type codes | FK lookup — billing items scoped by deal, revenue item, or party for invoice generation and deal/settlement statement queries |
| Cash Receipts workflow | cash_receipt, cash_receipt_split, cash_receipt_worksheet, cash_receipt_application, and cash_receipt_payout records | FK lookup — cash receipt application and payout amounts used in Settlement Statement V2 to show cash applied vs. receivables |
7.2 Downstream
| Consumer | Data Consumed | Mechanism |
|---|---|---|
| External clients and their parties | Generated PDF statement documents | Browser download triggered by user; PDF delivered as file attachment |
| Invoice lifecycle | invoice record created with status_cd = 'DRAFT' | INSERT into invoice; downstream invoice workflow (issue, void, mark paid) consumes the created record — see Invoicing Workflow |
| Audit trail | generated_statement records with storage coordinates and metadata | FK reference persisted in generated_statement; retrievable by administrators and auditors |
7.3 External Integrations
| System | Direction | Protocol | Notes |
|---|---|---|---|
| Object Storage (S3-compatible) | Outbound (upload) and Inbound (download) | S3 API (PutObject / GetObject) | Generated PDFs are uploaded via s3Service.uploadPdf() using a structured key pattern: {type}/{clientId}/{dateRange}. Re-downloads use s3Service.downloadPdf(). In the PoC development environment, a local file_path may be used instead of S3 when S3 is not configured. |
8. Functional Screen Requirements
8.1 Statement Generator Page
Route: /statements
Data loading:
getClientsForStatement— queries activepartyrecords on page mount to populate client dropdown; limit 100, ordered byparty.display_name
Generate Tab
The Generate tab hosts all PDF generation forms presented as separate expandable cards, one per statement type. All cards appear on the same tab simultaneously.
Conditional display:
- All six statement type cards are always visible on the Generate tab.
- Each card operates independently; selecting parameters in one card does not affect others.
Client Statement Sub-section
The Client Statement card generates a per-client payment activity summary for a date range.
| Field / Column | Source | Editable? | Condition |
|---|---|---|---|
| Client | party.party_id, party.display_name | Yes | Always; populated from getClientsForStatement |
| From Date | User input | Yes | Always; pre-set to 2024-01-01 on load |
| To Date | User input | Yes | Always; pre-set to 2024-12-31 on load |
| Currency | User input | Yes | Always; defaults to 'USD'; options: USD, EUR, GBP, CAD |
Conditional display:
- "Preview & Edit Transactions" button enabled when client,
date_from, anddate_toare all populated. - Transaction preview panel replaces the button after a successful preview fetch.
- "Cancel" button in preview panel returns the card to the input form and clears the transaction list.
- "Generate Statement (N items)" button appears in preview mode; label reflects the number of included (non-excluded) transactions.
- Button is disabled when all transactions are excluded (0 included items).
- Success panel appears after generation; it shows file name,
statement_ref, and "Preview" / "Download" buttons. - Error message appears if the server action returns an error.
Transaction Preview Table (inside Client Statement card)
Shows posted payment items returned by the preview query, one row per payment_item grouped by posting date and deal.
| Field / Column | Source | Editable? | Condition |
|---|---|---|---|
| Include checkbox | Client state (excludedIds set) | Yes | Always in preview mode |
| Date | payment_item.posting_dt | No | Always |
| Deal/Project | deal.deal_reference, deal.deal_name | No | Always; "-" when deal reference is null |
| Memo | payment_item.payment_item_name | No | Always; "-" when null |
| Gross | Computed: sum of payment_item_amt for the grouped transaction | No | Always |
| Commission | Computed: sum of amounts for payment_item_type_cd = 'S' items | No | Always |
| Net | Computed: gross − commission − third-party payout amounts | No | Always |
Grid features:
- Sortable columns: None (ordered by
payment_item.posting_dtdescending) - Filters: None
- Row selection: Checkbox per row (multi-select); checked = included in PDF, unchecked = excluded
- Pagination: No; all results returned
Conditional display:
- Master checkbox in table header toggles all rows selected or deselected.
- Excluded rows render at reduced opacity.
- "N item(s) excluded" badge shown in card header when
excludedIds.size > 0. - Totals summary panel below the table updates live as checkboxes change, showing Total Gross, Total Commission, Total Net for included items.
Settlement Statement (Engagement View) Sub-section
| Field / Column | Source | Editable? | Condition |
|---|---|---|---|
| Client | party.party_id, party.display_name | Yes | Always; shared client list from page-level state |
| From Date | User input | Yes | Always |
| To Date | User input | Yes | Always |
| Currency | User input | Yes | Always; defaults to 'USD' |
Conditional display:
- "Generate Settlement Statement" button enabled when client,
date_from, anddate_toare populated.
Deal Statement Sub-section
| Field / Column | Source | Editable? | Condition |
|---|---|---|---|
| Deal | deal.deal_id, deal.deal_name, deal.deal_reference, deal.active_ind | Yes | Always; loaded from getDealsForStatement |
| Deal info panel | deal.deal_name, deal.deal_reference, deal.active_ind | No | Visible when a deal is selected |
Conditional display:
- Deal dropdown is disabled when no deals are available or while loading.
- Info panel shows deal name, reference, and "Active" / "Inactive" status when a deal is selected.
- "Generate Deal Statement" button enabled when a deal is selected.
Settlement Statement V2 Sub-section
| Field / Column | Source | Editable? | Condition |
|---|---|---|---|
| Deal | deal.deal_id, deal.deal_name, deal.deal_reference, deal.active_ind | Yes | Always |
| Revenue Item | sales_item.sales_item_id, sales_item.name, sales_item.sales_item_ref, sales_item.gross_amt | Yes | Enabled after a deal is selected; reloads when deal changes |
| Revenue item info panel | sales_item.name, sales_item.sales_item_ref, deal.deal_name, sales_item.gross_amt | No | Visible when a revenue item is selected |
Conditional display:
- Revenue item dropdown shows "Select a deal first" placeholder until a deal is chosen.
- Revenue item dropdown disabled while loading or when no revenue items exist for the selected deal.
- "Generate Settlement Statement" button enabled when a revenue item is selected.
Invoice Generator Sub-section
| Field / Column | Source | Editable? | Condition |
|---|---|---|---|
| Invoice For | User input: 'CLIENT' or 'BUYER' | Yes | Always; defaults to 'CLIENT' |
| UTA Entity | User input: 'US' or 'UK' | Yes | Always; defaults to 'US' |
| Party | party.party_id, party.display_name, deal count | Yes | Reloads when Invoice For changes |
| Billing Items table (checkbox) | billing_item.billing_item_id state | Yes | Visible after party is selected |
| Billing item description | deal.deal_name, sales_item.sales_item_id | No | Always in billing items table |
| Due Date | billing_item.billing_item_due_dt | No | Always in billing items table; "-" when null |
| Amount | billing_item_detail.billing_item_detail_amt (REV for CLIENT, PAY for BUYER) | No | Always in billing items table |
| Subtotal | Computed: sum of selected items | No | Visible when billing items are selected |
| VAT @ 20% | Computed: subtotal × 0.20 | No | Visible when isUKEntity = true |
| WHT @ 30% | Computed: subtotal × 0.30 | No | Visible when US entity and targetType = 'BUYER' |
| Total Due | Computed: subtotal ± tax | No | Visible when billing items are selected |
Grid features:
- Sortable columns: None
- Filters: None
- Row selection: Checkbox per row; all rows auto-selected on party load; toggle to include/exclude
- Pagination: No; limited to 100 items with
overflow-y-autoscroll
Conditional display:
- Billing items table is hidden until a party is selected.
- "Generate Invoice (N items)" button label reflects current selection count.
- Button disabled when no billing items are selected.
AR Aging Statement Sub-section
| Field / Column | Source | Editable? | Condition |
|---|---|---|---|
| Client filter | party.party_id, party.display_name | Yes | Optional; when blank, all clients are included |
| As-of Date | User input | Yes | Optional; defaults to today (new Date()) |
| Open Items Only | Boolean | Yes | Always; defaults to true |
Conditional display:
- "Generate AR Aging Statement" button is always enabled (no required fields).
History Tab
Shows the 50 most recent completed generated_statement records, ordered by generated_dt descending.
| Field / Column | Source | Editable? | Condition |
|---|---|---|---|
| Statement Ref | generated_statement.statement_ref | No | Always |
| Client | party.display_name joined via generated_statement.client_id | No | Always; "Unknown" when party not found or client_id is null |
| Type | generated_statement.statement_type_cd | No | Always; underscores replaced with spaces for display |
| Date Range | generated_statement.date_from + generated_statement.date_to | No | Visible when both fields are populated; "-" otherwise |
| Generated | generated_statement.generated_dt | No | Always; "-" when null |
| Size | generated_statement.file_size_bytes | No | Always; formatted as B / KB / MB; "-" when null |
| Download button | N/A | N/A | Always visible for each row |
Grid features:
- Sortable columns: None (fixed order by
generated_dtdescending) - Filters: None exposed in UI (server action supports
client_idandstatement_typefilter parameters) - Row selection: None
- Pagination: No; 50 records shown
Conditional display:
- "Refresh" button in card header reloads history on demand.
- Loading spinner shown while history is fetching.
- "No statements have been generated yet." message shown when the result set is empty.
9. Additional Diagrams
stateDiagram-v2
[*] --> PENDING : generated_statement INSERT
PENDING --> GENERATING : Generation process starts
GENERATING --> COMPLETED : PDF stored in object storage
GENERATING --> FAILED : Error during generation or uploadThe generated_statement.generation_status_cd state machine above is fully described in Invoices and Statements Data Model — Section 3.2.
**PoC Artifact:** In the PoC, generation is synchronous. The `PENDING` and `GENERATING` states are never persisted — records are written directly with `generation_status_cd = 'COMPLETED'` after a successful generation and upload. Production may introduce asynchronous job-based PDF generation that passes through each intermediate state.
sequenceDiagram
participant U as User
participant S as Statements Page
participant A as Server Actions
participant SVC as StatementService
participant PDF as PDF Generator
participant ST as Object Storage
participant DB as Database
U->>S: Select client, date range, currency
U->>S: Click "Preview & Edit Transactions"
S->>A: getClientStatementPreviewAction(clientId, dateFrom, dateTo)
A->>SVC: getClientStatementPreview()
SVC->>DB: Query posted payment_item records
DB-->>SVC: Transaction rows
SVC-->>A: { client, transactions, totals }
A-->>S: Preview data
S->>U: Display transaction table
U->>S: Uncheck some transactions
U->>S: Click "Generate Statement (N items)"
S->>A: generateClientStatementAction(clientId, ..., excludedIds)
A->>SVC: generateClientStatement(..., excludedIds)
SVC->>DB: Re-query payment_item (filter excluded IDs)
DB-->>SVC: Filtered transactions
SVC->>PDF: generateClientStatement(statementData)
PDF-->>SVC: PDF buffer
SVC->>ST: uploadPdf(s3Key, buffer)
ST-->>SVC: { bucket, key }
SVC->>DB: INSERT generated_statement (generation_status_cd = 'COMPLETED')
DB-->>SVC: generated_statement_id
SVC-->>A: { success, buffer, fileName, statementRef }
A-->>S: { pdfBase64, fileName, statementRef }
S->>U: Show success panel with download / preview buttons10. Cross-References
| Document | Relationship |
|---|---|
| Invoices and Statements Data Model | Defines generated_statement, invoice, invoice_number_sequence, invoice_bank_details, and billing_item_document tables used throughout this workflow |
| Invoices and Statements Queries | Specifies all data retrieval operations for client transactions, settlement engagements, deal statements, AR aging, and generated statement history |
| Invoices and Statements Procedures | Specifies all data mutation operations: invoice creation (with number generation and bridge-table linking), statement PDF generation, and persistence to object storage |
| Invoicing Workflow | Downstream: invoices generated here have status_cd = 'DRAFT'; the invoicing workflow manages the issue, void, and paid status transitions |
| Worksheets Workflow | Upstream: worksheet apply and approve create posted payment_item records that appear on client statements; also the source of production tax calculations |
| Settlements Workflow | Upstream: participant_settlement_item records created during settlement drive the engagement-view Settlement Statement |
| Payments Workflow | Upstream: bank-sent and GL-posted payment items satisfy the payment_item_posting_status_cd = 'P' requirement for client statements |
| Billing Items Workflow | Upstream: billing_item and billing_item_detail records created via the billing items workflow are queried for invoice generation and deal statements |
| AR Aging Workflow | Related: the AR Aging Statement produced here is a PDF export of the same aging data displayed interactively in the AR Aging report screen |
11. Gherkin Scenarios
Feature: Statements - Client Statement Generation
Scenario: Generate a client statement for a client with posted payments in the period
Given party "Taylor Swift" has party_id = 42 and active_ind = true
And payment_item records exist for client_id = 42 with posting_dt between 2024-01-01 and 2024-12-31
And payment_item.payment_item_posting_status_cd = 'P' for all those records
When the user selects client "Taylor Swift", date_from = 2024-01-01, date_to = 2024-12-31, currency = 'USD'
And clicks "Preview & Edit Transactions"
Then the transaction preview table shows all posted payment_item rows for client_id = 42 in that period
And the totals panel shows the aggregate gross, commission, and net amounts
Scenario: Exclude transactions from a client statement before generation
Given a client statement preview is loaded with 5 transactions for client_id = 42
And payment_item with payment_item_id = 1001 has payment_item_amt = 5000.00 and payment_item_type_cd = 'S'
When the user unchecks the row for payment_item_id = 1001
Then the "1 item(s) excluded" indicator appears in the card header
And the totals panel decreases by 5000.00 for both Gross and Commission
And the "Generate Statement (4 items)" button reflects 4 included items
Scenario: Generate statement creates generated_statement record with exclusion metadata
Given the user has excluded payment_item_id = 1001 and 4 transactions remain included
When the user clicks "Generate Statement (4 items)"
Then a generated_statement row is inserted with statement_type_cd = 'CLIENT_STATEMENT'
And generated_statement.generation_status_cd = 'COMPLETED'
And generated_statement.client_id = 42
And generated_statement.metadata.excludedPaymentItemIds = [1001]
And generated_statement.metadata.transactionCount = 4
And generated_statement.statement_ref begins with 'CS-'
And the success panel shows the file name and statement_ref
Scenario: Client with no posted payments in the period sees an empty statement message
Given party "New Artist" has party_id = 99
And no payment_item records exist for client_id = 99 with posting_dt in 2024
When the user selects party 99, date_from = 2024-01-01, date_to = 2024-12-31, and previews
Then the preview panel shows "No transactions found for the selected date range."
And the "Generate Statement (0 items)" button is disabledFeature: Statements - Settlement Statement (Engagement View)
Scenario: Generate a settlement statement showing engagements for a client
Given participant_settlement_item records exist with payment_party_id = 42
And those items are joined to payment_item records with posting_dt between 2024-01-01 and 2024-12-31
And the payment_item records are linked to deal records
When the user selects client "Taylor Swift" (party_id = 42), date range 2024-01-01 to 2024-12-31
And clicks "Generate Settlement Statement" on the Settlement Statement card
Then a PDF is generated with one engagement row per distinct deal.deal_id
And each row shows guarantee, commission_due, and deposit_received aggregated from participant_settlement_item
And a generated_statement row is inserted with statement_type_cd = 'SETTLEMENT_STATEMENT'
And generated_statement.statement_ref begins with 'SS-'
Scenario: Settlement statement for a client with no settlement items in period
Given party_id = 99 has no participant_settlement_item records with posting_dt in 2024
When the user generates a settlement statement for party 99 for date range 2024
Then the PDF renders with the engagement table showing "No engagements found for the selected date range."
And a generated_statement row is inserted (empty statements are valid and stored)Feature: Statements - Deal Statement Generation
Scenario: Generate a deal statement for an active deal with revenue items and receivables
Given deal with deal_id = 10 and deal_name = "World Tour 2024" has active_ind = true
And sales_item records with sales_item_id = 101 and 102 exist under deal_id = 10
And billing_item records exist under each sales_item with billing_item_detail records for REV and PAY
When the user selects deal "World Tour 2024" and clicks "Generate Deal Statement"
Then the PDF shows a deal header with deal_name = "World Tour 2024" and deal.deal_reference
And revenue items 101 and 102 each have a section showing their receivable rows
And each receivable row shows billing_item_detail.billing_item_detail_amt for REV (commission) and PAY (payable)
And a generated_statement row is inserted with statement_ref beginning with 'DS-'
Scenario: Deal statement for an inactive deal still generates successfully
Given deal with deal_id = 20 has active_ind = false
When the user selects the inactive deal and generates a deal statement
Then the PDF generates without error
And the deal details block on the PDF shows the "Inactive" status indicator
And a generated_statement row is insertedFeature: Statements - Invoice Generation
Scenario: Generate a commission invoice for a client using US entity rules
Given party "Live Nation" (party_id = 55) exists with partyRoleTypeCd = 'CLIENT' in 3 deal_party rows
And billing_item records exist for that client with billing_item_detail_type_cd = 'REV'
And no billing_item_document rows exist for those billing items with document_type_cd = 'CI'
When the user selects "Client (Commission Invoice)", "US" entity, party "Live Nation"
And all 3 billing items are auto-selected
And clicks "Generate Invoice (3 items)"
Then an invoice record is inserted with invoice_type_cd = 'COMMISSION' and status_cd = 'DRAFT'
And invoice.invoice_number is formatted as 'UTA_US-{current_year}-{6-digit-sequence}'
And invoice_number_sequence.current_sequence is incremented for the US entity + current year
And 3 billing_item_document rows are inserted with document_type_cd = 'CI'
And the success panel shows the generated invoice_number
Scenario: UK entity invoice enforces one-client-per-invoice grouping
Given the user selects "UK" entity and selects billing items from 2 different clients
When the user clicks "Generate Invoice"
Then 2 separate invoice records are created: one per client
And both invoices have multi_client_ind = false
And both have the UK entity's invoice_number prefix
Scenario: Billing items already linked to an invoice are not available for re-invoicing
Given billing_item_id = 500 already has a billing_item_document row with document_type_cd = 'CI'
When the user loads billing items for a CLIENT invoice for the same client
Then billing_item_id = 500 does not appear in the billing items tableFeature: Statements - Statement History and Re-download
Scenario: Re-download a previously generated statement from the history tab
Given a generated_statement row exists with generated_statement_id = 77
And generated_statement.generation_status_cd = 'COMPLETED'
And generated_statement.s3_key = 'CLIENT_STATEMENT/42/2024-01-01_2024-12-31.pdf'
And generated_statement.file_name = 'CS-1710000000-ABCD1234.pdf'
When the user opens the Statement History tab
And clicks the download icon for generated_statement_id = 77
Then the PDF is retrieved from object storage using s3_key = 'CLIENT_STATEMENT/42/2024-01-01_2024-12-31.pdf'
And the file downloads to the browser as 'CS-1710000000-ABCD1234.pdf'
And no generated_statement record is created or modified
Scenario: History tab shows only completed statements
Given generated_statement rows exist with generation_status_cd values 'COMPLETED', 'FAILED', and 'PENDING'
When the user opens the Statement History tab
Then only the row with generation_status_cd = 'COMPLETED' appears in the history table
And rows with 'FAILED' and 'PENDING' are excluded
Scenario: History tab loads the 50 most recent completed statements
Given 60 completed generated_statement rows exist ordered by generated_dt
When the user opens the Statement History tab
Then the table shows 50 rows
And they are ordered by generated_statement.generated_dt descending
And the 10 oldest records do not appear