Skip to content

Cash Receipts Workflow

1. Executive Summary

Purpose

The cash receipts workflow manages the ingestion, tracking, and pre-processing of payments received from buyers before they can be applied to outstanding receivables. Every dollar that arrives at a UTA bank account — whether by wire transfer, ACH, check, or via an imported bank statement file — enters the Client Processing system as a cash_receipt record. From there, the receipt is subdivided into one or more splits, each split is tagged with contextual references (client, deal, buyer), and each split is then forwarded to a worksheet where cash is applied against billing items. The cash receipts workflow is therefore the front door to all downstream financial processing: no receivable can be applied, no client can be paid, and no GL entry can be posted until a receipt has been received, validated, and split.

Scope

Covered:

  • Manual creation of cash receipt records
  • Editing and inline updating of receipt header fields
  • Receipt amount adjustments (bank fees, corrections) via the adjustment mechanism
  • Receipt transfers to a different bank account with optional FX conversion
  • Receipt locking and unlocking for concurrency control
  • Receipt voiding (consequence of reducing the net amount to zero)
  • Split creation — default 1:1 split auto-created on receipt creation; additional splits carved from existing splits
  • Split amount adjustments and inter-split fund transfers
  • Split deletion with fund reallocation
  • Split notes (comments) editing
  • Split reference tagging — linking splits to clients, deals, buyers, departments, and payment terms for downstream receivable search and tax warning calculations
  • Quick reference addition inline from the cash receipts list page
  • Tax warning display on splits based on party references
  • Worksheet creation from a split (navigates user to the worksheet screen)
  • Document attachment viewing on receipts and splits

Not covered (documented separately):

Key Objectives

  • Provide a single point of entry for all cash arriving at UTA bank accounts.
  • Enforce the split-total invariant: the sum of all active split amounts must always equal the receipt's net_receipt_amt, preventing unbalanced cash.
  • Enable parallel processing of multi-party or multi-deal deposits by subdividing one receipt into independently processable splits.
  • Tag splits with enough contextual information (client, deal, buyer references) so that the downstream worksheet can suggest relevant receivables for matching.
  • Surface early tax warnings on splits when a referenced party may be subject to withholding, before the worksheet-level tax calculation runs.

2. Process Overview

mermaid
flowchart TD
    A([Buyer payment arrives at UTA bank]) --> B{Source}
    B -->|Bank file import| C[Bank transaction synced via living-mirror]
    B -->|Manual entry| D[User opens Add Cash Receipt dialog]
    C --> E[cash_receipt created automatically]
    D --> E
    E --> F[Default 1:1 split auto-created\ncash_receipt_split created\nDraft worksheet auto-created]
    F --> G{Receipt needs splitting?}
    G -->|No — single deal/client| H[Tag split with references\nclient, deal, buyer, payment term]
    G -->|Yes — multi-deal or multi-client| I[User creates additional splits\ncarving amounts from existing split]
    I --> H
    H --> J{Tax warning?}
    J -->|Yes| K[Tax warning badge displayed on split]
    J -->|No| L[Proceed]
    K --> L
    L --> M[User opens worksheet for split]
    M --> N([Worksheet workflow — apply cash to receivables])

Walkthrough

  1. Receipt arrives — A payment is received at a UTA bank account, either through automatic bank statement ingestion (see bank-ingestion workflow) or through manual entry by a user. In both cases, a cash_receipt record is created.

  2. Default split and worksheet auto-created — Immediately upon receipt creation, the split service creates a 1:1 cash_receipt_split record equal to cash_receipt.net_receipt_amt, and a Draft (D) cash_receipt_worksheet is created for that split. No user action is required for this step.

  3. Receipt editing — If the receipt requires corrections (wrong amount, wrong bank account, wrong currency), a user opens the receipt's edit dialog. The fields available for editing depend on cash_receipt.posting_status_cd: all fields are editable when Unposted (U) and no bank-imported filename or worksheet exists; only cash_receipt_comment and net_receipt_amt (via adjustments) when Posted (P); only cash_receipt_ref and cash_receipt_comment when Voided (V).

  4. Amount adjustment — If a bank fee or correction reduces the net amount of the receipt, a user creates a cash_receipt_adjustment record. The adjustment amount is deducted from cash_receipt.net_receipt_amt and simultaneously reduces the relevant split's split_amt. Only splits whose worksheet is in Draft status or has no worksheet can be adjusted.

  5. Reference tagging — The user tags each split with references that identify who the money is from and who it is for. References (stored in cash_receipt_reference) are informational: they drive suggested receivable filters in the worksheet and trigger tax warning calculations. The user can add references inline on the cash receipts list page or through the full Split Management panel.

  6. Splitting — If the receipt contains payments for more than one deal or client, the user creates additional splits through the Split Management panel. Each new split carves its amount from an existing split, maintaining the invariant that all split amounts sum to cash_receipt.net_receipt_amt.

  7. Inter-split fund transfer — If the allocation between existing splits needs to change, the user transfers funds from one split to another using the Transfer Funds action. Both splits must belong to the same receipt and both must have worksheets in Draft status or no worksheet.

  8. Tax warning check — When a CLIENT_ID or CONTRACTED_PARTY_ID reference is added to a split, the tax service evaluates whether withholding may apply. If so, cash_receipt_split.tax_warning_ind is set to true and tax_warning_json is populated. The warning is shown as a badge on the split row.

  9. Worksheet creation — When the user is ready to apply the split's cash, they click the "Open Worksheet" link or the "Create Worksheet" button for the split. This navigates to (or creates) the worksheet where cash is applied against billing items.


3. Business Rules

3.1 Amount Must Be Greater Than Zero

Business rule: A cash receipt cannot be created with an amount of zero or less. cash_receipt.original_receipt_amt must be positive.

Foundation reference: Receipt Creation Validation

Workflow context: The Add Cash Receipt dialog disables the Save button and shows an inline error if the amount field is zero or negative.


3.2 Split Total Must Equal Net Receipt Amount

Business rule: The sum of all non-voided cash_receipt_split.split_amt values for a receipt must equal cash_receipt.net_receipt_amt, within a tolerance of 0.005. Splits are always created by carving amounts from existing splits; the total can never drift.

Foundation reference: Split Total Validation

Workflow context: The Split Management panel shows a "Balanced" indicator when the difference is within tolerance and a red difference amount when it is not. The "Create Split" action validates balance before saving.


3.3 Split Amount Floor — Cannot Go Below Applied Amount

Business rule: A split's split_amt cannot be reduced below the sum of approved applications on its worksheet. If $3,000 has been applied on the worksheet, the split cannot be adjusted below $3,000.

Foundation reference: Split Amount Floor

Workflow context: When a user enters a new split amount in the adjustment dialog, the service checks the applied amount and returns an error: "Cannot reduce split below approved applications ($X.XX)."


3.4 Cannot Modify Split When Worksheet Is Applied or Later

Business rule: A split's amount, fund transfers, and deletion are blocked when the split's associated worksheet has progressed beyond Draft (D) status to Applied (P), Settled (T), Approved (A), or Returned (R).

Foundation reference: Split Modification Rules by Worksheet Status

Workflow context: In the Split Management panel, the Edit, Delete, and transfer actions for a split are disabled when the worksheet status badge shows Applied, Settled, Approved, or Returned.


3.5 Cannot Delete the Last Split

