---
title: Claim authority save
summary: Validates and persists an employee's grant authority together with any dirty business function and category change limit rows, stamping the authorizing employee on every changed row.
status: draft
owner: Technical Writer
last_reviewed: 2026-07-30
library: SAIF.Business.Claim.Authority
reference_type: package
operation_id: OP-002
trigger: Caller calls clsClaimAuthority.Save() (directly or via SaveChild) after populating or editing the aggregate
---

# Claim authority save

Claim authority save persists whichever parts of the authority aggregate the caller changed: the employee's own grant authority level, the business function limit rows, and the category change limit rows. Before persisting, every dirty limit row is stamped with the acting (authorizing) employee's ID, and the object's aggregate `IsValid` — which rolls up the grant authority and both limit collections — governs whether callers should invoke `Save()` at all, mirroring the caller-checks-`IsValid`-first pattern used across the BOF business layer.

| Field | Value |
| --- | --- |
| **Operation ID** | OP-002 |
| **Trigger** | `clsClaimAuthority.Save()` (also invoked as `SaveChild()` when this object is saved as another object's child) |
| **Inputs** | Dirty state of `GrantAuthority`, `BusinessFunctionLimits`, `CategoryChangeLimits`; `AuthorizingEmployee.ID` from initialization; `IsSecurityOverride` flag |
| **Outputs** | Boolean success (`ErrorCount = 0`); persisted `CL_CLAIM_EMP_AUTH_TYPE` row; persisted business function and category change limit rows |
| **Primary components** | `clsClaimAuthority.Save`, `clsClaimAuthority.SaveMe`, `clsClaimAuthority.IsValid`, `clsClaimAuthority.IsSecurityOverride` |
| **Entry point** | `Business\SAIF.Business.Claim.Authority\clsClaimAuthority.vb` |

## Steps

1. **Check whether anything changed.** `SaveMe()` returns `True` immediately if `IsDirty` is false — `IsDirty` is true when the base object, the grant authority, the business function limits, or the category change limits report dirty.
2. **Evaluate aggregate validity (caller responsibility).** `IsValid` rolls up `MyBase.IsValid` (which runs [BR-001](../business-rules.md#br-001-mail-id-must-be-valid) — the subject employee record must be valid — and [BR-002](../business-rules.md#br-002-cannot-grant-authority-level-higher-than-own) — the requested grant authority level must not exceed the acting employee's own level) together with `GrantAuthority.IsValid`, `BusinessFunctionLimits.IsValid`, and `CategoryChangeLimits.IsValid`. `Save()` itself does not call `IsValid`; callers are expected to check it first.*
   - `IsSecurityOverride` can suppress the authority-level ceiling in [BR-002](../business-rules.md#br-002-cannot-grant-authority-level-higher-than-own) and the amount/approval-type checks used by the child limit rules (see [Authorization amount and approval-type checks](authorization-amount-and-approval-checks.md)). The property setter itself enforces a rule: setting it to `True` while `AppGlobal.EnvironmentService.IsProduction` is true is silently forced back to `False` instead of taking effect ([BR-012](../business-rules.md#br-012-security-override-disabled-in-production)).
3. **Stamp the authorizing employee on dirty limit rows.** If `BusinessFunctionLimits.IsDirty`, every dirty item in the collection has `AuthorizedByEmplid` set to the acting employee's ID; the same stamping happens for every dirty item in `CategoryChangeLimits`. This runs unconditionally before any child save, even if the grant authority itself is unchanged.
4. **Save the grant authority, if dirty.** `SaveChildObject(GrantAuthority)` dispatches to `clsClaimEmpAuthType`'s CRUD lifecycle:
   - New row: `BeforeInsert` binds `ClaimAuthTypeCode`, `ClaimBusProcessCode`, `EmployeeEmplid`, and the update user, then executes the insert ([SQL-003](../sql/SQL-003-saif-business-claim-authority.md), [CL_CLAIM_EMP_AUTH_TYPE](../database-tables.md#cl_claim_emp_auth_type)).
     - On a rows-affected value other than `1`: add an `InsertError` with message "Insert Failed".
   - Existing row: `BeforeUpdate` binds the same fields plus `UpdateNum` and executes the update ([SQL-018](../sql/SQL-018-saif-business-claim-authority.md), [CL_CLAIM_EMP_AUTH_TYPE](../database-tables.md#cl_claim_emp_auth_type)).
     - On a rows-affected value other than `1`: add an `UpdateError` with the DB contention message.
   - Deleted row (structurally supported but not exercised by any caller found in this library*): `BeforeDelete` binds the key and update number and executes the delete ([SQL-021](../sql/SQL-021-saif-business-claim-authority.md), [CL_CLAIM_EMP_AUTH_TYPE](../database-tables.md#cl_claim_emp_auth_type)).
     - On a rows-affected value other than `1`: add a `DeleteError` with the DB contention message.
5. **Save the business function limits, if dirty.** `SaveChildObject(BusinessFunctionLimits)` cascades through the collection's own `Save()` (which calls `ApplyEdit()` first) and each dirty item's insert/update/delete lifecycle. See [Business function limit maintenance](business-function-limit-maintenance.md) for the full per-row detail and rule citations.
6. **Save the category change limits, if dirty.** `SaveChildObject(CategoryChangeLimits)` cascades the same way. See [Category change limit maintenance](category-change-limit-maintenance.md) for the full per-row detail and rule citations.
7. **Return the outcome.** `SaveMe()` returns `ErrorCount = 0` as the overall success indicator; both `Save()` and `SaveChild()` return this same result.

## Process flow

The following diagram visualizes the save cascade.

```mermaid
flowchart TD
	Start([Caller calls Save]) --> Dirty{IsDirty?}
	Dirty -->|No| NoOp([Return True; nothing to do])
	Dirty -->|Yes| Stamp[Stamp AuthorizedByEmplid<br>on dirty limit rows]
	Stamp --> GrantDirty{GrantAuthority dirty?}
	GrantDirty -->|Yes| SaveGrant[Insert / update / delete<br>CL_CLAIM_EMP_AUTH_TYPE]
	GrantDirty -->|No| BizDirty
	SaveGrant --> BizDirty{BusinessFunctionLimits dirty?}
	BizDirty -->|Yes| SaveBiz[Cascade save to<br>business function limit rows]
	BizDirty -->|No| CatDirty
	SaveBiz --> CatDirty{CategoryChangeLimits dirty?}
	CatDirty -->|Yes| SaveCat[Cascade save to<br>category change limit rows]
	CatDirty -->|No| Done
	SaveCat --> Done([Return ErrorCount = 0])
```

## Failure and edge-case behavior

- `Save()` never calls `IsValid` itself, so an invalid aggregate (for example, a grant authority that exceeds the acting employee's own level) can still reach the database if the caller skips the `IsValid` check.*
- Optimistic concurrency failures on any child (grant authority, business function limit, or category change limit) surface as an added error message rather than a thrown exception; `SaveMe()` still returns based on the aggregate `ErrorCount`.
- Production environments force `IsSecurityOverride` to `False` regardless of what the caller requests, so override behavior can only be exercised in non-production environments.
- Because `AuthorizedByEmplid` is stamped from the in-memory `AuthorizingEmployee` resolved during initialization, a save performed long after initialization (in a long-lived object) reflects the identity captured at load time, not necessarily the current caller.*

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