---
title: Authorization amount and approval-type checks
summary: Runs inline scalar Oracle queries to determine the maximum dollar amount, or whether any row exists at all, that an authorizing employee may grant for a given business function or reserve category and approval purpose.
status: draft
owner: Technical Writer
last_reviewed: 2026-07-30
library: SAIF.Business.Claim.Authority
reference_type: package
operation_id: OP-005
trigger: Invoked internally by the business function and category change limit validation rules (not called directly by external consumers in this library)
---

# Authorization amount and approval-type checks

These five methods on `clsClaimAuthority` are the actual authority-ceiling checks that back [BR-005](../business-rules.md#br-005-cannot-grant-amount-exceeding-own-authority), [BR-007](../business-rules.md#br-007-cannot-grant-approval-type-beyond-own-authority), [BR-010](../business-rules.md#br-010-cannot-grant-amount-exceeding-own-category-authority), and [BR-011](../business-rules.md#br-011-cannot-grant-approval-type-beyond-own-category-authority). Each issues a single inline scalar query against the authorizing employee's own limit rows and compares the result to the amount or approval type the row under validation is trying to grant. All five share the same shape: build a scalar request, bind the authorizing employee and lookup codes, execute, and fall back to a safe default (`0`) if the result cannot be cast.

| Field | Value |
| --- | --- |
| **Operation ID** | OP-005 |
| **Trigger** | Called from `clsClaimEmpBusFuncLimit.ValidAuthorizeAmount`, `ValidAuthorizeApprovalType`, and `clsClaimEmpCatChangeLimit.ValidAuthorizeAmount`, `ValidAuthorizeCategoryApprovalType` |
| **Inputs** | Business function code, cost category code, authority purpose code, and the amount being requested (for the amount checks) |
| **Outputs** | Boolean — whether the authorizing employee's own maximum amount covers the requested amount, or whether at least one matching limit row exists for the requested approval type |
| **Primary components** | `clsClaimAuthority.CanAuthorizeReserves`, `CanAuthorizePayment`, `CanAuthorizeCategory`, `CanAuthorizeApprovalType`, `CanAuthorizeCategoryApprovalType`, `clsClaimAuthority.CanAuthorize` (shared private helper) |
| **Entry point** | `Business\SAIF.Business.Claim.Authority\clsClaimAuthority.vb` |

## Steps

1. **Business function amount checks (reserves and payments).** `CanAuthorizeReserves(busFunctionCode, authPurposeCode, amount)` and `CanAuthorizePayment(busFunctionCode, authPurposeCode, amount)` both delegate to the private `CanAuthorize(businessProcess, busFunctionCode, authPurposeCode, amount)` helper:
   - Build a scalar request bound to `Emplid` (the authorizing employee), `inBusProcess`, `inBusFunction`, and `inAuthPurpose`.
   - Execute `CanAuthorizeSQL` for payments or `ReservesCanAuthorizeSQL` for reserves — both select `MAX(max_amount)` from [CL_CLAIM_EMP_BUS_FUNC_LIMIT](../database-tables.md#cl_claim_emp_bus_func_limit) for the authorizing employee, matching business process and function exactly, and matching authority purpose either exactly (payments) or with `>=` (reserves — a higher purpose code covers lower ones), filtered to rows whose expiration date is empty or in the future.
   - Cast the scalar result to `Decimal`; on an `InvalidCastException` (for example, no matching row, so the result is `DBNull`), treat the maximum as `0`.
   - Return `amount <= maxAuthorizedAmount`.
2. **Category amount check.** `CanAuthorizeCategory(categoryCode, authPurposeCode, amount)` builds a scalar request bound to `Emplid`, `CategoryCode`, and `inAuthPurpose`, and executes `CanAuthorizeCategorySQL` (exact purpose match) or `ReservesCanAuthorizeCategorySQL` (`>=` purpose match, selected when `inAuthPurposeCode` equals the reserves business-process constant) against [CL_CLAIM_EMP_CAT_CHANGE_LIMIT](../database-tables.md#cl_claim_emp_cat_change_limit). The cast-and-compare logic is identical to step 1.
   - Note: the reserves/payments branch for this method tests `inAuthPurposeCode = BUSINESS_PROCESS_RESERVES` rather than a business-process parameter — because authority purpose codes and business process codes share the same underlying code space (`"1"`/`"2"`), this reproduces the intended reserves-vs-payments split, but only correctly for the specific purpose-code values in use today.*
3. **Business function approval-type checks (reserves and payments).** `CanAuthorizeApprovalType(businessProcess, busFunctionCode, authPurposeCode)` builds a scalar `COUNT(*)` request bound to the same four parameters and executes `CanAuthorizePurposeSQL` or `ReservesCanAuthorizePurposeSQL` against [CL_CLAIM_EMP_BUS_FUNC_LIMIT](../database-tables.md#cl_claim_emp_bus_func_limit), using the same exact-vs-`>=` purpose comparison as step 1.
   - Cast to `Decimal`; on failure, treat the row count as `0`.
   - Return `rowCount > 0` — the check only cares whether any matching row exists, not what its amount is.
4. **Category approval-type check.** `CanAuthorizeCategoryApprovalType(categoryCode, authPurposeCode)` builds a scalar `COUNT(*)` request bound to `Emplid`, `inCategoryCode`, and `inAuthPurpose`, and executes `CanAuthorizeCategoryPurposeSQL` or `ReservesCanAuthorizeCategoryPurposeSQL` against [CL_CLAIM_EMP_CAT_CHANGE_LIMIT](../database-tables.md#cl_claim_emp_cat_change_limit) using the same branch logic as step 2.
5. **Return to the calling validation rule.** Each method's boolean result feeds directly into the caller's rule function (see [Business function limit maintenance](business-function-limit-maintenance.md) and [Category change limit maintenance](category-change-limit-maintenance.md)); none of these five methods add error messages themselves.

## Process flow

The following diagram visualizes the shared shape of the five checks.

```mermaid
flowchart TD
	Start([Limit-row rule invokes a<br>CanAuthorize* method]) --> Which{Amount check or<br>approval-type check?}
	Which -->|Amount| BuildScalar[Build scalar request:<br>MAX amount for authorizing employee]
	Which -->|Approval type| BuildCount[Build scalar request:<br>COUNT of matching rows]
	BuildScalar --> Category{Category or<br>business function?}
	BuildCount --> Category
	Category -->|Business function| BizSQL[Select CanAuthorizeSQL /<br>ReservesCanAuthorizeSQL variant]
	Category -->|Category| CatSQL[Select CanAuthorizeCategorySQL /<br>ReservesCanAuthorizeCategorySQL variant]
	BizSQL --> Execute[Execute against employee's<br>own limit rows]
	CatSQL --> Execute
	Execute --> Cast{Result castable?}
	Cast -->|No| Zero[Treat result as 0]
	Cast -->|Yes| Value[Use cast value]
	Zero --> Compare{Amount check?}
	Value --> Compare
	Compare -->|Yes| AmtCheck([Return amount <= max])
	Compare -->|No| CountCheck([Return rowCount > 0])
```

## Failure and edge-case behavior

- An `InvalidCastException` (typically a `DBNull` scalar result when no matching row exists) is treated as "no authority" (`0`), not as an error — the caller sees a validation failure rather than an exception.
- The `>=` purpose-code comparison used for reserves assumes higher authority-purpose codes are strictly more permissive than lower ones; this ordering is defined by the `AuthorityPurposes` enum values in `mdlClaimAuthority.vb` and is not re-validated here.*
- These checks always query the **authorizing** employee's own rows, not the subject employee's — the amount or approval type being granted to the subject is checked against what the person doing the granting is themselves allowed to authorize.
- None of these five methods are documented with their own cataloged SQL IDs in this library's SQL catalog; the inline query text is reproduced above from the `Criteria` class properties (`CanAuthorizeSQL`, `CanAuthorizePurposeSQL`, `CanAuthorizeCategorySQL`, `CanAuthorizeCategoryPurposeSQL`, and their `Reserves*` counterparts) rather than linked to a `sql/SQL-*.md` document.*

## 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`