Business rule: At least one split must exist for every receipt. Deleting the last remaining split is not permitted.

Foundation reference: Split Deletion Rules

Workflow context: The Delete action on the last split in the Split Management panel is disabled with a tooltip explaining that the last split cannot be deleted.


3.6 Deleting a Split With Funds Requires a Target Split

Business rule: If a split being deleted has a non-zero split_amt, the user must specify a target split to receive the remaining funds. The transfer and deletion are performed atomically.

Foundation reference: Split Deletion With Fund Transfer

Workflow context: The Delete Split dialog shows a "Transfer remaining funds to" dropdown when the split has a non-zero amount. The Save button is disabled until a target is selected.


3.7 Void Is the Consequence of Zeroing the Amount

Business rule: There is no independent void action on a receipt. A receipt becomes Voided (V) automatically when adjustments reduce cash_receipt.net_receipt_amt to zero. All splits are voided and empty Draft worksheets are deleted as a side-effect.

Foundation reference: Receipt Voiding Via Adjustment

IMPORTANT

This design preserves the audit trail: the adjustment records that caused the void remain, so it is always possible to see why a receipt was cancelled. There is no way to void a receipt that has active (non-Draft) worksheets with applications.


3.8 Voided Receipts Are Read-Only Except for Ref and Comment

Business rule: Once cash_receipt.posting_status_cd = 'V', only cash_receipt_ref and cash_receipt_comment may be modified. All splits are locked. No splits can be created, deleted, or adjusted.

Foundation reference: Receipt Update Rules by Posting Status

Workflow context: Voided receipt rows in the table show inline pencil icons on the Ref and Comment columns only. The action menu is hidden for voided rows. The Split Management panel shows a "This receipt is voided — actions are disabled" banner.


3.9 FX Rate Required When Currencies Differ

Business rule: If cash_receipt.original_currency_cd differs from cash_receipt.currency_cd, cash_receipt.fx_rate must be provided and must be greater than zero. The working amount (receipt_amt) is calculated as original_receipt_amt * fx_rate.

Foundation reference: Currency Conversion Calculation

Workflow context: In the Add/Edit Cash Receipt dialog, when the Original Currency and Working Currency dropdowns differ, an FX Rate input field appears. The dialog validates that the FX rate is a positive number before saving.


3.10 Adjustments Cannot Be Applied to Voided Receipts

Business rule: No new cash_receipt_adjustment records can be created for a receipt with posting_status_cd = 'V'.

Foundation reference: Adjustment Rules


3.11 Posted Adjustments Cannot Be Deleted

Business rule: A cash_receipt_adjustment with posting_status_cd = 'P' is read-only and cannot be deleted. Transfer-type adjustments (adjustment_type_cd = 'TR') also cannot be deleted.

Foundation reference: Adjustment Deletion Rules


3.12 References Are Informational Only

Business rule: cash_receipt_reference records are not foreign key enforced. They store identifier values as strings for search suggestion and tax warning purposes. The actual tax calculation always uses the billing item's data on the worksheet, never the split reference.

Foundation reference: Reference Rules

Workflow context: References are displayed as colored badge tags (Client, Deal, Buyer, Term, Sale, Dept) on each split row. Hovering a badge shows the raw ref_or_id value.


3.13 Tax Warning Set When Party Reference Is Added

Business rule: When a CLIENT_ID or CONTRACTED_PARTY_ID reference is added to a split, the withholding tax service evaluates whether withholding may apply. If so, cash_receipt_split.tax_warning_ind is set to true and cash_receipt_split.tax_warning_json is populated.

Foundation reference: TODO: Document in foundation/procedures/cash-receipts.md (tax warning update procedure)

Workflow context: A tax warning indicator badge appears on the split row. This is a preliminary warning only; the definitive withholding calculation happens at the worksheet level using the billing item data.


3.14 New Split Auto-Creates a Draft Worksheet

Business rule: Every new cash_receipt_split automatically gets a Draft (D) cash_receipt_worksheet created for it. This applies to the default 1:1 split created at receipt creation and to every additional split created by the user.

Foundation reference: Default Split and Worksheet Creation


4. Data Access & Operations References

4.1 Queries Used

OperationFoundation DocPurpose in This Workflow
searchCashReceiptsSearch Cash ReceiptsPopulates the cash receipts list on page load and after every save. Supports filtering by ref, bank account, date range, filename, and posting status.
getSplitsForReceiptsGet Splits for Receipts (Bulk)Loads split rows and reference tags for the selected receipt(s) in the inline splits panel. Also used for split count badges in the receipt table.
getSplitsWithWorksheetsGet Splits with Worksheets by Receipt IDLoads the Split Management panel with all splits and their current worksheet status, applied/remaining amounts, and lock state.
getCashReceiptByIdGet Cash Receipt by IDFetches the current receipt for validation before update operations.
getAdjustmentsForReceiptGet Adjustments by Cash Receipt IDLoads the adjustments panel in the edit dialog.
sumByCashReceiptIdSum Adjustments by Cash Receipt IDRecalculates cash_receipt.net_receipt_amt after creating or deleting an adjustment.
getAdjustAmountEligibilityTODO: Document in foundation/queries/cash-receipts.mdChecks which splits of a receipt are eligible for amount adjustment (Draft worksheet or no worksheet). Displayed in the edit dialog to show adjustable splits and their unapplied headroom.
getBankAccountOptionsTODO: Document in foundation/queries/cash-receipts.mdPopulates the bank account dropdown in the Add/Edit dialog and the Transfer dialog.
getUnpostedMetricGet Unposted Receipts MetricPowers the dashboard unposted receipts count and total amount card.
getCashReceivedTodayTotalGet Cash Received Today TotalPowers the dashboard cash-received-today metric.
getFileCountsForEntitiesTODO: Document in foundation/queries/cash-receipts.mdLoads document attachment counts for all receipt rows and all split rows in bulk.
getReferencesBySplitIdGet References by Split IDResolves references when calculating tax warnings for a specific split.

4.2 Procedures Used

OperationFoundation DocTrigger in This Workflow
createCashReceiptCreate Cash ReceiptUser saves the Add Cash Receipt dialog.
createDefaultSplitCreate Default SplitCalled automatically inside createCashReceipt; not a direct user action.
updateCashReceiptUpdate Cash ReceiptUser saves the Edit Cash Receipt dialog with field changes.
updateCashReceiptInlineTODO: Document in foundation/procedures/cash-receipts.mdUser clicks and edits the Ref or Comment cell inline on a voided receipt row.
createAdjustmentCreate Cash Receipt AdjustmentUser adds an adjustment in the Adjustments section of the edit dialog.
deleteAdjustmentDelete Cash Receipt AdjustmentUser deletes an unposted, non-transfer adjustment in the Adjustments section.
createTransferCreate Cash Receipt TransferUser specifies a destination bank account and amount in the Transfer section of the edit dialog.
lockCashReceiptLock Cash ReceiptUser clicks the lock action on a receipt.
unlockCashReceiptUnlock Cash ReceiptUser clicks the unlock action on a locked receipt.
createSplitCreate Cash Receipt SplitUser saves the Create Split dialog in the Split Management panel.
updateSplitUpdate Cash Receipt SplitUser saves the Edit Split dialog in the Split Management panel.
adjustSplitAmountAdjust Split AmountUser changes the amount in the Edit Split dialog in the Split Management panel.
updateSplitNotesUpdate Split NotesUser clicks and edits the Comments cell inline on a split row.
transferFundsBetweenSplitsTransfer Funds Between SplitsUser saves the Transfer Funds dialog in the Split Management panel.
deleteSplitDelete Cash Receipt SplitUser confirms deletion in the Delete Split dialog.
addCashReceiptReferenceAdd Cash Receipt ReferenceUser selects a search result in the inline reference add field on the cash receipts list page.
createWorksheetForSplitCreate Worksheet for SplitUser clicks "Create Worksheet" or the worksheet link on a split row.

