---
title: Benefit schedule payment processing
summary: Stops a claim's outstanding time-loss and federal benefit payment schedules when claim data changes, either truncating a released schedule or deleting its unreleased payments, and posts an adjuster review task.
status: draft
owner: SAIF Doc Gen
last_reviewed: 2026-07-30
library: SAIF.Business.Claim
reference_type: package
operation_id: OP-BC-01
trigger: A claim-maintenance, claim-payment, overpayment, or claim-adjustment application calls ProcessBenefitPayment after changing claim data that invalidates the payment schedule
---

# Benefit schedule payment processing

When a claim change invalidates an in-flight benefit payment schedule — a date of injury, date of death, disability date, work status, weekly wage, support order, CDA, claim status, jurisdiction, claim decision, or a cancelled check — the calling application asks this operation to stop the schedule. The operation walks every schedule row on the claim that still has payments owed, decides per row whether the pending payment has already been released to the payment system, and either truncates the schedule to a single remaining payment or deletes the scheduled payment outright. It then records an adjuster task describing what changed and what remains to be reviewed.

Three near-identical business objects implement this behavior against the same `CL_BENEFIT_SCHEDULE` table and are documented together because they share one Criteria contract, one set of SQL statements, and one control flow: `clsBenefitSchedule` (time-loss and federal schedules, with task posting), `clsActiveBenefitSchedule` (the same flow extended for claim-adjustment cancel-check callers), and `clsFederalBenefitSchedule` (retrieve, update, and delete only, without the stop-payment routine).

| Field | Value |
| --- | --- |
| **Operation ID** | OP-BC-01 |
| **Trigger** | `clsBenefitSchedule.ProcessBenefitPayment(claimID, mailID, callingApplication, callingFunction, postTaskForReleased)` or `clsActiveBenefitSchedule.ProcessBenefitPayment(claimID, callingApplication, callingFunction)`; the CRUD path is entered through `GetBenefitSchedule` / `NewBenefitSchedule` followed by `Save()` |
| **Inputs** | `ClaimID`; `BenefitPaymentSeqNum`; the calling application and calling function enumerations; the adjuster mail ID for task assignment; a flag stating whether the caller posts its own task for released payments; `RemainingPaymentCount`, `NextIssueDate`, `ReleasedPaymentCount`, and `UpdateNum` for the CRUD path |
| **Outputs** | Boolean indicating that at least one schedule row was processed; truncated or deleted schedule and payment rows; a claim task for the adjuster; error messages `#PAYUPD#`, `#PAYDEL#`, `UpdateError`, `DeleteError` |
| **Primary components** | `clsBenefitSchedule.ProcessBenefitPayment`, `clsBenefitSchedule.RetrieveBenefitPayments`, `clsBenefitSchedule.ReturnTask`, `clsActiveBenefitSchedule.ProcessBenefitPayment`, `clsFederalBenefitSchedule` |
| **Entry point** | `Business\SAIF.Business.Claim\clsBenefitSchedule.vb` |

## Steps

1. **Record the caller context.** `ProcessBenefitPayment` stores the calling application (Overpayments, Claim Maintenance, Claim Payment, or — in `clsActiveBenefitSchedule` only — Claim Adjustments) and the calling function (date of death, date of injury, date of disability, support order, work status, weekly wage, CDA, claim status, jurisdiction, and in `clsActiveBenefitSchedule` also claim decision and cancel check). These two values drive only the wording of the task text produced in step 8.
2. **Prepare the task generator.** `clsBenefitSchedule` immediately constructs a claim task generator for the claim so a task can be added later; `clsActiveBenefitSchedule` skips this because it never posts a task.
3. **Read the claim's outstanding schedules.** `RetrieveBenefitPayments` opens its own portal request and runs the schedule query for the claim, restricted to rows whose remaining payment count is greater than zero, returning zero to many rows ([CL_BENEFIT_SCHEDULE](../database-tables.md#cl_benefit_schedule)). This filtered variant of the schedule select is not catalogued separately from the keyed retrieve ([SQL-017](../sql/SQL-017-saif-business-claim.md), [SQL-013](../sql/SQL-013-saif-business-claim.md)).*
   - If the result set is empty: the operation returns `False` without touching any data.
