---
title: Business function limit maintenance
summary: Retrieves and validates the per-employee, per-business-function dollar limits an employee may authorize, enforcing amount, expiration, duplicate, and authority-ceiling rules before persisting.
status: draft
owner: Technical Writer
last_reviewed: 2026-07-30
library: SAIF.Business.Claim.Authority
reference_type: package
operation_id: OP-003
trigger: Caller retrieves clsClaimEmpBusFuncLimitCollection via clsClaimAuthority.Create, edits or adds rows, and calls Save()
---

# Business function limit maintenance

A business function limit is a per-employee, per-business-function (adjuster, awards, CDA settlement, DCS settlement, federal settlement, penalty, TD payment, vocational), per-approval-type maximum dollar amount the employee is permitted to authorize. The collection is loaded as part of [Claim authority initialization](claim-authority-initialization.md), scoped to either the reserves or payments business process, and edited/persisted as part of [Claim authority save](claim-authority-save.md).

| Field | Value |
| --- | --- |
| **Operation ID** | OP-003 |
| **Trigger** | `clsClaimEmpBusFuncLimitCollection.GetReserveLimits` / `GetPaymentLimits` (retrieve); `Add(emplid, busProcessCode)` (new row); collection or aggregate `Save()` (persist) |
| **Inputs** | `EmployeeEmplid`, `ClaimBusProcessCode`, `ClaimBusFunctionCode`, `ClaimAuthPurposeCode`, `MaxAmount`, `ExpDate`, `AuthorizedByEmplid` |
| **Outputs** | Populated `clsClaimEmpBusFuncLimitCollection`; persisted insert/update/delete of `CL_CLAIM_EMP_BUS_FUNC_LIMIT` rows; broken-rule errors on validation failure |
| **Primary components** | `clsClaimEmpBusFuncLimitCollection.GetReserveLimits`, `GetPaymentLimits`, `clsClaimEmpBusFuncLimit` (CRUD lifecycle and business rules) |
| **Entry point** | `Business\SAIF.Business.Claim.Authority\clsClaimEmpBusFuncLimitCollection.vb`, `Business\SAIF.Business.Claim.Authority\clsClaimEmpBusFuncLimit.vb` |

## Steps