5. Key User Actions

5.1 Add Cash Receipt

Preconditions:

  • User has CASH_MANAGER or IT role.
  • At least one active bank account must exist in the system.

Procedure reference: Create Cash Receipt

Steps:

  1. User clicks "Add Cash Receipt" button on the cash receipts list page.
  2. User fills in Deposit Date, Bank Account, Receipt Ref (optional), Amount, Original Currency, Working Currency, FX Rate (if currencies differ), and Comment (optional).
  3. User clicks Save.
  4. The system creates a cash_receipt record with posting_status_cd = 'U'.
  5. The system auto-creates a default cash_receipt_split with split_amt = net_receipt_amt and a Draft cash_receipt_worksheet for that split.
  6. The receipt list refreshes with the new row.

Postconditions:

  • cash_receipt.posting_status_cd = 'U'
  • cash_receipt.net_receipt_amt = original_receipt_amt (or original_receipt_amt * fx_rate when currency conversion applied)
  • One cash_receipt_split row with split_sequence = 1, split_amt = net_receipt_amt, split_status_cd = 'N'
  • One cash_receipt_worksheet row with cash_receipt_worksheet_status_cd = 'D', current_item_ind = true

UI trigger: "Add Cash Receipt" button. Always visible and always enabled.


5.2 Edit Cash Receipt

Preconditions:

  • Receipt exists.
  • cash_receipt.posting_status_cd is not 'V' for full field edits.
  • For full field edit (all fields): posting_status_cd = 'U', no bank-imported filename, and no worksheet exists for any split.

Procedure reference: Update Cash Receipt

Steps:

  1. User clicks "Edit" from the action menu on a receipt row.
  2. The edit dialog opens, pre-populated with current receipt fields.
  3. Editable fields depend on posting_status_cd: all fields when Unposted and not yet worksheeted; only Comment when Posted; only Ref and Comment when Voided.
  4. User modifies fields and clicks Save.
  5. The cash_receipt record is updated. If the amount changed and only one split without a worksheet exists, that split's split_amt is updated to match.

Postconditions:

  • cash_receipt fields updated per changes.
  • If amount changed and one worksheet-less split exists: cash_receipt_split.split_amt updated to match new net_receipt_amt.

UI trigger: "Edit" item in the receipt row action menu. Action menu visible on non-voided rows only. For voided rows, inline click-to-edit is shown directly in the Ref and Comment table cells.


5.3 Adjust Receipt Amount (Add Adjustment)

Preconditions:

  • cash_receipt.posting_status_cd is not 'V'.
  • At least one split exists with a Draft worksheet or no worksheet.
  • New adjusted amount must be >= the applied amount on the split's worksheet.

Procedure reference: Create Cash Receipt Adjustment

Steps:

  1. User opens the Edit Cash Receipt dialog.
  2. User clicks "Add Adjustment" in the Adjustments section.
  3. User enters the adjustment amount (positive), a required comment, and selects which split to reduce.
  4. User clicks Save Adjustment.
  5. A cash_receipt_adjustment record is created with adjustment_type_cd = 'ADJ' and posting_status_cd = 'U'.
  6. The selected split's split_amt is reduced by the adjustment amount.
  7. cash_receipt.net_receipt_amt is recalculated as receipt_amt - SUM(adjustment_amt).
  8. If net_receipt_amt reaches zero, all splits are voided and the receipt's posting_status_cd is set to 'V'.

Postconditions:

  • New cash_receipt_adjustment row with posting_status_cd = 'U'.
  • cash_receipt_split.split_amt reduced on the selected split.
  • cash_receipt.net_receipt_amt updated.
  • If net reaches zero: cash_receipt.posting_status_cd = 'V', all splits voided.

UI trigger: "Add Adjustment" button in the Adjustments section of the Edit Cash Receipt dialog. Visible when editing an existing receipt. Enabled when posting_status_cd != 'V'.


5.4 Delete Adjustment

Preconditions:

  • cash_receipt.posting_status_cd is not 'V'.
  • cash_receipt_adjustment.posting_status_cd = 'U' (not posted).
  • cash_receipt_adjustment.adjustment_type_cd != 'TR' (transfers cannot be deleted).

Procedure reference: Delete Cash Receipt Adjustment

Steps:

  1. User clicks the delete icon next to an adjustment row in the Edit dialog.
  2. The system restores the adjustment amount back to the associated split's split_amt.
  3. The adjustment record is deleted.
  4. cash_receipt.net_receipt_amt is recalculated.

Postconditions:

  • cash_receipt_adjustment row deleted.
  • cash_receipt_split.split_amt restored by the adjustment amount.
  • cash_receipt.net_receipt_amt updated.

UI trigger: Trash icon on each adjustment row in the Edit dialog. Disabled for posted adjustments (posting_status_cd = 'P') and for transfer-type adjustments (adjustment_type_cd = 'TR').


5.5 Transfer to Different Bank Account

Preconditions:

  • cash_receipt.posting_status_cd is not 'V'.
  • Destination bank account must be active.
  • Source split must have a Draft worksheet or no worksheet.
  • Transfer amount must be positive and not exceed the split's available balance.

Procedure reference: Create Cash Receipt Transfer

Steps:

  1. User opens the Edit Cash Receipt dialog and clicks "Transfer to Another Bank."
  2. User selects the destination bank account, enters a transfer amount, and selects the source split.
  3. User clicks Execute Transfer.
  4. A cash_receipt_adjustment record with adjustment_type_cd = 'TR' is created, reducing the source split's amount and the receipt's net_receipt_amt.
  5. A new cash_receipt is created on the destination bank account with the converted amount (using FX rates if the currencies differ).
  6. The new receipt on the destination bank gets a default 1:1 split and Draft worksheet.

Postconditions:

  • Source cash_receipt_adjustment created with adjustment_type_cd = 'TR'.
  • Source cash_receipt_split.split_amt reduced.
  • Source cash_receipt.net_receipt_amt reduced.
  • New cash_receipt created at destination bank with converted net_receipt_amt.

UI trigger: "Transfer to Another Bank" button in the Edit Cash Receipt dialog. Visible when editing an existing non-voided receipt.

**PoC Artifact:** FX rates in the PoC transfer implementation are hardcoded demo values (`USD: 1.0, GBP: 0.79, EUR: 0.92`, etc.). Production must use a real FX rate feed.


5.6 Lock / Unlock Cash Receipt

Preconditions:

  • For Lock: receipt is not already locked (locked_by_user_id is null).
  • For Unlock: receipt is locked; current user is the lock holder or has IT role.

Procedure reference: Lock / Unlock Cash Receipt

Steps:

  1. User clicks the lock or unlock action on a receipt.
  2. cash_receipt.locked_by_user_id is set to the current user's ID (lock) or cleared to null (unlock).

Postconditions:

  • cash_receipt.locked_by_user_id set to the user's ID (lock) or null (unlock).

