---
title: Support order management
summary: Creates, updates, and deletes child-support withholding orders for a worker, manages their per-claim connections, and derives downstream to-do tasks.
status: draft
owner: SAIF Doc Gen
last_reviewed: 2026-07-30
library: SAIF.Business.Claim.Maintenance
reference_type: package
operation_id: OP-CM-04
trigger: Caller calls NewClaimSupportOrder / GetClaimSupportOrderCollection, edits the order and its claim connections, and calls Save()
---

# Support order management

Support order management owns child-support withholding orders held against a worker and the set of claims each order applies to. A new order automatically pre-selects every eligible claim for the worker, and the object then enforces date, amount, flag, and selection rules before persisting through the `PK82141_SUPPORT_ORDER` package. Deleting an order is blocked whenever awards or payments already reference it, and a separate to-do flow derives follow-up tasks for claims whose payment schedules are affected.

| Field | Value |
| --- | --- |
| **Operation ID** | OP-CM-04 |
| **Trigger** | Caller invokes `clsClaimSupportOrder.NewClaimSupportOrder` / `clsClaimSupportOrderCollection.GetClaimSupportOrderCollection`, edits the order and its claim selections, and calls `Save()` |
| **Inputs** | `WorkerID` (Decimal); generated `SupportOrderID`; order fields `AllClaimFlag`, `ArrearageFlag`, `DelinquentMonthlyAmount`, `EffectiveDate`, `MaxReductionPercent`, `MonthlyAmount`, `ReceiptDate`, `SedAccountNum`, `EnforcingAgencyName`, `TerminationDate`; selected `ClaimID` values through `SupportOrderConnections`; acting user from the data-portal info |
| **Outputs** | Persisted support-order row and per-claim connection rows; populated order and collection objects; a `TodoTasks` array of claim/task pairs for the downstream to-do queue; broken rules and error messages on validation or concurrency failure |
| **Primary components** | `clsClaimSupportOrder` (create, insert, update, delete, `isDeletable`, `DetermineTodoTasks`, `CreateToDoTasks`, `DetermineAllClaims`, rule methods `ValidSelectedClaims`…`PaymentIssueWarning`), `clsClaimSupportOrderCollection` (`FilterExpired`, `TodoTasks`, `ClaimsForWorker`), `clsClaimSupportOrderConn`, `clsClaimSupportOrderConnCollection` |
| **Entry point** | `Business\SAIF.Business.Claim.Maintenance\clsClaimSupportOrder.vb` |

## Steps

