---
title: Category change limit maintenance
summary: Retrieves and validates the per-employee reserve-category 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-004
trigger: Caller retrieves clsClaimEmpCatChangeLimitCollection via clsClaimAuthority.Create, edits or adds rows, and calls Save()
---

# Category change limit maintenance

A category change limit is a per-employee maximum dollar amount the employee may authorize when changing a claim's reserve cost category. Unlike business function limits, category change limits are not split by business process — the collection is loaded once per employee, regardless of reserves or payments scope, as part of [Claim authority initialization](claim-authority-initialization.md) and persisted as part of [Claim authority save](claim-authority-save.md).

| Field | Value |
| --- | --- |
| **Operation ID** | OP-004 |
| **Trigger** | `clsClaimEmpCatChangeLimitCollection.GetClaimEmpCatChangeLimits` (retrieve); `Add(emplid)` (new row); collection or aggregate `Save()` (persist) |
| **Inputs** | `EmployeeEmplid`, `ClaimCostCategoryCode`, `ClaimAuthPurposeCode`, `MaxChangeAmount`, `ExpDate`, `AuthorizedByEmplid` |
| **Outputs** | Populated `clsClaimEmpCatChangeLimitCollection`; persisted insert/update/delete of `CL_CLAIM_EMP_CAT_CHANGE_LIMIT` rows; broken-rule errors on validation failure |
| **Primary components** | `clsClaimEmpCatChangeLimitCollection.GetClaimEmpCatChangeLimits`, `clsClaimEmpCatChangeLimit` (CRUD lifecycle and business rules) |
| **Entry point** | `Business\SAIF.Business.Claim.Authority\clsClaimEmpCatChangeLimitCollection.vb`, `Business\SAIF.Business.Claim.Authority\clsClaimEmpCatChangeLimit.vb` |

## Steps

1. **Retrieve the collection.** `GetClaimEmpCatChangeLimits(dpi, emplid)` builds a `Criteria` and retrieves every category-change-limit row for the employee, filtered only by `EmployeeEmplid` ([SQL-017](../sql/SQL-017-saif-business-claim-authority.md), [CL_CLAIM_EMP_CAT_CHANGE_LIMIT](../database-tables.md#cl_claim_emp_cat_change_limit)).
   - A single-object retrieve variant of the same filter also exists on `clsClaimEmpCatChangeLimit` itself ([SQL-016](../sql/SQL-016-saif-business-claim-authority.md), [CL_CLAIM_EMP_CAT_CHANGE_LIMIT](../database-tables.md#cl_claim_emp_cat_change_limit)), but no caller of it was found within this library; the collection retrieve is the path actually exercised from `clsClaimAuthority.Create`.*
2. **Add a new limit row.** `Add(emplid)` calls `clsClaimEmpCatChangeLimit.NewClaimEmpCatChangeLimit`, which allocates a sequence value via `CL_CLM_EMP_CAT_CHG_LIM_SEQ.NEXTVAL` ([SQL-002](../sql/SQL-002-saif-business-claim-authority.md)) and defaults the new row's acting employee and zero amount.*
3. **Set the maximum change amount.** Editing `MaxChangeAmount` marks the row dirty and runs `ValidAmountMin` — the amount must be greater than zero ([BR-008](../business-rules.md#br-008-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-009](../business-rules.md#br-009-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 category ceiling.** `ValidAuthorizeAmount` runs whenever the row is dirty and `IsSecurityOverride` is not set, delegating to `clsClaimAuthority.CanAuthorizeCategory(categoryCode, authPurposeCode, maxChangeAmount)` ([BR-010](../business-rules.md#br-010-cannot-grant-amount-exceeding-own-category-authority)). See [Authorization amount and approval-type checks](authorization-amount-and-approval-checks.md).
   - On failure: error "You are not authorized to grant this amount."
6. **Reject duplicate category/approval-type combinations.** `DuplicateCategoryCode` runs whenever `ClaimCostCategoryCode` changes and the row is not deleted; it scans sibling (non-deleted, non-self) rows in the same collection for a matching `ClaimCostCategoryCode` + `ClaimAuthPurposeCode` pair ([BR-013](../business-rules.md#br-013-no-duplicate-categoryapproval-type-combinations)). This check is purely in-memory and issues no SQL.
   - On failure: error "May not have multiple rows with the same Category and Approval Type."
7. **Check the approval type against the acting employee's own category ceiling.** `ValidAuthorizeCategoryApprovalType` runs whenever `ClaimAuthPurposeCode` changes and `IsSecurityOverride` is not set, delegating to `clsClaimAuthority.CanAuthorizeCategoryApprovalType(categoryCode, authPurposeCode)` ([BR-011](../business-rules.md#br-011-cannot-grant-approval-type-beyond-own-category-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 6 first stamps `AuthorizedByEmplid` on every dirty row, then cascades `Save()`:
   - New row: insert binds all fields including the sequence-allocated key ([SQL-005](../sql/SQL-005-saif-business-claim-authority.md), [CL_CLAIM_EMP_CAT_CHANGE_LIMIT](../database-tables.md#cl_claim_emp_cat_change_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-020](../sql/SQL-020-saif-business-claim-authority.md), [CL_CLAIM_EMP_CAT_CHANGE_LIMIT](../database-tables.md#cl_claim_emp_cat_change_limit)).
     - On a rows-affected value other than `1`: DB contention error.
   - Removed row: delete binds the sequence key and `UpdateNum` ([SQL-023](../sql/SQL-023-saif-business-claim-authority.md), [CL_CLAIM_EMP_CAT_CHANGE_LIMIT](../database-tables.md#cl_claim_emp_cat_change_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 category change limit row.

```mermaid
flowchart TD
	Start([Load or add a category limit row]) --> Retrieve[Retrieve category change<br>limits for employee]
	Retrieve --> Edit[Caller edits MaxChangeAmount,<br>ExpDate, category/purpose codes]
	Edit --> Rules{Rules pass?}
	Rules -->|Amount <= 0| ErrAmt([Amount error])
	Rules -->|Expired date| ErrExp([Expiration error])
	Rules -->|Amount exceeds own category ceiling| ErrAuth([Own-ceiling error])
	Rules -->|Duplicate category/purpose| ErrDup([Duplicate error])
	Rules -->|Approval type exceeds own category 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-010](../business-rules.md#br-010-cannot-grant-amount-exceeding-own-category-authority)) and the approval-type ceiling ([BR-011](../business-rules.md#br-011-cannot-grant-approval-type-beyond-own-category-authority)) checks, but is forced to `False` in production.
- The duplicate-category-code check ([BR-013](../business-rules.md#br-013-no-duplicate-categoryapproval-type-combinations)) shares the same `RuleData` identifier as the business-function-limit duplicate check (`clsClaimEmpBusFuncLimitColl01`) even though it is defined on a different class; this appears to be a copy-paste artifact in the source rather than an intentional shared rule.*
- The single-object retrieve on `clsClaimEmpCatChangeLimit` ([SQL-016](../sql/SQL-016-saif-business-claim-authority.md)) has no known caller in this library; it may be dead code or reserved for a consumer outside this codebase.**

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