UI trigger: Lock/unlock control on the receipt row or edit dialog. Locked-by user name appears in the "Locked By" column of the receipts table.


5.7 Add Reference to Split (Quick Add)

Preconditions:

  • Split is not voided (split_status_cd != 'V').
  • Split status allows reference modification (status N, S, A, or R).
  • posting_status_cd on the parent receipt is not 'V'.

Procedure reference: Add Cash Receipt Reference

Steps:

  1. User selects a receipt row (or uses checkbox selection) to reveal the splits panel.
  2. User clicks the "+" add icon on a split's Match column to expand the inline reference search field.
  3. User types a search term (minimum 2 characters). The universal search returns matching parties, deals, revenue items, and billing items.
  4. User selects a result. The system maps the result type to a cash_receipt_reference.type_cd value (party → CLIENT_ID, deal → DEAL_ID, revenue item → SALES_ITEM_REF, billing item → PAYMENT_TERM_REF).
  5. A cash_receipt_reference record is created.
  6. The splits panel refreshes to show the new reference tag.
  7. If the reference is a party (CLIENT_ID or CONTRACTED_PARTY_ID), the tax service evaluates withholding warnings.

Postconditions:

  • New cash_receipt_reference row with the selected type_cd and ref_or_id.
  • If party reference: cash_receipt_split.tax_warning_ind may be set to true and tax_warning_json populated.

UI trigger: "+" icon in the Match column of a split row in the inline splits panel. Visible on non-voided splits.


5.8 Create Additional Split

Preconditions:

  • Receipt posting_status_cd is not 'V'.
  • At least one source split exists with available balance greater than zero.
  • Source split's worksheet must be in Draft status or the split must have no worksheet.

Procedure reference: Create Cash Receipt Split

Steps:

  1. User opens the Split Management panel for a receipt.
  2. User clicks "Create Split."
  3. The Create Split dialog opens, showing the source split's available balance.
  4. User enters the new split amount, optional notes, and an optional supporting file attachment.
  5. User clicks Save.
  6. The source split's split_amt is reduced by the new amount.
  7. A new cash_receipt_split record is created with split_status_cd = 'N' and parent_split_id = source split ID.
  8. A Draft cash_receipt_worksheet is auto-created for the new split.
  9. If the new amount equals all of the source split's remaining balance, the source split and its empty Draft worksheet are auto-deleted.

Postconditions:

  • Source cash_receipt_split.split_amt reduced (or source deleted if fully consumed).
  • New cash_receipt_split row with split_status_cd = 'N'.
  • New cash_receipt_worksheet row with cash_receipt_worksheet_status_cd = 'D'.
  • Split total still equals cash_receipt.net_receipt_amt.

UI trigger: "Create Split" button in the Split Management panel. Enabled when posting_status_cd != 'V'.


5.9 Transfer Funds Between Splits

Preconditions:

  • At least two splits exist on the receipt.
  • Both source and target splits must have worksheets in Draft status or no worksheet.
  • Transfer amount must not exceed the source split's available balance.
  • Both splits must belong to the same receipt.

Procedure reference: Transfer Funds Between Splits

Steps:

  1. User opens the Split Management panel and clicks "Transfer Funds."
  2. The Transfer Funds dialog opens with a source split selector, target split selector, and amount field.
  3. User selects source, target, and enters the amount to transfer.
  4. User clicks Transfer.
  5. Both split amounts are updated atomically: source reduced, target increased.
  6. If the source is reduced to zero, it is auto-deleted (when worksheet is empty Draft).

Postconditions:

  • Source cash_receipt_split.split_amt reduced.
  • Target cash_receipt_split.split_amt increased.
  • Receipt total unchanged.

UI trigger: "Transfer Funds" button in the Split Management panel. Enabled when at least two splits exist and posting_status_cd != 'V'.


5.10 Delete Split

Preconditions:

  • At least two splits exist (cannot delete the last split).
  • Split's worksheet must be in Draft status with no applications, or the split must have no worksheet.
  • If the split has remaining funds, a target split must be provided.

Procedure reference: Delete Cash Receipt Split

Steps:

  1. User clicks the trash icon on a split row in the Split Management panel.
  2. The Delete Split dialog opens, showing the split's amount and a "Transfer remaining funds to" selector.
  3. If the split has a non-zero amount, user selects a target split.
  4. User confirms deletion.
  5. If funds remain, they are transferred to the target split first.
  6. The split's empty Draft worksheet (if any) is deleted.
  7. The split record is deleted.

Postconditions:

  • cash_receipt_split row deleted.
  • Funds transferred to target split if non-zero amount.
  • Receipt total unchanged.

UI trigger: Trash icon on each split row in the Split Management panel. Disabled on the last remaining split and on splits whose worksheet has progressed beyond Draft.


5.11 Edit Split (Notes or Amount)

Preconditions:

  • For amount change: split's worksheet must be in Draft status or have no worksheet; new amount must be >= applied amount.
  • For notes change only: split must not be voided; notes can be updated regardless of worksheet status.

Procedure reference: Update Cash Receipt Split

Steps:

  1. For the Split Management panel: user clicks the edit icon on a split row; the Edit Split dialog opens pre-filled with current values; user modifies fields and saves.
  2. For inline comments on the splits panel: user clicks the Comments cell; the cell becomes an editable input; user types and presses Enter or clicks away to save.

Postconditions:

  • cash_receipt_split.split_amt updated (if changed).
  • cash_receipt_split.notes updated (if changed).

UI trigger: Edit icon on each split row in the Split Management panel. Comments cell on the inline splits panel is always click-to-edit for non-voided splits.


5.12 Open or Create Worksheet for Split

Preconditions:

  • Split must have an associated worksheet (all splits get a Draft worksheet auto-created on creation).
  • If no worksheet exists (legacy data edge case): the create-worksheet action creates one first.

Procedure reference: Create Worksheet for Split

Steps:

  1. User clicks the worksheet status badge (e.g., "Draft" with link icon) on a split row in the inline splits panel or Split Management panel.
  2. The system navigates to the worksheet detail page in the same tab (or creates the worksheet if none exists, then navigates).

Postconditions:

  • User is navigated to /worksheets/[worksheetId].
  • If worksheet was created: new cash_receipt_worksheet row with cash_receipt_worksheet_status_cd = 'D'.

UI trigger: Worksheet status badge/link on the split row. Always visible when a worksheet exists. A "Create Worksheet" button is shown when no worksheet exists.


6. Permissions & Role-Based Access

ActionCASH_MANAGERCASH_PROCESSORSETTLEMENT_APPROVERIT
View cash receipts listYesYesYesYes
Add cash receipt (manual)YesYes
Edit cash receipt fieldsYesYes
Add / delete adjustmentYesYes
Create transfer to bankYesYes
Lock / unlock receiptYesYes
View splits panelYesYesYesYes
Add reference to splitYesYes
Create additional splitYesYes
Edit split (amount / notes)YesYes
Transfer funds between splitsYesYes
Delete splitYesYes
Create worksheet for splitYesYes
Open / view worksheetYesYesYesYes

Field-level restrictions:

  • On voided receipts (posting_status_cd = 'V'): only cash_receipt_ref and cash_receipt_comment are editable (inline in the table). All split management actions are disabled; the Split Management panel shows a voided receipt banner.
  • On posted receipts (posting_status_cd = 'P'): only cash_receipt_comment is editable via the dialog form; net_receipt_amt can only change through the adjustment mechanism.
  • Receipt locking (locked_by_user_id non-null): only the locking user or IT can unlock. The "Locked By" column in the receipts table shows the lock holder.