1. **Create a new order.** `NewClaimSupportOrder(dataPortal, workerID)` builds a criteria holding the worker identifier and calls `DataAccessLayer.CreateObject`.
2. **Reserve the identifier.** `BeforeCreate` issues a scalar read of the support-order sequence ([SQL-001](../sql/SQL-001.md), [DUAL](../database-tables.md#dual)) and `AfterCreate` stores the value as the new `SupportOrderID`.
3. **Default the new order.** `AfterCreate` seeds the all-claim flag to `Y`, the arrearage flag to `N`, both amounts and the maximum reduction percent to zero, the effective and receipt dates to now, a blank SED account number, a single-space enforcing agency name, a termination date of `Date.MaxValue`, update number zero, and the acting user in upper case.
4. **Pre-select eligible claims (`CreateConnections`).** An inline read returns every claim for the worker whose status is neither `I` nor `V` and whose jurisdiction is state ([SQL-054](../sql/SQL-054.md), [CL_INJURY_CLAIM](../database-tables.md#cl_injury_claim)) ([BR-CM-008](../business-rules.md#br-cm-008-claims-with-status-i-in-progress-or-v-voided-are-excluded-from-support-order-claim)).
   - For each returned claim identifier, an in-memory connection object is added to `SupportOrderConnections`, so a brand-new order starts with all eligible claims selected.
5. **Caller edits the order.** Property setters mark the object dirty; the caller also selects or de-selects claim connections. No database access occurs until `Save()`.
6. **Short-circuit clean saves.** `Save()` routes to `SaveSupportOrder()`, which returns success immediately when the object is not dirty.
7. **Derive the reduction cap.** For a non-deleted order whose monthly or delinquent amount changed, `SetMaxReductionPercent()` sets the maximum reduction percent to 25% when a monthly amount is present, otherwise 15% when only a delinquent amount is present ([BR-CM-006](../business-rules.md#br-cm-006-award-reduction-validation-before-support-order-modification)).*
8. **Run the validation rule set.** The registered rules fire before persistence; any error-severity failure blocks the save and surfaces through the error messages.
   - `ValidSelectedClaims`: for every claim of the worker that is *not* currently connected, check whether an award references the order for that claim ([SQL-049](../sql/SQL-049.md), [CL_BENEFIT_SCHEDULE](../database-tables.md#cl_benefit_schedule)) or a payment does ([SQL-058](../sql/SQL-058.md), [CL_BENEFIT_PAYMENT](../database-tables.md#cl_benefit_payment)); a positive count produces a per-claim "cannot be de-selected" error ([BR-CM-006](../business-rules.md#br-cm-006-award-reduction-validation-before-support-order-modification)).
   - `ValidSelectedClaims` also fails when no claim at all is connected — an order can never be saved with zero connections.
   - `ValidReceiptDate`: required and may not be in the future.
   - `ValidEffecitveDate`: required and may not be later than seven days from today.
   - `ValidTerminationDate`: when set, may not be in the future.
   - `ValidTerminationEffDate`: when set, may not precede the effective date.
   - `ValidMonthlyAmt` and `ValidDelinquentAmt`: neither amount may be negative.
   - `ValidArrearageFlag`: must be `Y` or `N`. `ValidSedAccountNum`: must be non-blank.
   - `PaymentIssueWarning`: a warning-severity rule that calls the payment-about-to-be-issued check for the worker ([SQL-057](../sql/SQL-057.md), [CL_BENEFIT_PAYMENT](../database-tables.md#cl_benefit_payment)) and warns without blocking when a released payment is pending ([BR-CM-004](../business-rules.md#br-cm-004-support-order-validates-payment-about-to-be-issued-status-before-changes)).
9. **Insert a new order.** `BeforeInsert` calls the package insert procedure with every order field, the acting user, and a rows-affected return parameter ([SQL-008](../sql/SQL-008.md), `CL_CLAIM_SUPPORT_ORDER`).
   - An empty enforcing agency name is coerced to a single space before binding, working around the not-null column.*
   - `AfterInsert`: if rows affected is not exactly one, add an insert error carrying the DB contention message ([BR-CM-001](../business-rules.md#br-cm-001-optimistic-concurrency-updates-fail-if-rowsaffected-1)); otherwise clear the error and mark the object old.
10. **Update an existing order.**
    - `BeforeUpdate` first calls `DetermineAllClaims()`, which walks the worker's state-jurisdiction claims and sets the all-claim flag false when any of them is missing from the connection collection.
    - It then calls the package update procedure with the order fields, the update number as the concurrency token, the acting user, and a rows-affected return parameter ([SQL-092](../sql/SQL-092.md), `CL_CLAIM_SUPPORT_ORDER`).
    - `AfterUpdate`: rows affected other than one produces an update error with the DB contention message ([BR-CM-001](../business-rules.md#br-cm-001-optimistic-concurrency-updates-fail-if-rowsaffected-1)); otherwise the error is cleared and the object is marked old.
11. **Cascade the claim connections.** After the insert or update, `SaveChildObject(SupportOrderConnections)` saves the connection collection.
    - Each newly selected connection inserts a row through an inline statement ([SQL-009](../sql/SQL-009.md), [CL_CLAIM_SUPPORT_ORDER_CONN](../database-tables.md#cl_claim_support_order_conn)); a result other than one adds an insert error.
    - Each de-selected connection deletes its row through an inline statement ([SQL-111](../sql/SQL-111.md), [CL_CLAIM_SUPPORT_ORDER_CONN](../database-tables.md#cl_claim_support_order_conn)); a result other than one adds a delete error.
    - `Restore(ClaimID)` on the connection collection moves an entry back from the deleted list into the live list, re-marking it old then dirty, so a claim can be re-selected before the save.
12. **Check deletability before deleting.** `isDeletable` runs two order-wide guards and blocks the delete without executing any delete statement:
    - An award exists for the order ([SQL-051](../sql/SQL-051.md), [CL_BENEFIT_SCHEDULE](../database-tables.md#cl_benefit_schedule)) ([BR-CM-002](../business-rules.md#br-cm-002-support-order-cannot-be-deleted-if-awards-exist-for-the-suo-claim)).
    - A payment exists for the order ([SQL-056](../sql/SQL-056.md), [CL_BENEFIT_PAYMENT](../database-tables.md#cl_benefit_payment)) ([BR-CM-003](../business-rules.md#br-cm-003-support-order-cannot-be-deleted-if-payments-exist-for-the-suo-claim)).
13. **Delete the order.** When deletable, marking the object deleted and calling `Save()` routes to the delete path: `BeforeDelete` calls the package delete procedure with the order, worker, and acting user plus a rows-affected return parameter ([SQL-110](../sql/SQL-110.md), `CL_CLAIM_SUPPORT_ORDER`), and `AfterDelete` raises a delete error when rows affected is not one ([BR-CM-001](../business-rules.md#br-cm-001-optimistic-concurrency-updates-fail-if-rowsaffected-1)).
14. **Support award reduction checks.** `AwardReductionExists(AwardNum)` calls the package award-reduction check for the order and award ([SQL-050](../sql/SQL-050.md), [CL_BENEFIT_SCHEDULE](../database-tables.md#cl_benefit_schedule)) and is consumed by award-side callers ([BR-CM-006](../business-rules.md#br-cm-006-award-reduction-validation-before-support-order-modification)).*
15. **Check for a benefit payee.** `BenifitPayeeReferencesOrder()` calls the package benefit-payee check for the order ([SQL-052](../sql/SQL-052.md), [CL_BENEFIT_PAYMENT](../database-tables.md#cl_benefit_payment)) ([BR-CM-005](../business-rules.md#br-cm-005-benefit-payee-must-exist-for-support-order-before-payment-processing)); it is both a collaborator-facing helper and the gate for the to-do flow.
16. **Derive to-do tasks (`DetermineTodoTasks`).** The `TodoTasks` property clears the task list and runs the derivation only when the order is new, dirty, or has a benefit payee referencing it ([BR-CM-005](../business-rules.md#br-cm-005-benefit-payee-must-exist-for-support-order-before-payment-processing)).
    - Retrieve the affected payment-schedule claims for the worker ([SQL-055](../sql/SQL-055.md), [CL_BENEFIT_SCHEDULE](../database-tables.md#cl_benefit_schedule)), reading claim identifier, benefit-payment sequence number, and a nullable next issue date that becomes an empty smart date when null.
    - For each row, `CreateToDoTasks` calls the package to-do determination procedure with the claim, benefit-payment sub-number, next issue date, and acting user, returning a task identifier as an output parameter ([SQL-002](../sql/SQL-002.md), [CL_BENEFIT_SCHEDULE](../database-tables.md#cl_benefit_schedule)); a non-blank task identifier is appended as a claim/task pair.
    - `CheckReleasedPayments(claimID)` re-runs the payment-exists check for the order ([SQL-056](../sql/SQL-056.md), [CL_BENEFIT_PAYMENT](../database-tables.md#cl_benefit_payment)) and, on a positive count, appends a fixed released-payment follow-up task.
17. **Aggregate tasks across orders.** `clsClaimSupportOrderCollection.TodoTasks` merges the task lists of every order in the collection into a deduplicated array.
18. **Retrieve orders for a worker.** `GetClaimSupportOrderCollection(dataPortal, workerID)` calls the package retrieve for the worker and returns a cursor ([SQL-059](../sql/SQL-059.md), `CL_CLAIM_SUPPORT_ORDER`); `AfterRetrieve` loads each order, sorts by receipt, effective, and termination dates descending then SED account ascending, and selects the first entry.
19. **Retrieve the connections for an order.** `SupportOrderConnections` lazily calls the package connection retrieve for the order and returns a cursor ([SQL-060](../sql/SQL-060.md), [CL_CLAIM_SUPPORT_ORDER_CONN](../database-tables.md#cl_claim_support_order_conn)); each row is loaded, given its own criteria, and marked old.
20. **Resolve the worker's eligible claims.** `ClaimsForWorker` on the collection retrieves the worker's claim history and filters it to active statuses — the collection-level analog of the create-time eligibility filter ([BR-CM-008](../business-rules.md#br-cm-008-claims-with-status-i-in-progress-or-v-voided-are-excluded-from-support-order-claim)).
    - Sub-step: the claim-history retrieve and the active-status filter are performed by the claim-data collection, which returns only claims the support order may attach to.

    > **Origin**: `clsClaimDataCollection.GetWorkerClaimHist` and `FilterActiveClaimStatus` are implemented in `SAIF.Business.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-claim/operations-processes.md) in the `SAIF.Business.Claim` documentation set.
21. **Filter expired orders.** `FilterExpired()` builds a filtered view containing only orders whose termination date is still `Date.MaxValue`, preserving the current selection; `ClearFilter()` restores the full list.

## Process flow

The following diagram visualizes this operation's control flow.

```mermaid
flowchart TD
	Start([NewClaimSupportOrder workerID]) --> Seq[BeforeCreate reads<br>support order sequence]
	Seq --> Defaults[AfterCreate defaults fields]
	Defaults --> Conns[CreateConnections selects<br>claims not in status I or V]
	Conns --> Edit[Caller edits order<br>and claim selections]
	Edit --> Save[Save calls SaveSupportOrder]
	Save --> Dirty{IsDirty?}
	Dirty -->|No| NoOp([Return success; no DB access])
	Dirty -->|Yes| Deleted{IsDeleted?}
	Deleted -->|Yes| Deletable{Award or payment<br>references the order?}
	Deletable -->|Yes| Blocked([Delete blocked;<br>error attached, no SQL run])
	Deletable -->|No| Del[Call DeleteSupportOrder]
	Deleted -->|No| Cap[SetMaxReductionPercent<br>when amounts changed]
	Cap --> Rules[Run rules: selected claims,<br>dates, amounts, flags;<br>payment issue warns only]
	Rules --> Ok{Any error-severity<br>rule broken?}
	Ok -->|Yes| Abort([Save aborted;<br>errors returned])
	Ok -->|No| New{IsNew?}
	New -->|Yes| Ins[Call InsertSupportOrder]
	New -->|No| All[DetermineAllClaims<br>then UpdateSupportOrder]
	Ins --> Rows{RowsAffected = 1?}
	All --> Rows
	Del --> Rows
	Rows -->|No| Contention([DB contention error;<br>object stays dirty])
	Rows -->|Yes| Children[SaveChildObject on<br>connection collection]
	Children --> Done([MarkOld; save succeeded])
```

## Failure and edge-case behavior

- Any rows-affected value other than one from the insert, update, or delete procedure produces a blocking error and leaves the object dirty, so the caller can retry or show a stale-data message ([BR-CM-001](../business-rules.md#br-cm-001-optimistic-concurrency-updates-fail-if-rowsaffected-1)).
- Connection insert and delete check the plain scalar result rather than a named return parameter, an implementation inconsistency with the parent object.*
- Delete is blocked before any statement runs when awards ([BR-CM-002](../business-rules.md#br-cm-002-support-order-cannot-be-deleted-if-awards-exist-for-the-suo-claim)) or payments ([BR-CM-003](../business-rules.md#br-cm-003-support-order-cannot-be-deleted-if-payments-exist-for-the-suo-claim)) reference the order; the errors are attached to the object rather than thrown.
- De-selection is blocked per claim when that specific claim has an award or payment tied to the order, while whole-order delete uses the order-wide equivalents — two parallel but distinct check pairs.
- The payment-issue check is warning severity, so a save can proceed even when a released payment is about to be issued ([BR-CM-004](../business-rules.md#br-cm-004-support-order-validates-payment-about-to-be-issued-status-before-changes)).
- An empty enforcing agency name is silently converted to a single space before insert and update, avoiding a not-null violation; no rule protects the business meaning of a missing agency name.*
- An order can never be saved with zero claim connections.
- The termination-date setter coerces `Date.MinValue` to `Date.MaxValue`, so "no termination" is always stored as the maximum date; the order counts as rescinded only once a real modified termination date is set.
- The single-order retrieve factory is inconsistent with its criteria class, whose retrieve statement property throws, so that path appears to be unreachable in practice and all real retrieval flows through the collection.*
- The `PK82141_SUPPORT_ORDER` package body could not be located in the Oracle source during catalog retrieval, so the behavior of its entry points is derived from the call sites and parameter shapes rather than verified procedure bodies.**
- `DetermineAllClaims` and `ValidSelectedClaims` both cast the parent to the order collection, so a detached order would fail these checks.*

## 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. Statements marked with `**` could not be confirmed; treat
> as unknown until verified.

## Sources

- `Business\SAIF.Business.Claim.Maintenance\clsClaimSupportOrder.vb`
- `Business\SAIF.Business.Claim.Maintenance\clsClaimSupportOrderCollection.vb`
- `Business\SAIF.Business.Claim.Maintenance\clsClaimSupportOrderConn.vb`
- `Business\SAIF.Business.Claim.Maintenance\clsClaimSupportOrderConnCollection.vb`