4. **Loop the schedule rows.** For each row returned, load the benefit payment sequence number, claim identifier, released payment count, remaining payment count, and update number into the object.
5. **Ask whether the pending payment was already released.** The claim service counts financial transactions for the claim and benefit payment sequence number whose transaction status is released.
   - Sub-step: build a scalar request against the financial transaction table filtered by claim identifier, benefit payment sub-number, and a financial transaction status code of `1`.
   - Sub-step: execute the request and return `True` when the count is greater than zero.

   > **Origin**: The released-payment check is implemented by `ClaimServices.hasReleasedScheduledPayment` in `SAIF.Business` and executed on behalf of this operation; see [Claim information and authorization support](../../saif-business/operations/claim-information-and-authorization-support.md).
6. **Released branch — truncate the schedule.** When a released payment exists, set the remaining payment count to `1`, capture the current portal user as the update user, and run the partial schedule update that writes only the remaining payment count, `SYSDATE`, an incremented update number, and the update user, keyed on claim, sequence number, and the prior update number ([BR-009](../business-rules.md#br-009-released-scheduled-payments-are-truncated-to-one-remaining-payment), [SQL-031](../sql/SQL-031-saif-business-claim.md), [CL_BENEFIT_SCHEDULE](../database-tables.md#cl_benefit_schedule)).
   - If the affected row count is `0`: add error `#PAYUPD#` — "The Payment Records for this Schedule were NOT succesfully updated." — and return `False` immediately, leaving any remaining schedule rows unprocessed ([BR-008](../business-rules.md#br-008-updatedelete-row-count-must-equal-1)).
   - Otherwise: record the stop status as *released*, meaning a payment will still be issued unless the adjuster deletes it.
7. **Unreleased branch — delete the scheduled payment.** When no released payment exists, run the payment delete keyed on claim identifier and benefit payment sequence number; removal of the payment cascades to the schedule ([BR-009](../business-rules.md#br-009-released-scheduled-payments-are-truncated-to-one-remaining-payment), [CL_BENEFIT_PAYMENT](../database-tables.md#cl_benefit_payment)). This delete uses the same statement shape catalogued for the award benefit payment object ([SQL-041](../sql/SQL-041-saif-business-claim.md)).*
   - If the affected row count is `0`: add error `#PAYDEL#` — "The Payment Records for this Schedule were NOT succesfully deleted." — and return `False` immediately ([BR-008](../business-rules.md#br-008-updatedelete-row-count-must-equal-1)).
   - Otherwise: record the stop status as *deleted*.
8. **Compose the task text.** `ReturnTask` builds a sentence starting with "TD Payment Schedule stopped - ", appends the phrase matching the calling application and function (for example "date of injury ", "support order ", or "weekly wage "), appends "updated. ", then appends either "This schedule has been deleted. " or "There is a released payment that will be issued unless you delete it. " depending on the stop status, and closes with "Please review. ".
   - In `clsActiveBenefitSchedule`, a claim-adjustment caller contributes "check cancelled " or "claim decision " and the word "updated. " is suppressed.
9. **Post the adjuster task.** Unless the caller declared that it posts the task itself *and* the stop status is released, add a task for the claim addressed to the supplied mail ID with the composed text, due today with a zero day offset, and save it ([BR-010](../business-rules.md#br-010-stopping-a-benefit-payment-schedule-posts-an-adjuster-review-task)).
   - Sub-step: the task generator rejects a claim identifier of zero with an application exception.
   - Sub-step: it creates a new claim task for the claim and acting user, resolving the responsible adjuster when no mail ID was supplied.
   - Sub-step: it shifts the due date forward by the supplied day offset, falling back to the previous working day when the offset lands on a non-working day.
   - Sub-step: saving the generator saves the underlying claim task collection.

   > **Origin**: Steps 9.1–9.4 are implemented by `clsClaimTaskGenerator.AddTask` and `clsClaimTaskGenerator.Save` in `SAIF.Business.Tasks.Claim` and executed on behalf of this operation. That library is documented in the previous format, so no per-operation page exists; see [Operations and processes](../../saif-business-tasks-claim/operations/claim-task-lifecycle.md) in the `SAIF.Business.Tasks.Claim` documentation set.
10. **Return the outcome.** After the loop, the function returns `True` when at least one schedule row was processed, otherwise `False`.
11. **CRUD path — retrieve a single schedule.** `GetBenefitSchedule` (or the federal equivalent) fetches one schedule row by benefit payment sequence number and claim identifier and fills the object; nothing is reported when no row matches ([SQL-013](../sql/SQL-013-saif-business-claim.md), [SQL-017](../sql/SQL-017-saif-business-claim.md), [SQL-022](../sql/SQL-022-saif-business-claim.md), [CL_BENEFIT_SCHEDULE](../database-tables.md#cl_benefit_schedule)).
12. **CRUD path — update a schedule.** `Save()` accepts changes and runs the full schedule update, writing the next issue date, released and remaining payment counts, `SYSDATE`, an incremented update number, and the update user, keyed on the prior update number ([SQL-029](../sql/SQL-029-saif-business-claim.md), [SQL-031](../sql/SQL-031-saif-business-claim.md), [SQL-036](../sql/SQL-036-saif-business-claim.md), [CL_BENEFIT_SCHEDULE](../database-tables.md#cl_benefit_schedule)).
    - If exactly one row is not affected: add `UpdateError` carrying the framework database contention message ([BR-008](../business-rules.md#br-008-updatedelete-row-count-must-equal-1)).
13. **CRUD path — delete a schedule.** The delete removes the schedule row by benefit payment sequence number and claim identifier ([SQL-040](../sql/SQL-040-saif-business-claim.md), [SQL-042](../sql/SQL-042-saif-business-claim.md), [SQL-046](../sql/SQL-046-saif-business-claim.md), [CL_BENEFIT_SCHEDULE](../database-tables.md#cl_benefit_schedule)).
    - If exactly one row is not affected: add `DeleteError` with the message "Delete Failed" ([BR-008](../business-rules.md#br-008-updatedelete-row-count-must-equal-1)).
    - Otherwise the object is marked new so it is treated as unsaved from that point on.
14. **Create and insert are refused.** All three objects raise an application exception from their create and insert SQL properties, so a benefit schedule can never be originated through this library.

## Process flow

The following diagram visualizes this operation's control flow for one claim.

```mermaid
flowchart TD
	Start([Caller stops the payment schedule<br>after a claim change]) --> Read[Read schedules for the claim<br>with remaining payments above zero]
	Read --> Any{Any rows?}
	Any -->|No| NoRows([Return False;<br>nothing changed])
	Any -->|Yes| Row[Load next schedule row]
	Row --> Rel{Released financial<br>transaction exists?}
	Rel -->|Yes| Trunc[Set remaining count to 1<br>and update the schedule]
	Rel -->|No| Del[Delete the scheduled<br>benefit payment]
	Trunc --> URows{Rows affected = 0?}
	Del --> DRows{Rows affected = 0?}
	URows -->|Yes| PayUpd([Add PAYUPD error;<br>return False])
	DRows -->|Yes| PayDel([Add PAYDEL error;<br>return False])
	URows -->|No| StatusR[Stop status = released]
	DRows -->|No| StatusD[Stop status = deleted]
	StatusR --> Task{Caller posts its own task<br>for released payments?}
	StatusD --> Compose[Compose task text from<br>calling application and function]
	Task -->|Yes| Next{More schedule rows?}
	Task -->|No| Compose
	Compose --> Add[Add and save adjuster task]
	Add --> Next
	Next -->|Yes| Row
	Next -->|No| Done([Return True])
```

## Failure and edge-case behavior

- A zero row count on either the truncate or the delete aborts the whole loop, so schedules later in the result set are left untouched and the claim can be left partially stopped.
- The stop-payment path validates nothing before writing: neither object registers a business rule, so the caller alone decides that the schedule should be stopped.
- `clsActiveBenefitSchedule` performs the same data changes as `clsBenefitSchedule` but posts no adjuster task at all, so a claim-adjustment caller must create its own follow-up.
- Task suppression applies only when the payment was released; a deleted schedule always produces a task regardless of the caller's preference.
- The `Save()` override on all three objects returns `True` unconditionally and discards the framework save result, so callers must inspect the error collection rather than the return value.*
- Retrieval returns an unfilled object rather than an error when no schedule matches the supplied keys, so callers must check the populated state themselves.
- The task text is assembled from a fixed phrase table, so a calling application or function outside the enumerated set contributes no descriptive fragment and the adjuster receives a generic sentence.
- `clsFederalBenefitSchedule` shares the schedule table and statement shapes but has no stop-payment routine, no released-payment check, and no task generation, so federal schedules stopped through that object leave no adjuster trail.

## 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\clsBenefitSchedule.vb`
- `Business\SAIF.Business.Claim\clsActiveBenefitSchedule.vb`
- `Business\SAIF.Business.Claim\clsFederalBenefitSchedule.vb`
- `Business\SAIF.Business\ClaimServices.vb`
- `Business\SAIF.Business.Tasks.Claim\clsClaimTaskGenerator.vb`