**PoC Artifact:** Role enforcement in the PoC uses a mock user cookie (`mock_user_id`). Production must wire actual session authentication and role checks in all server actions.


7. Integration Points

7.1 Upstream

SourceData ProvidedMechanism
Bank Statement File Import (CAMT.053 / CAMT.052)cash_receipt records auto-created from bank_transaction rows; bank_ref_id and entry_status populated from bank dataLiving-mirror sync: findByBankReference deduplication + syncFromBankTransaction upsert. See Bank Ingestion Workflow.
Write-Off Packet Approvalcash_receipt with receipt_type_cd = 'WRITE_OFF' created programmatically when a write-off packet is approvedService-to-service call from WriteOffPacketService to CashReceiptService. See Write-Offs Workflow.
Cash Matching Screencash_receipt_reference records added to splits when the user saves a match in the cash matching workflowaddCashReceiptReference action called from the cash-matching screen. See Cash Matching Workflow.

7.2 Downstream

ConsumerData ConsumedMechanism
Worksheets Workflowcash_receipt_split.split_amt (available balance), cash_receipt_split.cash_receipt_split_id (FK), split references (suggested receivable filters), cash_receipt_split.tax_warning_ind (early warnings)FK lookup from cash_receipt_worksheet to cash_receipt_split; worksheet reads split context on load.
GL Posting Batch Jobcash_receipt rows with posting_status_cd = 'U' and deposit_date <= cutoff date; bank_account.uta_account_id for GL account mappinggetUnpostedReceiptsUpToDate query called by the accounting batch job. See Accounting Jobs Workflow.
Tax Warning Servicecash_receipt_reference entries of type_cd = 'CLIENT_ID' or 'CONTRACTED_PARTY_ID' on the splitCalled internally after addCashReceiptReference; updates cash_receipt_split.tax_warning_ind and tax_warning_json.
Dashboard MetricsUnposted count and total, cash received today totalgetUnpostedMetric and getCashReceivedTodayTotal queries.
Client Detail Payment Historycash_receipt records linked to a client's billing items via worksheet applicationsgetCashReceiptsByClientId query joining through cash_receipt_application to billing_item.

7.3 External Integrations

SystemDirectionProtocolNotes
Bank APIs (CNB, JPM, BofA)InboundISO 20022 CAMT.053/CAMT.052 XML; EASI Link JSONSource of auto-generated receipts via bank statement ingestion. Handled by the bank ingestion workflow; cash receipts workflow only consumes the resulting cash_receipt records.
FX Rate ProviderInboundTODODemo FX rates are hardcoded in the PoC. Production requires integration with a real FX rate feed for both receipt conversion and transfer conversion.

8. Functional Screen Requirements

8.1 Cash Receipts List Page

Route: /cash-receipts

Data loading:

  • searchCashReceiptsSearch Cash Receipts (all receipts on initial load, capped at 100 results displayed)
  • getSplitsForReceipts (bulk) — Get Splits for Receipts Bulk — loads split counts and reference tags for all displayed rows in a single batch query
  • getFileCountsForEntities (bulk) — loads document attachment counts for all receipt rows in a single batch query

Receipt Table Region

Displays all cash receipts as a sortable, filterable, paginated data grid. Each row represents one cash_receipt record.

Field / ColumnSourceEditable?Condition
Datecash_receipt.deposit_dateNoAlways visible
Bank Accountbank_account.bank_account_name (joined via bank_account_id)NoAlways visible; blank for receipts with no bank account set
Filenamecash_receipt.filenameNoAlways visible; blank for manual receipts
Refcash_receipt.cash_receipt_refYes (inline click-to-edit)Inline edit available only when posting_status_cd = 'V'
Commentcash_receipt.cash_receipt_commentYes (inline click-to-edit)Inline edit available only when posting_status_cd = 'V'
Posting Statuscash_receipt.posting_status_cdNoAlways visible; "VOID" badge for 'V', "Unposted" for 'U', "Posted" for 'P'
Currcash_receipt.currency_cdNoAlways visible
Amountcash_receipt.net_receipt_amtNoAlways visible; formatted as currency
Orig Currcash_receipt.original_currency_cdNoAlways visible
FX Ratecash_receipt.fx_rateNoAlways visible; formatted to 4 decimal places; 1.0000 when no conversion
Orig Amtcash_receipt.original_receipt_amtNoAlways visible; formatted as currency in original currency
Post Datecash_receipt.posting_dtNoAlways visible; blank until posting_status_cd = 'P'
Created ByResolved from cash_receipt.created_byusers.first_name + last_nameNoAlways visible
Created Dtcash_receipt.created_dtNoAlways visible
Updated ByResolved from cash_receipt.updated_byusers.first_name + last_nameNoAlways visible
Updated Dtcash_receipt.updated_dtNoAlways visible
Locked Bycash_receipt.locked_by_user_id resolved to users.first_name + last_nameNoBlank when locked_by_user_id is null
SplitsCount of cash_receipt_split rows (from bulk load)NoAlways visible; highlighted badge when has_multiple_splits = true
DocsCount of file attachments (from bulk file-count load)NoButton disabled when count = 0; opens document dialog on click
ActionEdit action menu (three-dot icon)Hidden on voided rows

Grid features:

  • Sortable columns: all data columns
  • Filters: global text filter applied across all visible text fields
  • Row selection: checkbox (multi-select) and single-row click — both trigger the splits panel below
  • Pagination: enabled

Conditional display:

  • Action menu (three-dot icon) visible and enabled only on non-voided rows.
  • Splits count badge highlighted in purple when has_multiple_splits = true.
  • Docs button disabled when document count = 0.
  • Inline click-to-edit pencil icon visible on Ref and Comment cells only for voided rows.

Inline Splits Panel Region

Appears below the receipt table when one or more receipts are selected (row click or checkbox selection). Shows all splits for the selected receipt(s). The panel is sortable.

Field / ColumnSourceEditable?Condition
Split #cash_receipt_split.split_sequenceNoAlways visible
Amountcash_receipt_split.split_amtNoAlways visible; formatted as currency
Statuscash_receipt_split.split_status_cd resolved via code masterNoAlways visible; color-coded badge
Commentscash_receipt_split.notesYes (inline click-to-edit)Editable in any non-voided status
Matchcash_receipt_reference records for the split (type:value badge tags)No (add via inline search)Displayed as colored typed badge tags
Worksheetcash_receipt_worksheet.cash_receipt_worksheet_status_cd (linked)NoShows status badge and link to worksheet; "Create Worksheet" button when none exists

Grid features:

  • Sortable columns: Split #, Amount, Status, Comments, Match (by reference count), Worksheet (by status code)
  • Filters: none (panel is scoped to selected receipt(s))
  • Row selection: none
  • Pagination: none (all splits displayed)

Conditional display:

  • "Manage Splits" button shown only when exactly one receipt is selected.
  • Split rows with a voided parent receipt displayed with a highlighted background.
  • Inline reference "+" add icon visible on each non-voided split row.
  • Tax warning badge visible on split row when cash_receipt_split.tax_warning_ind = true.
  • Worksheet cell shows link to open existing worksheet when worksheetId is populated; shows "Create Worksheet" button when no worksheet exists.
  • Panel header shows "({n} receipts selected)" note when more than one receipt is selected via checkbox.
  • Close button collapses the splits panel.

