---
title: User access and external-user reporting
summary: Classifies users, derives PMS group keys, gates resource checks, and reports external-user activity by customer scope.
status: draft
owner: SAIF
last_reviewed: 2026-07-30
library: SAIF.Business
reference_type: package
operation_id: OP-SB-12
trigger: Caller evaluates the current user or requests external-user reporting.
---

# User access and external-user reporting

This operation combines current-user classification helpers with the reporting queries used for external customers. The library distinguishes internal and external user types from the current principal, derives PMS group keys when needed, and exposes customer-scoped last-logon and user-list queries.

| Field | Value |
| --- | --- |
| **Operation ID** | OP-SB-12 |
| **Trigger** | Caller invokes user-type, resource-access, or external-user-reporting helpers. |
| **Inputs** | Security principal, resource name, customer or customer-group ID, external-user type code |
| **Outputs** | User type, group IDs, booleans, last-logon rows, user collections, or summary message |
| **Primary components** | `clsUserType.Initialize`, `clsUserType.GetGroupKeyFromPMSId`, `ObjectServices.IsAuthorized`, `ExternalUserServices.GetLastLogonsByCustomer`, `ExternalUserServices.GetUsersByCustomer` |
| **Entry point** | `Business\SAIF.Business\clsUserType.vb` |

## Steps

1. `clsUserType.Initialize` evaluates the current security principal in priority order and assigns the first matching category such as SAIF employee, agent, policyholder, group, MCO, medical provider, bookkeeper, loss control, auditor, or unknown.
2. Group-user accessors defer PMS group-key derivation until `GroupID` or `GroupChapterID` is requested.
3. `SetGroupKey` parses chapter markers such as `%`, bracketed values, and the special `[^E]` case from the user number before deciding whether the raw key already contains a PMS number.
4. When the key is a PMS-style numeric group, `GetGroupKeyFromPMSId` calls `cp_get_group_key_4_pms_info` and stores the returned group key and chapter identifier for later access checks ([SQL-034](../sql/SQL-034-cp-get-group-key-4-pms-info.md)).
5. `ObjectServices.IsAuthorized` and related wrappers expose resource-authorization checks against the current principal without adding local SQL.
6. External-user reporting expands the incoming user-type code when needed, builds the customer-group or customer-specific query, and joins `EXT_USER` to `EXT_USER_TYPE` to return last-logon rows or current-user rows ([SQL-036](../sql/SQL-036-external-user-last-logon-user-lookup-family.md), [EXT_USER](../database-tables.md#ext-user-ext-user-type), [EXT_USER_TYPE](../database-tables.md#ext-user-ext-user-type)).
7. Production-mode reporting excludes test users from the external-user result sets before the results are returned ([BR-SB-007](../business-rules.md#br-sb-007-production-external-user-queries-hide-test-users), [SQL-036](../sql/SQL-036-external-user-last-logon-user-lookup-family.md), [EXT_USER](../database-tables.md#ext-user-ext-user-type), [EXT_USER_TYPE](../database-tables.md#ext-user-ext-user-type)).
8. Message helpers reduce the returned rows to a single summary string when callers need only the latest external-user logon narrative.

## Process flow

The following diagram visualizes this operation's control flow.

```mermaid
flowchart TD
    Start([User or reporting request]) --> Kind{Current principal or external-user query?}
    Kind -->|Principal| Principal[Classify user and derive group data]
    Kind -->|External query| Query[Build customer-scoped external-user query]
    Principal --> Return1([Return user type or access result])
    Query --> Prod{Production environment?}
    Prod -->|Yes| Filter[Exclude test users]
    Prod -->|No| Return2([Return query rows])
    Filter --> Return3([Return filtered rows or message])
```

## Failure and edge-case behavior

- Users who do not match any configured authorization group are classified as `Unknown`.
- Group-key derivation only runs for group users and returns empty chapter data when the user number does not contain chapter information.
- Production reporting intentionally suppresses test users from the external-user result sets ([BR-SB-007](../business-rules.md#br-sb-007-production-external-user-queries-hide-test-users)).

## Related documentation
- [Operations and processes](../operations-processes.md)
- [Business rules](../business-rules.md)
- [SQL catalog](../sql/index.md)
- [Database tables](../database-tables.md)

## Sources
- `Business\SAIF.Business\clsUserType.vb`
- `Business\SAIF.Business\ObjectServices.vb`
- `Business\SAIF.Business\Services\ExternalUserServices.vb`