1. **Retrieve the collection.** `GetReserveLimits(dpi, emplid)` builds a `Criteria` fixed to the reserve business-process code and retrieves; `GetPaymentLimits(dpi, emplid)` does the same for the payments code. Both execute the same parameterized `RetrieveSQL` — filtered by `EmployeeEmplid` and `BusinessProcessCode` — and materialize one `clsClaimEmpBusFuncLimit` per row ([SQL-015](../sql/SQL-015-saif-business-claim-authority.md), [CL_CLAIM_EMP_BUS_FUNC_LIMIT](../database-tables.md#cl_claim_emp_bus_func_limit)).
2. **Add a new limit row.** `Add(emplid, busProcessCode)` calls `clsClaimEmpBusFuncLimit.NewClaimEmpBusFuncLimit`, which allocates a sequence value via `CL_CLM_EMP_BUS_FUN_LIM_SEQ.NEXTVAL` ([SQL-001](../sql/SQL-001-saif-business-claim-authority.md)) and defaults the new row: the acting employee (from data-portal `UserID`) becomes `AuthorizedByEmplid`, `MaxAmount` is `0`, and the business function/process/purpose codes default to Adjuster/Reserve/All for reserves or Awards/Payments/InitiateAndRelease for payments.
3. **Set the maximum amount.** Editing `MaxAmount` marks the row dirty and, on the next `IsValid` check, runs `ValidAmountMin` — the amount must be greater than zero ([BR-003](../business-rules.md#br-003-maximum-limit-must-be-greater-than-zero)).
   - On failure: error "Maximum limit must be greater than zero."
4. **Set the expiration date.** Editing `ExpDate` runs `ValidExpDate` — an empty expiration date is allowed, but a populated one may not be in the past ([BR-004](../business-rules.md#br-004-expiration-date-may-not-be-in-the-past)).
   - On failure: error "Expiration date may not be in the past."
5. **Check the grantable amount against the acting employee's own ceiling.** `ValidAuthorizeAmount` runs whenever the row is dirty and `IsSecurityOverride` is not set ([BR-005](../business-rules.md#br-005-cannot-grant-amount-exceeding-own-authority)):
   - If `ClaimBusProcessCode` is the reserve code: delegate to the parent `clsClaimAuthority.CanAuthorizeReserves(busFunctionCode, authPurposeCode, maxAmount)`.
   - Otherwise: delegate to `clsClaimAuthority.CanAuthorizePayment(busFunctionCode, authPurposeCode, maxAmount)`.
   - See [Authorization amount and approval-type checks](authorization-amount-and-approval-checks.md) for the inline scalar-query logic behind both calls.
   - On failure: error "You are not authorized to grant this amount."
6. **Reject duplicate function/approval-type combinations.** `DuplicateFunctionCode` runs whenever `ClaimBusFunctionCode` changes and the row is not deleted; it scans sibling (non-deleted, non-self) rows in the same collection for a matching `ClaimBusFunctionCode` + `ClaimAuthPurposeCode` pair ([BR-006](../business-rules.md#br-006-no-duplicate-functionapproval-type-combinations)). This check is purely in-memory and issues no SQL.
   - On failure: error "May not have multiple rows with the same Function and Approval Type."
7. **Check the approval type against the acting employee's own ceiling.** `ValidAuthorizeApprovalType` runs whenever `ClaimAuthPurposeCode` changes and `IsSecurityOverride` is not set, delegating to `clsClaimAuthority.CanAuthorizeApprovalType(busProcessCode, busFunctionCode, authPurposeCode)` ([BR-007](../business-rules.md#br-007-cannot-grant-approval-type-beyond-own-authority)). See [Authorization amount and approval-type checks](authorization-amount-and-approval-checks.md).
   - On failure: error "You are not authorized to grant this Approval Type."
8. **Persist on save.** [Claim authority save](claim-authority-save.md) step 5 first stamps `AuthorizedByEmplid` on every dirty row, then cascades `Save()`:
   - New row: insert binds all fields including the sequence-allocated key and default expiration date ([SQL-004](../sql/SQL-004-saif-business-claim-authority.md), [CL_CLAIM_EMP_BUS_FUNC_LIMIT](../database-tables.md#cl_claim_emp_bus_func_limit)).
     - On a rows-affected value other than `1`: error "Insert Failed".
   - Changed row: update binds the same fields plus the key and `UpdateNum` ([SQL-019](../sql/SQL-019-saif-business-claim-authority.md), [CL_CLAIM_EMP_BUS_FUNC_LIMIT](../database-tables.md#cl_claim_emp_bus_func_limit)).
     - On a rows-affected value other than `1`: DB contention error.
   - Removed row: delete binds the sequence key and `UpdateNum` ([SQL-022](../sql/SQL-022-saif-business-claim-authority.md), [CL_CLAIM_EMP_BUS_FUNC_LIMIT](../database-tables.md#cl_claim_emp_bus_func_limit)).
     - On a rows-affected value other than `1`: DB contention error.

## Process flow

The following diagram visualizes retrieval, in-memory editing, and save for a business function limit row.

```mermaid
flowchart TD
	Start([Load or add a limit row]) --> Retrieve[Retrieve reserve or payment<br>limits for employee]
	Retrieve --> Edit[Caller edits MaxAmount,<br>ExpDate, function/purpose codes]
	Edit --> Rules{Rules pass?}
	Rules -->|Amount <= 0| ErrAmt([Amount error])
	Rules -->|Expired date| ErrExp([Expiration error])
	Rules -->|Amount exceeds own ceiling| ErrAuth([Own-ceiling error])
	Rules -->|Duplicate function/purpose| ErrDup([Duplicate error])
	Rules -->|Approval type exceeds own ceiling| ErrAppr([Approval-type error])
	Rules -->|All pass| Save[Save cascades from<br>Claim authority save]
	Save --> Rows{RowsAffected = 1?}
	Rows -->|Yes| Done([Row persisted])
	Rows -->|No| Contention([Insert/DB contention error added])
```

## Failure and edge-case behavior

- `IsSecurityOverride` bypasses both the amount ceiling ([BR-005](../business-rules.md#br-005-cannot-grant-amount-exceeding-own-authority)) and the approval-type ceiling ([BR-007](../business-rules.md#br-007-cannot-grant-approval-type-beyond-own-authority)) checks, but is forced to `False` in production, so the bypass only takes effect in non-production environments.
- The duplicate-function-code check ([BR-006](../business-rules.md#br-006-no-duplicate-functionapproval-type-combinations)) only inspects rows currently in the same in-memory collection; it cannot detect duplicates against rows outside the loaded scope (for example, if only reserve limits were loaded, a payments-side duplicate would not be caught).*
- `IsValid` on this object returns `True` whenever the row is not dirty, so an already-persisted row with stale data that has since become invalid (for example, an expiration date that has since passed) is not re-validated unless it is edited again.

## 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.Authority\clsClaimEmpBusFuncLimit.vb`
- `Business\SAIF.Business.Claim.Authority\clsClaimEmpBusFuncLimitCollection.vb`