8.2 Add / Edit Cash Receipt Dialog

Route: Modal overlay on /cash-receipts

Data loading:

  • getBankAccountOptions — populates Bank Account dropdown on dialog open
  • getAdjustAmountEligibility — loads split eligibility data (edit mode only, on dialog open)
  • getAdjustmentsForReceipt — loads the adjustments list (edit mode only, on dialog open)

Form Region

Field / ColumnSourceEditable?Condition
Deposit Datecash_receipt.deposit_dateYesWhen canFullEdit = true (unposted, no worksheet, no filename)
Bank Accountcash_receipt.bank_account_idYesWhen canFullEdit = true
Receipt Refcash_receipt.cash_receipt_refYesWhen canFullEdit = true
Original Amountcash_receipt.original_receipt_amtYesWhen canFullEdit = true OR canAdjustAmount = true
Original Currencycash_receipt.original_currency_cdYesWhen canFullEdit = true
Working Currencycash_receipt.currency_cdYesWhen canFullEdit = true; auto-populated from selected bank account
FX Ratecash_receipt.fx_rateYesWhen canFullEdit = true AND original_currency_cd != currency_cd
Converted AmountComputed: original_receipt_amt * fx_rateNoWhen canFullEdit = true AND currencies differ; display only
Commentcash_receipt.cash_receipt_commentYesAlways editable in all posting statuses
Split selectorcash_receipt_split.cash_receipt_split_id (adjustable splits only)YesShown when canAdjustAmount = true and more than one adjustable split exists

Conditional display:

  • FX Rate field and Converted Amount row visible only when original_currency_cd != currency_cd.
  • Amount field and split selector shown when canAdjustAmount = true (at least one split with Draft worksheet or no worksheet).
  • All form fields except Comment are read-only when posting_status_cd = 'P'.
  • All form fields except Comment are read-only when posting_status_cd = 'V'.

Adjustments Region (Edit Mode Only)

Lists existing cash_receipt_adjustment records and allows adding new ones for the selected receipt.

Field / ColumnSourceEditable?Condition
Adjustment Amountcash_receipt_adjustment.adjustment_amtNoAlways visible per row
Commentcash_receipt_adjustment.commentNoAlways visible per row
Typecash_receipt_adjustment.adjustment_type_cdNoADJ shown as "Adjustment", TR shown as "Transfer"
Posting Statuscash_receipt_adjustment.posting_status_cdNoU = Unposted, P = Posted
DeleteButton enabled only for unposted ('U'), non-transfer adjustments

Conditional display:

  • "Add Adjustment" button visible when posting_status_cd != 'V'.
  • New adjustment inline form (amount, comment, split selector) shown when "Add Adjustment" is clicked.
  • Trash icon disabled for posted adjustments (posting_status_cd = 'P') and for transfer-type adjustments (adjustment_type_cd = 'TR').

Transfer Region (Edit Mode Only)

Allows transferring a portion of the receipt's net amount to a different bank account, creating a new receipt there.

Field / ColumnSourceEditable?Condition
Destination Bank Accountbank_account.bank_account_idYesWhen transfer form is expanded
Transfer AmountUser-enteredYesWhen transfer form is expanded
Source Splitcash_receipt_split.cash_receipt_split_id (only adjustable splits)YesWhen transfer form is expanded
Converted Amount PreviewComputed: transfer_amt * fx_rateNoWhen destination bank currency differs from source receipt currency

Conditional display:

  • "Transfer to Another Bank" button visible when editing a non-voided receipt.
  • Transfer form shown when the button is clicked.
  • FX conversion preview shown when destination bank account currency differs from the source receipt's currency_cd.

8.3 Split Management Panel

Route: Side panel (sheet overlay) on /cash-receipts

Data loading:

Summary Region

Shows receipt-level balance context.

Field / ColumnSourceEditable?Condition
Receipt Amountcash_receipt.net_receipt_amtNoAlways visible
Total SplitsSUM(cash_receipt_split.split_amt) computedNoAlways visible
Differencenet_receipt_amt - SUM(split_amt) computedNo"Balanced" when within 0.005 tolerance; red difference amount otherwise

Split List Region

Field / ColumnSourceEditable?Condition
Sequencecash_receipt_split.split_sequenceNoAlways visible
Amountcash_receipt_split.split_amtNoAlways visible
AppliedSum of approved applications from cash_receipt_applicationNoAlways visible
Remainingsplit_amt - applied_amt computedNoAlways visible
Statuscash_receipt_split.split_status_cd resolved via code masterNoAlways visible
Notescash_receipt_split.notesNo (edit via action)Always visible
Worksheetcash_receipt_worksheet.cash_receipt_worksheet_status_cdNoLink opens worksheet in new tab
DocumentsFile count from file_upload entity linkNoExpandable button to reveal file list
EditOpens Edit Split dialog; disabled when worksheet status is not Draft
DeleteOpens Delete Split dialog; disabled on last split and on non-Draft worksheets

Grid features:

  • Sortable columns: none (displayed in split_sequence order)
  • Filters: none
  • Row selection: none
  • Pagination: none

Conditional display:

  • "Create Split" button enabled when posting_status_cd != 'V' and at least one split exists.
  • "Transfer Funds" button enabled when posting_status_cd != 'V' and at least two splits exist.
  • Edit and Delete icons per split row disabled when the split's worksheet status is Applied, Settled, Approved, or Returned.
  • Lock icon shown on a split row when the split's worksheet is locked by another user.
  • Voided receipt banner shown across the top when isVoided = true; all action buttons disabled.

8.4 Create Split Dialog

Route: Modal on the Split Management panel

Data loading:

  • Source split's split_amt and applied amount passed from the panel state — no additional query at dialog open.

Form Region

Field / ColumnSourceEditable?Condition
AmountUser-enteredYesMust be > 0 and <= source split's available balance
NotesUser-enteredYesOptional free text
Supporting DocumentFile uploadYesOptional file attachment linked to the new split via file_upload entity link
Source Split (display)cash_receipt_split.split_sequence and available balance from panelNoShown as context; not selectable in this dialog

Conditional display:

  • Available balance shown as context beneath the amount field.
  • Info message shown when all source-split funds will be consumed, warning that the source split will be auto-deleted.

8.5 Transfer Funds Dialog

Route: Modal on the Split Management panel

Data loading:

  • All splits for the receipt passed from the panel state — no additional query at dialog open.

Form Region

Field / ColumnSourceEditable?Condition
From SplitDropdown of all non-voided splits on the receiptYesRequired
To SplitDropdown of all non-voided splits excluding the "From" selectionYesRequired; must differ from "From"
AmountUser-enteredYesMust be > 0 and <= "From" split's available balance

Conditional display:

  • Transfer button disabled until all three fields are valid.
  • When the From split available balance would reach zero after transfer, a note is displayed that the source split may be auto-deleted if its worksheet is empty Draft.

8.6 Delete Split Dialog

Route: Modal on the Split Management panel

Data loading:

  • Split data passed from the panel state — no additional query at dialog open.

Form Region

Field / ColumnSourceEditable?Condition
Split to Delete (display)cash_receipt_split.split_sequence and split_amtNoAlways shown as context
Transfer Remaining Funds ToDropdown of other non-voided splits on the receiptYesRequired when split_amt > 0

