---
title: Payment posting and totals management
summary: Records posting of released payments against financial transactions and maintains running claim payment totals per cost category.
status: draft
owner: SAIF Doc Gen
last_reviewed: 2026-07-30
library: SAIF.Business.Claim.Payment
reference_type: embedded
operation_id: OP-CP-02
trigger: A payment cycle (select, print, post) creates posting rows; any process that must roll a claim's cost totals forward for an effective date calls the total manager
---

# Payment posting and totals management

Payment posting records the transition of a released financial transaction through select/print/post, and the total manager maintains a running, append-only ledger of paid amounts and timeloss-day quantities per claim cost category. Both classes read from, but never mutate, the financial transaction rows documented in [Financial transaction and remark management](financial-transaction-and-remark-management.md).

| Field | Value |
| --- | --- |
| **Operation ID** | OP-CP-02 |
| **Trigger** | `clsPaymentPosting.NewPaymentPosting(dpi, paymentTransStatSeqNum, typeCode)`; `clsPaymentPostingCollection.GetPaymentPostingCollection(...)`; `clsPaymentTotalManager.New(dpi, effectiveDate)` followed by `AddTransaction` |
| **Inputs** | Payment transaction status sequence number, payment transaction number type code, payment transaction type, financial transaction status; for totals — effective date, claim ID, cost category, amount, optional timeloss day quantity |
| **Outputs** | Rows in `CL_PAYMENT_POSTING`; new rows in `CL_PAYMENT_TOTAL`; posting/total collections for downstream check-printing and reporting |
| **Primary components** | `clsPaymentPosting`, `clsPaymentPostingCollection`, `clsPaymentTotalManager` |
| **Entry point** | `Business\SAIF.Business.Claim.Payment\FinancialTransaction\clsPaymentPosting.vb` |

## Steps

1. **Create a posting record.** `NewPaymentPosting` seeds `PaymentTransStatSeqNum` and `PaymentTransNumTypeCode` from the criteria; the caller then sets `ClaimFinancialTransSeqNum`, `ClaimID`, `FinancialTransTypeCode`, `PaymentID`, and `TransactionAmount`. `SAIFAwardNum`, `BenefitPaymentSeqNum`, `PayeeTypeCode`, `SAIFClaimNum`, `PayeeTin`, and `FederalBenefitFlag` are read-only, populated only by the retrieval join query.
2. **Insert the posting** ([SQL-023](../sql/SQL-023.md), [CL_PAYMENT_POSTING](../database-tables.md#cl_payment_posting)) ([BR-CP-009](../business-rules.md#br-cp-009-payment-postings-are-insert-only)).
   - On a rows-affected value other than 1: `"Insert Failed"` error added. Note the object is **not** marked old on success, unlike the remark object in Financial transaction management.
3. **Postings are insert-only** ([BR-CP-009](../business-rules.md#br-cp-009-payment-postings-are-insert-only)). `Criteria.CreateSQL/DeleteSQL/RetrieveSQL/UpdateSQL` for a single posting all throw `ApplicationException(InvalidSQLProperty)`; postings can only be retrieved as a collection.
4. **Retrieve postings by status.** `clsPaymentPostingCollection.GetPaymentPostingCollection` filters by `FinancialTransactionStatusCode` ([SQL-076](../sql/SQL-076.md), [SQL-077](../sql/SQL-077.md), [CL_PAYMENT_POSTING](../database-tables.md#cl_payment_posting)); an unrecognized status code silently falls back to Released rather than raising an error.
5. **Instantiate the total manager for an effective date.** `clsPaymentTotalManager.New(dpi, effectiveDate)` prepares a per-claim, per-category ledger anchored to that date.
6. **Read the claim's current totals** ([BR-CP-010](../business-rules.md#br-cp-010-claim-payment-totals-are-append-only-and-latest-sequence-wins)). `GetCurrentPaidCostsForClaim` selects the highest-sequence row per cost category ([SQL-078](../sql/SQL-078.md), [CL_PAYMENT_TOTAL](../database-tables.md#cl_payment_total)); a category with no prior row starts from a zero baseline.
7. **Record a transaction against a category.** `AddTransaction` accumulates a paid amount (and, for timeloss categories, a day quantity) onto the in-memory `CostCategoryRecord` for that category.
8. **Save modified categories only** ([BR-CP-010](../business-rules.md#br-cp-010-claim-payment-totals-are-append-only-and-latest-sequence-wins)). `Save()` inserts a new row only for categories whose paid amount or day quantity actually changed ([SQL-024](../sql/SQL-024.md), [CL_PAYMENT_TOTAL](../database-tables.md#cl_payment_total)); unmodified categories are skipped entirely, and no existing row is ever updated.
   - On a rows-affected value other than 1 for an inserted category: `DBContentionError`-style failure recorded, consistent with [BR-CP-001](../business-rules.md#br-cp-001-optimistic-concurrency-on-all-stored-procedure-based-operations).

## Process flow

```mermaid
flowchart TD
	Start([Payment cycle or claim<br>total recalculation]) --> Which{Posting or totals?}
	Which -->|Posting| NewPost[Create posting record]
	NewPost --> InsPost[Insert CL_PAYMENT_POSTING]
	InsPost --> RowsP{RowsAffected = 1?}
	RowsP -->|No| FailP([Insert Failed])
	RowsP -->|Yes| DonePost([Posting recorded])
	Which -->|Totals| ReadTotals[Read current totals<br>by highest sequence per category]
	ReadTotals --> AddTx[AddTransaction per<br>cost category]
	AddTx --> Modified{Category amount<br>or days changed?}
	Modified -->|No| Skip([Category skipped;<br>no new row])
	Modified -->|Yes| InsTotal[Insert new CL_PAYMENT_TOTAL row]
	InsTotal --> RowsT{RowsAffected = 1?}
	RowsT -->|No| FailT([Contention error recorded])
	RowsT -->|Yes| DoneTotal([New total row persisted])
```

## Failure and edge-case behavior

- An unrecognized `FinancialTransactionStatusCode` on retrieval silently defaults to Released rather than raising an error or returning an empty set.
- `clsPaymentPosting.Equals(Object)` calls an instance-typed `Equals` overload that is referenced but never defined in the file, so equality falls back to the inherited framework implementation rather than a field comparison — likely unintentional.
- Because totals are append-only, a caller who reads totals for an effective date in the past will not see later corrections unless a new row with a higher sequence has since been written for that category.
- No cross-check exists between posting amounts and total-manager amounts in this file set; consistency between `CL_PAYMENT_POSTING` and `CL_PAYMENT_TOTAL` depends entirely on callers invoking both correctly.

## 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\FinancialTransaction\clsPaymentPosting.vb`
- `Business\SAIF.Business.Claim.Payment\FinancialTransaction\clsPaymentPostingCollection.vb`
- `Business\SAIF.Business.Claim.Payment\FinancialTransaction\clsPaymentTotalManager.vb`
