---
title: Transfer adjustment processing
summary: Moves previously posted payment amounts from one claim, or one context, to another by creating a linked pair of offsetting financial transactions.
status: draft
owner: SAIF Doc Gen
last_reviewed: 2026-07-30
library: SAIF.Business.Claim.Payment
reference_type: embedded
operation_id: OP-CP-06
trigger: An adjuster selects a transfer type, loads the source claim's posted payments, marks the payments to transfer, and calls Save()
---

# Transfer adjustment processing

A transfer moves money already paid — claim-to-claim, in full, or for another documented reason — by writing a linked pair of offsetting financial transactions rather than altering the original payment. `clsTransferAdjustment` is a shared base (transfer-reason metadata, remark text generation) extended by three concrete transfer classes selected at construction ([BR-CP-022](../business-rules.md#br-cp-022-refund-and-transfer-adjustments-are-mutually-exclusive-by-concrete-type)).

| Field | Value |
| --- | --- |
| **Operation ID** | OP-CP-06 |
| **Trigger** | Caller constructs `clsClaimToClaimTransfer`, `clsFullTransfer`, or `clsOtherTransfer`, sets `FromClaim`/`ToClaim` and `TransferInfo`, calls `LoadPayments`, marks candidate payments `SelectForTransfer`, and calls `Save()` |
| **Inputs** | `IDataPortalInfo`, source and destination `clsClaimData`, transfer reason (claim change, policy change, injury-date change), issue-date filter, selected payment set |
| **Outputs** | A paired "from" (negative) and "to" (positive) `CL_FINANCIAL_TRANS` row per transferred payment, linked by `TransferTransID`, each with mirrored detail lines; boolean save result |
| **Primary components** | `clsTransferAdjustment`, `clsClaimToClaimTransfer`, `clsFullTransfer`, `clsOtherTransfer` |
| **Entry point** | `Business\SAIF.Business.Claim.Payment\Adjustments\Transfers\clsTransferAdjustment.vb` |

## Steps

1. **Select the concrete transfer type** ([BR-CP-022](../business-rules.md#br-cp-022-refund-and-transfer-adjustments-are-mutually-exclusive-by-concrete-type)). The caller instantiates `clsClaimToClaimTransfer` (moves payments between two claims), `clsFullTransfer`, or `clsOtherTransfer`, and records `TransferInfo.TransferReason` (`ClaimChange`, `PolicyChange`, or `InjuryDateChange`).
2. **Load candidate payments.** `LoadPayments(issueFromDate)` reads the source claim's posted transactions (cached per claim/issue-date pair in `Static` locals on the base class) and groups their detail lines by transaction and payment category into read-only `clsClaimPayment` candidates.
3. **Mark payments for transfer.** The caller sets `SelectForTransfer = True` on each candidate the adjuster chooses to move; unmarked payments are left untouched on the source claim.
4. **Validate the request.** For `clsClaimToClaimTransfer`, full validation (including the base remark/amount rules) runs only when the transfer reason is `ClaimChange`; other reasons bypass `MyBase.IsValid` entirely and are always considered valid at this level.
5. **Build the paired transactions.** For each selected payment, `Save()` creates a "from" transaction (on the source claim, amount negated) and a "to" transaction (on the destination claim, amount positive), each pointing at the other's sequence number via `TransferTransID`; both are stamped Released status, today's entry date, the configured issue date, and `IgnoreBusinessRules = True`.
   - The "from" transaction's remark is a generated string naming the destination claim; the "to" transaction's remark is reason-specific text from `GetToTransRemarkText` (claim number, injury date, or policy number changed-from text depending on the reason), or blank for unrecognized reasons.
6. **Mirror detail lines with sign flips.** For every original detail line, a new detail is added to both the "from" and "to" transactions, copying category/reimbursement/cost/penalty/MCO-fee/EAIP flags unchanged, but negating `TransactionAmt`, `TDDayQty`, and `TDOffsetAmt` on the "from" side and keeping them positive on the "to" side.
7. **Save both transactions per payment.** Each generated transaction is saved individually through [Financial transaction and remark management](financial-transaction-and-remark-management.md) (`clsFinancialTrans.Save()`); the loop stops and returns `False` at the first failed save, leaving any already-saved transactions committed.

## Process flow

```mermaid
flowchart TD
	Start([Adjuster loads source claim's<br>posted payments]) --> Select[Mark payments SelectForTransfer]
	Select --> Which{Transfer reason<br>= ClaimChange?}
	Which -->|Yes| Validate{Remark/amount<br>rules pass?}
	Which -->|No| Build
	Validate -->|No| Blocked([Broken rule; save blocked])
	Validate -->|Yes| Build[For each selected payment:<br>build From and To transactions]
	Build --> Mirror[Mirror detail lines,<br>negate amounts on From side]
	Mirror --> SaveFrom[Save From transaction]
	SaveFrom --> FromOk{Saved?}
	FromOk -->|No| Fail([Save returns False;<br>remaining payments not processed])
	FromOk -->|Yes| SaveTo[Save To transaction]
	SaveTo --> ToOk{Saved?}
	ToOk -->|No| Fail
	ToOk -->|Yes| More{More selected<br>payments?}
	More -->|Yes| Build
	More -->|No| Done([Transfer complete])
```

## Failure and edge-case behavior

- `Save()` iterates payments and, within each payment, both transaction halves, but does not roll back transactions from earlier payments in the same call if a later one fails — a multi-payment transfer can leave a partially-completed transfer split across claims.
- For `clsClaimToClaimTransfer`, any transfer reason other than `ClaimChange` skips the base validation rules entirely (`IsValid` returns `True` unconditionally), so amount and remark checks only apply to claim-change transfers.
- The "from"/"to" pairing depends on both `clsFinancialTrans.NewFinancialTrans` calls succeeding in obtaining sequence numbers before either is saved; a sequence exhaustion or portal failure at that point would leave `TransferTransID` referencing a transaction that was never persisted.*
- `LoadPayments`'s claim/issue-date cache is process-wide (`Static`), not per-instance, matching the same cross-cutting caching pattern seen in refund processing.

## Related documentation

- [Operations and processes](../operations-processes.md)
- [Business rules](../business-rules.md)
- [SQL catalog](../sql/index.md)
- [Database tables](../database-tables.md)

> **Note:** Statements marked with `*` were inferred from code structure, naming
> conventions, or contextual evidence where direct confirmation was not available
> in source artifacts.

## Sources

- `Business\SAIF.Business.Claim.Payment\Adjustments\clsAdjustmentBase.vb`
- `Business\SAIF.Business.Claim.Payment\Adjustments\Transfers\clsTransferAdjustment.vb`
- `Business\SAIF.Business.Claim.Payment\Adjustments\Transfers\clsClaimToClaimTransfer.vb`
- `Business\SAIF.Business.Claim.Payment\Adjustments\Transfers\clsFullTransfer.vb`
- `Business\SAIF.Business.Claim.Payment\Adjustments\Transfers\clsOtherTransfer.vb`