Conditional display:

  • Transfer target dropdown shown only when the split has a non-zero split_amt.
  • Confirm button disabled until a transfer target is selected (when required).

9. Additional Diagrams

Receipt Posting Status Lifecycle

mermaid
stateDiagram-v2
    [*] --> U : Receipt created (manual or bank import)
    U --> P : GL posting batch runs
    U --> V : Adjustments reduce net_receipt_amt to zero
    P --> V : Adjustments reduce net_receipt_amt to zero

Split Status Lifecycle

mermaid
stateDiagram-v2
    [*] --> N : Split created (default or additional)
    N --> S : Agent submits split for review
    S --> A : Cash manager approves
    S --> R : Cash manager returns for revision
    R --> S : Agent resubmits after correction
    A --> F : Worksheet fully applied (split_amt = applied_amt)
    A --> P_APPLIED : Worksheet partially applied (balance remains)
    N --> V : Parent receipt voided (amount zeroed)
    A --> V : Parent receipt voided
    P_APPLIED --> V : Parent receipt voided

NOTE

F (Fully Applied) and P (Partially Applied) are terminal states set by the worksheet service when cash is applied. They do not transition further unless the receipt is voided. The split-level submit/approve/revise flow (N → S → A/R) is a reviewer workflow that can precede worksheet processing but is not enforced as a hard gate in the current implementation.

Receipt Creation Sequence

mermaid
sequenceDiagram
    actor User
    participant UI as Cash Receipts Page
    participant Action as Server Action
    participant ReceiptSvc as CashReceiptService
    participant SplitSvc as CashReceiptSplitService
    participant WsRepo as WorksheetRepository

    User->>UI: Click "Add Cash Receipt" and Save
    UI->>Action: createCashReceipt(data)
    Action->>ReceiptSvc: createCashReceipt(data, userId)
    ReceiptSvc->>ReceiptSvc: INSERT cash_receipt (posting_status_cd='U')
    ReceiptSvc->>SplitSvc: createDefaultSplit(cashReceiptId, netReceiptAmt, userId)
    SplitSvc->>SplitSvc: INSERT cash_receipt_split (split_status_cd='N', split_sequence=1)
    SplitSvc->>WsRepo: createWorksheet(splitId, status_cd='D', current_item_ind=true)
    WsRepo-->>SplitSvc: worksheet created
    SplitSvc-->>ReceiptSvc: split created
    ReceiptSvc-->>Action: success
    Action-->>UI: revalidatePath, return result
    UI-->>User: Receipt list refreshed

10. Cross-References

DocumentRelationship
Cash Receipts Data ModelDefines cash_receipt, cash_receipt_split, cash_receipt_reference, and cash_receipt_adjustment tables used throughout this workflow
Cash Receipts QueriesSpecifies all data retrieval operations referenced in Section 4.1
Cash Receipts ProceduresSpecifies all data mutation operations referenced in Section 4.2 and Section 5
Worksheets WorkflowDownstream: every cash receipt split feeds a worksheet where cash is applied to receivables; worksheet status drives split editability
Bank Ingestion WorkflowUpstream: bank statement file import creates cash receipts via the living-mirror sync pattern
Write-Offs WorkflowUpstream: write-off packet approval creates system-generated WRITE_OFF type receipts
Accounting Jobs WorkflowDownstream: GL posting batch reads unposted receipts via getUnpostedReceiptsUpToDate
Cash Matching WorkflowRelated: the Cash Matching screen provides the universal search used for quick reference addition on splits

11. Gherkin Scenarios

gherkin
Feature: Cash Receipts - Manual Receipt Creation

  Scenario: Cash manager creates a USD receipt and default split is auto-created
    Given no cash receipts exist for deposit date 2026-03-02
    And bank account "JPMorgan USD" with bank_account_id = 5 exists and is active
    When the cash manager opens the Add Cash Receipt dialog
    And enters deposit_date = '2026-03-02', bank_account_id = 5, cash_receipt_ref = 'CR-001'
    And enters original_receipt_amt = '50000.00', original_currency_cd = 'USD'
    And clicks Save
    Then a cash_receipt row is created with posting_status_cd = 'U', net_receipt_amt = '50000.00', receipt_amt = '50000.00', currency_cd = 'USD'
    And a cash_receipt_split row is created with split_amt = '50000.00', split_status_cd = 'N', split_sequence = 1
    And a cash_receipt_worksheet row is created with cash_receipt_worksheet_status_cd = 'D', current_item_ind = true
    And the new receipt appears in the cash receipts list

  Scenario: Cash manager creates a GBP receipt requiring FX conversion
    Given bank account "Barclays GBP" with bank_account_id = 8 exists with currency_cd = 'GBP'
    And the working currency for the UTA office is USD
    When the cash manager enters original_receipt_amt = '10000.00', original_currency_cd = 'GBP', currency_cd = 'USD', fx_rate = 1.27
    And clicks Save
    Then cash_receipt.receipt_amt = '12700.00'
    And cash_receipt.net_receipt_amt = '12700.00'
    And cash_receipt.original_receipt_amt = '10000.00'
    And cash_receipt.original_currency_cd = 'GBP'
    And cash_receipt_split.split_amt = '12700.00'

  Scenario: Creation fails when amount is zero
    When the cash manager enters original_receipt_amt = '0.00'
    And clicks Save
    Then the dialog displays an error "Receipt amount must be greater than zero"
    And no cash_receipt row is created

  Scenario: Creation fails when FX rate is missing for a cross-currency receipt
    When the cash manager enters original_currency_cd = 'GBP' and currency_cd = 'USD' but leaves fx_rate blank
    And clicks Save
    Then the dialog displays an error "FX rate is required for currency conversion"
    And no cash_receipt row is created
gherkin
Feature: Cash Receipts - Amount Adjustments

  Scenario: Cash manager records a bank fee adjustment reducing the receipt net amount
    Given cash_receipt with cash_receipt_id = 42 has posting_status_cd = 'U', receipt_amt = '50000.00', net_receipt_amt = '50000.00'
    And cash_receipt_split with cash_receipt_split_id = 101 has split_amt = '50000.00'
    And split 101 has a worksheet with cash_receipt_worksheet_status_cd = 'D' and no applications
    When the cash manager opens the edit dialog for receipt 42
    And adds an adjustment with adjustment_amt = '25.00', comment = 'Wire transfer fee', applied to split 101
    Then a cash_receipt_adjustment row is created with adjustment_amt = '25.00', adjustment_type_cd = 'ADJ', posting_status_cd = 'U'
    And cash_receipt_split.split_amt for split 101 = '49975.00'
    And cash_receipt.net_receipt_amt = '49975.00'

  Scenario: Adjustment is blocked when the split's worksheet is in Applied status
    Given cash_receipt_split with cash_receipt_split_id = 101 has a worksheet with cash_receipt_worksheet_status_cd = 'P'
    When the cash manager attempts to add an adjustment to split 101
    Then the system returns an error "Cannot adjust split while worksheet is in Applied status"
    And no cash_receipt_adjustment row is created

  Scenario: Adjustment reducing net amount to zero voids the receipt
    Given cash_receipt with cash_receipt_id = 55 has receipt_amt = '100.00', net_receipt_amt = '100.00'
    And cash_receipt_split with cash_receipt_split_id = 110 has split_amt = '100.00'
    And split 110 has a Draft worksheet with no applications
    When the cash manager adds an adjustment of '100.00' to split 110
    Then cash_receipt.posting_status_cd = 'V'
    And cash_receipt_split with cash_receipt_split_id = 110 has split_status_cd = 'V'
    And the Draft worksheet for split 110 is deleted

  Scenario: Adjustment amount cannot exceed split available balance
    Given cash_receipt_split with cash_receipt_split_id = 101 has split_amt = '100.00' with no applications
    When the cash manager attempts to add an adjustment of '150.00' to split 101
    Then the system returns an error "Adjustment ($150.00) exceeds split amount ($100.00)"
    And no cash_receipt_adjustment row is created

  Scenario: Posted adjustment cannot be deleted
    Given cash_receipt_adjustment with cash_receipt_adjustment_id = 99 has posting_status_cd = 'P'
    When the cash manager attempts to delete adjustment 99
    Then the system returns an error "Cannot delete posted adjustments"
    And the adjustment row remains unchanged
gherkin
Feature: Cash Receipts - Split Management

  Scenario: Cash manager carves a new split from the default split for a two-deal receipt
    Given cash_receipt with cash_receipt_id = 10 has net_receipt_amt = '100000.00'
    And cash_receipt_split with cash_receipt_split_id = 201 has split_amt = '100000.00', split_status_cd = 'N'
    And split 201 has a Draft worksheet with no applications
    When the cash manager opens Split Management and creates a new split with amount = '60000.00' from source split 201
    Then a new cash_receipt_split row is created with split_amt = '60000.00', split_status_cd = 'N', parent_split_id = 201
    And a new cash_receipt_worksheet row with cash_receipt_worksheet_status_cd = 'D' is created for the new split
    And cash_receipt_split with cash_receipt_split_id = 201 has split_amt = '40000.00'
    And SUM(split_amt) for all non-voided splits on receipt 10 = '100000.00'

  Scenario: Creating a split using all source funds auto-deletes the source split
    Given cash_receipt_split with cash_receipt_split_id = 201 has split_amt = '30000.00'
    And split 201 has a Draft worksheet with no applications
    When the cash manager creates a new split with amount = '30000.00' from source split 201
    Then the new split is created with split_amt = '30000.00'
    And cash_receipt_split with cash_receipt_split_id = 201 is deleted
    And the Draft worksheet for split 201 is deleted

  Scenario: Cannot create a split when source split has an Applied worksheet
    Given cash_receipt_split with cash_receipt_split_id = 202 has a worksheet with cash_receipt_worksheet_status_cd = 'P'
    When the cash manager attempts to create a split from split 202
    Then the system returns an error indicating the source split cannot be modified
    And no new cash_receipt_split row is created

  Scenario: Cannot delete the last remaining split on a receipt
    Given cash_receipt with cash_receipt_id = 20 has exactly one split with cash_receipt_split_id = 301
    When the cash manager attempts to delete split 301
    Then the Delete button for split 301 is disabled
    And no deletion occurs

  Scenario: Transfer funds moves amount from one split to another
    Given cash_receipt_split with cash_receipt_split_id = 301 has split_amt = '80000.00'
    And cash_receipt_split with cash_receipt_split_id = 302 has split_amt = '20000.00'
    And both splits belong to cash_receipt_id = 20 and both have Draft worksheets with no applications
    When the cash manager transfers '30000.00' from split 301 to split 302
    Then cash_receipt_split with cash_receipt_split_id = 301 has split_amt = '50000.00'
    And cash_receipt_split with cash_receipt_split_id = 302 has split_amt = '50000.00'
    And SUM(split_amt) for receipt 20 = '100000.00'

  Scenario: Cannot transfer between splits of different receipts
    Given cash_receipt_split with cash_receipt_split_id = 301 belongs to cash_receipt_id = 20
    And cash_receipt_split with cash_receipt_split_id = 401 belongs to cash_receipt_id = 21
    When the cash manager attempts to transfer from split 301 to split 401
    Then the system returns an error "Cannot transfer between splits of different receipts"
    And both split_amt values remain unchanged
gherkin
Feature: Cash Receipts - References and Tax Warnings

  Scenario: Adding a party reference triggers tax warning evaluation
    Given cash_receipt_split with cash_receipt_split_id = 501 has no references
    And party with party_id = 77 is a UK non-resident entertainer subject to FEU withholding
    When the cash manager adds a CLIENT_ID reference for party 77 to split 501
    Then a cash_receipt_reference row is created with cash_receipt_split_id = 501, type_cd = 'CLIENT_ID', ref_or_id = '77'
    And cash_receipt_split.tax_warning_ind = true for split 501
    And cash_receipt_split.tax_warning_json contains a warning for jurisdiction 'UK_FEU'
    And a tax warning badge is displayed on split 501 in the splits panel

  Scenario: Adding a deal reference does not trigger a tax warning
    Given cash_receipt_split with cash_receipt_split_id = 502 has no references
    When the cash manager adds a DEAL_ID reference for deal 200 to split 502
    Then a cash_receipt_reference row is created with type_cd = 'DEAL_ID', ref_or_id = '200'
    And cash_receipt_split.tax_warning_ind remains false for split 502

  Scenario: References are stored without FK validation
    Given no deal with deal_id = 9999 exists in the database
    When the cash manager adds a DEAL_ID reference with ref_or_id = '9999' to a split
    Then the cash_receipt_reference row is created with type_cd = 'DEAL_ID', ref_or_id = '9999'
    And no error is raised at the database level
gherkin
Feature: Cash Receipts - Voiding and Posting Status Rules

  Scenario: Voided receipt restricts all operations except ref and comment editing
    Given cash_receipt with cash_receipt_id = 60 has posting_status_cd = 'V'
    When the cash manager views receipt 60 in the receipts list
    Then the action menu (three-dot icon) is not displayed for the receipt row
    And inline click-to-edit pencil icons are shown on the Ref and Comment cells
    And opening the Split Management panel for receipt 60 shows a voided receipt banner
    And all split action buttons (Create Split, Transfer Funds, Edit, Delete) are disabled

  Scenario: Voided receipt rejects new adjustments
    Given cash_receipt with cash_receipt_id = 60 has posting_status_cd = 'V'
    When the system attempts to create an adjustment on receipt 60
    Then the system returns an error "Cannot add adjustments to voided receipts"
    And no cash_receipt_adjustment row is created

  Scenario: Posted receipt allows only comment and net amount adjustments
    Given cash_receipt with cash_receipt_id = 70 has posting_status_cd = 'P'
    When the cash manager opens the edit dialog for receipt 70
    Then deposit_date, bank_account_id, cash_receipt_ref, original_receipt_amt, and currency fields are read-only
    And only cash_receipt_comment is editable through the standard form
    And the Adjustments section is available for adding new adjustments to change net_receipt_amt

  Scenario: Bank-originated receipt with a non-Draft worksheet prevents full field edit
    Given cash_receipt with cash_receipt_id = 80 has posting_status_cd = 'U' and filename = 'CAMT_20260302.xml'
    And the default split for receipt 80 has a worksheet with cash_receipt_worksheet_status_cd = 'P'
    When the cash manager opens the edit dialog for receipt 80
    Then deposit_date, bank_account_id, cash_receipt_ref, original_receipt_amt, and currency fields are read-only
    And only cash_receipt_comment is editable through the standard form

Confidential. For internal use only.