Skip to content

SAIF.Business.View.Policy business rules

This page captures the business rules enforced by the SAIF.Business.View.Policy library. The library is a read-only policy-view layer, so its rules govern who may see a policy, how policy associations are classified, and which objects are considered valid. Authorization rules are also summarised, from the enforcement point of view, on the Security and authorization page.

BR-001: Secure SAIF policies require explicit authorization

Field Value
Statement A policy whose SecurePolicyCode equals the SAIF secure-policy constant is denied to any principal that does not hold the SAIFpolicyInfo authorization.
Trigger clsPolicySecurity.IsPolicyValidForUser(clsPolicyData) is entered.
Enforcement clsPolicySecurity.IsPolicyValidForUser checks the secure-policy code first and consults the security principal's SAIFpolicyInfo authorization (clsPolicySecurity.vb, lines 173-176).
Outcome Access is refused immediately and no further user-type evaluation occurs.
Source Business/SAIF.Business.View.Policy/clsPolicySecurity.vb

BR-002: Invalid or unnumbered policies are never accessible

Field Value
Statement Access is refused when the policy fails validation or its policy number is zero.
Trigger Authorization evaluation continues past the secure-policy check.
Enforcement clsPolicySecurity.IsPolicyValidForUser tests inPolicyData.IsValid and PolicyNum before any user-type branch (clsPolicySecurity.vb, lines 178-180).
Outcome The caller receives a refusal, so an unloaded or invalid policy can never be exposed.
Source Business/SAIF.Business.View.Policy/clsPolicySecurity.vb

BR-003: Internal and provider user types have unrestricted policy visibility

Field Value
Statement SAIF employees, MCO users, medical providers, and bookkeepers may view any valid policy.
Trigger The user type resolved from the security principal is an internal or provider type.
Enforcement clsPolicySecurity.IsPolicyValidForUser grants access for those user types without further filtering (clsPolicySecurity.vb, lines 184-187).
Outcome Access is granted for every policy that passes the preceding validity checks.
Source Business/SAIF.Business.View.Policy/clsPolicySecurity.vb

BR-004: Agents see only their own book

Field Value
Statement An agent may view a policy only when the agent's user number matches the policy's agent number or the policy's agency sequence number.
Trigger The user type is Agent.
Enforcement clsPolicySecurity.IsPolicyValidForUser compares the principal's user number against AgentNumber and AgencySeqNum on the policy (clsPolicySecurity.vb, lines 189-194).
Outcome Access is granted on a match and refused otherwise, confining agents to their own book of business.
Source Business/SAIF.Business.View.Policy/clsPolicySecurity.vb

BR-005: Policyholders see their own policy and policies under the same parent association

Field Value
Statement A policyholder may view the requested policy when it is their own policy, or when it belongs to an association whose parent association the user's own policy also belongs to.
Trigger The user type is PolicyHolder.
Enforcement clsPolicySecurity.IsPolicyValidForUser delegates to IsPolicyValidForParentPolicy, which compares parent-policy numbers derived from the policy associations of both policies (clsPolicySecurity.vb, lines 136-146 and 196-202).
Outcome Access is granted only for policies inside the user's own parent association group.
SQL SQL-026
Source Business/SAIF.Business.View.Policy/clsPolicySecurity.vb

BR-006: Group users see only policies in their group or chapter

Field Value
Statement A group user may view a policy only when the group-membership query returns at least one row for the group identifier, chapter, and policy number.
Trigger The user type is Group.
Enforcement clsPolicySecurity.IsInGroup executes the SQL Server procedure cp_policy_in_group against the separately configured BDS data store and requires a count greater than zero (clsPolicySecurity.vb, lines 204-205 and 253-261).
Outcome Access is granted only for policies explicitly listed in the caller's group or chapter.
Source Business/SAIF.Business.View.Policy/clsPolicySecurity.vb

BR-007: Loss-control consultants see only policies they are assigned to

Field Value
Statement A loss-control user may view a policy only when the policy's loss-control consultant team-assignment name begins with the user's identifier. Demo loss-control users are matched against the assignment's user-id name instead of the user name, and a % character in the user identifier truncates the comparison prefix.
Trigger The user type is LossControl and the policy carries a loss-control team assignment.
Enforcement clsPolicySecurity.CanSafetyConsultantAccessPolicy performs the prefix comparison over the team assignments retrieved for the policy (clsPolicySecurity.vb, lines 207-218 and 227-236).
Outcome Access is granted on a prefix match; a policy with no loss-control assignment stays inaccessible.
SQL SQL-009
Source Business/SAIF.Business.View.Policy/clsPolicySecurity.vb

BR-008: Fee auditors see only policies with a recent, non-cancelled audit

Field Value
Statement An auditor may view a policy only when an audit exists for that policy under the auditor's vendor number whose cancel date and completed date are no older than 60 days before the data-source date.
Trigger The user type is Auditor.
Enforcement clsPolicySecurity.CanAuditorAccessPolicy runs a vendor-scoped, date-windowed audit count and requires a result greater than zero (clsPolicySecurity.vb, lines 220-221 and 263-282).
Outcome Access is granted only while an auditor's engagement on the policy is current.
Source Business/SAIF.Business.View.Policy/clsPolicySecurity.vb

BR-009: A policy view requires a positive policy number

Field Value
Statement clsPolicyData is valid only when its policy number is greater than zero.
Trigger Broken-rule evaluation runs during a read of IsValid.
Enforcement clsPolicyData.ValidPolicyNum is registered in AddBusinessRules and reports the message "Error: Invalid policy number." (clsPolicyData.vb, lines 2211-2219).
Outcome IsValid reports false, and the authorization path then refuses access under BR-002.
SQL SQL-007
Source Business/SAIF.Business.View.Policy/clsPolicyData.vb

BR-010: A non-employer account requires a non-zero account number

Field Value
Statement clsNonEmployerAccount is valid only when its account number is not zero.
Trigger Broken-rule evaluation runs after the object is loaded.
Enforcement clsNonEmployerAccount.IsValidAccountNumber is registered as a business rule and reports the message "Error: Invalid Non Employer Account Number" (clsNonEmployerAccount.vb, lines 273-279).
Outcome The object reports itself invalid, so callers can reject an unusable account before display.
Tables NON_EMPR_ACCT
SQL SQL-004
Source Business/SAIF.Business.View.Policy/clsNonEmployerAccount.vb

BR-011: Affiliated-policy visibility depends on user access level and affiliate type

Field Value
Statement Quick-file users never see affiliated policies. Internal, agent, auditor, group, and loss-control levels see them for every affiliate type except non-affiliated and affiliation parent or member. Policyholder levels see them only when the policy is the parent of the association.
Trigger clsPolicyData.DisplayAffiliatedPolices is read.
Enforcement clsPolicyData.DisplayAffiliatedPolices combines the caller's UserAccessLevels value with the resolved affiliate type (clsPolicyData.vb, lines 233-264). The member is marked <Obsolete> in favour of the Associations property.
Outcome Presentation layers receive a single boolean display decision for the affiliated-policy panel.
SQL SQL-001
Source Business/SAIF.Business.View.Policy/clsPolicyData.vb

BR-012: Demo access levels are treated as a distinct user population

Field Value
Statement A user is a demo user when the access level is any of demo agent, demo group, demo policyholder, demo auditor, or demo loss control. Demo status is propagated into team-assignment retrieval and loss-control name matching.
Trigger clsPolicyData.IsDemoUser is read, or clsPolicySecurity.ConvertUserTypeToUserAccessLevel runs.
Enforcement clsPolicyData.IsDemoUser tests the access level against the five demo values (clsPolicyData.vb, lines 266-273 and 1264-1272); clsPolicySecurity.ConvertUserTypeToUserAccessLevel selects the demo variant when the principal is flagged as a demo user (clsPolicySecurity.vb, lines 367-405).
Outcome Demo users receive masked demo identity data in team assignments and are matched on user-id name for loss-control access under BR-007.
SQL SQL-009
Source Business/SAIF.Business.View.Policy/clsPolicyData.vb, Business/SAIF.Business.View.Policy/clsPolicySecurity.vb

BR-013: User type maps to a ranked access level

Field Value
Statement Each authenticated user type maps to exactly one UserAccessLevels value: SAIF employee 1000, auditor 900 or 850, loss control 800 or 750, agent 700 or 650, group 600 or 550, policyholder, MCO, and medical provider 500 or 450, and bookkeeper to quick file 300. The lower value of each pair is selected when the user is flagged as a demo user.
Trigger clsPolicySecurity.UserAccessLevel is read, or the conversion is called explicitly.
Enforcement clsPolicySecurity.ConvertUserTypeToUserAccessLevel performs the mapping (clsPolicySecurity.vb, lines 367-405) against the UserAccessLevels enumeration declared in clsPolicyData.vb (lines 82-95).
Outcome The resulting ranked level is passed into clsPolicyData criteria and drives visibility decisions such as BR-011.
Source Business/SAIF.Business.View.Policy/clsPolicySecurity.vb, Business/SAIF.Business.View.Policy/clsPolicyData.vb

BR-014: Association date defaults differ per association family and detail-load failures are non-fatal

Field Value
Statement When no as-of date is supplied, experience-rating combination selection uses the data-source date while discount-combination selection uses the policy's latest policy-period effective date; when an as-of date is supplied, both use it. Separately, a failure while lazily loading policy detail is swallowed so that the header remains usable.
Trigger PolicyAssociationList.GetPolicyAssociationList is invoked, or clsPolicyData lazily reads its detail block.
Enforcement PolicyAssociations.vb (lines 258-272) selects the two default dates; clsPolicyData.vb (lines 1508-1520) catches and discards detail-load failures.
Outcome Association results are date-scoped predictably, and detail properties fall back to empty values instead of raising.
Tables POLICY_PERIOD
SQL SQL-013, SQL-019, SQL-027, SQL-028
Source Business/SAIF.Business.View.Policy/PolicyAssociations.vb, Business/SAIF.Business.View.Policy/clsPolicyData.vb

BR-015: Unrecognized relationship codes are classified as not specified

Field Value
Statement A relationship code returned by the association query that does not match a known code (WRAP, OREGN, LEASE, SUBAC, their M.-prefixed manual forms, DiscountCombination, and ExperienceCombination) is classified as not specified.
Trigger Rows are projected in GetPolicyAssociationList.
Enforcement PolicyAssociations.ConvertAssociationType maps unrecognised codes to NotSpecified (PolicyAssociations.vb, lines 220-252).
Outcome The association is retained but carries no meaningful type and maps to AffiliateTypes.NonAffiliated.
Tables POLICY_RELATIONSHIP
SQL SQL-003, SQL-026, SQL-029
Source Business/SAIF.Business.View.Policy/PolicyAssociations.vb

BR-016: Manually maintained affiliations are distinguished by an M-prefixed code

Field Value
Statement Associations sourced from POLICY_RELATIONSHIP are emitted with an M. prefix on the affiliation type code and resolve to the manual association types. IsManual and ToNonManual convert between the manual and system-derived forms.
Trigger Associations are retrieved and their type codes converted.
Enforcement PolicyAssociations.vb applies the prefix during projection and supplies the conversion helpers (lines 68-96, 220-252, and 396-420).
Outcome Consumers can distinguish user-entered affiliations from system-derived combinations.
Tables POLICY_RELATIONSHIP
SQL SQL-026
Source Business/SAIF.Business.View.Policy/PolicyAssociations.vb

BR-017: Association rows without a matching type code are discarded

Field Value
Statement A policy-header association row is retained only when its category-prefixed association type code matches an entry in the association type code table; unmatched rows are discarded. All types within one category grouping must additionally share a single source stored procedure.
Trigger clsAssociationTypeCode.GetGroupedPolicyHeaderAssociations or GetGroupedAssociations runs.
Enforcement Associations/clsAssociationTypeCode.vb (lines 320-333) filters rows against the loaded code table and resolves the shared source procedure with .Distinct.Single.
Outcome Unknown codes are dropped silently, and a category whose types disagree on their source procedure raises an error.
Tables ASSOCIATION_TYPE_CODE
SQL SQL-003, SQL-029
Source Business/SAIF.Business.View.Policy/Associations/clsAssociationTypeCode.vb

BR-018: Agent policy lists are produced only for numeric agent identifiers

Field Value
Statement The agent policy-list query runs only when the agent's user number is numeric. The agency-scope flag is set to the yes/no form of "the user is not a producer", so a non-producer agent receives the whole agency's book.
Trigger clsPolicySecurity.PolicyList is read for user type Agent.
Enforcement clsPolicySecurity.GetPolicyListForAgent performs the numeric test and sets the @ForAgency flag from producer status (clsPolicySecurity.vb, lines 73-75 and 324-337).
Outcome A non-numeric agent identifier yields an empty policy list rather than an error or an unfiltered list.
Source Business/SAIF.Business.View.Policy/clsPolicySecurity.vb

BR-019: Policy lists fail closed

Field Value
Statement When no user-type branch produces a policy list, an empty list is returned rather than Nothing or an unrestricted list.
Trigger clsPolicySecurity.PolicyList is read.
Enforcement clsPolicySecurity.PolicyList initialises the backing list and returns it unchanged when no branch matches (clsPolicySecurity.vb, lines 88-94).
Outcome Callers receive zero permitted policies, so an unrecognised user type cannot widen access.
Source Business/SAIF.Business.View.Policy/clsPolicySecurity.vb

BR-020: Affiliated policies are filtered to the requesting agent or agency when specified

Field Value
Statement When the criteria carry a non-zero agent number or agency sequence number, only affiliated policies matching that agent or agency are added to the collection. When both are zero, every affiliated policy is added.
Trigger clsAffiliatedPolicyCollection.AfterRetrieve processes result rows.
Enforcement clsAffiliatedPolicyCollection.vb (lines 104-125) filters each row against the criteria before adding it.
Outcome Agents see only their own affiliated policies within an affiliation group.
SQL SQL-001
Source Business/SAIF.Business.View.Policy/clsAffiliatedPolicyCollection.vb

BR-021: This library never writes policy data

Field Value
Statement Create, insert, update, and delete SQL are unsupported for every business object in this library. Attempting one either yields an empty statement or raises ApplicationException(clsConstants.Messages.InvalidSQLProperty).
Trigger The framework attempts any non-retrieve lifecycle operation.
Enforcement The Criteria SQL properties in all twelve compiled criteria classes refuse the operation (for example clsPolicyData.vb, lines 2382-2404, clsTradingAs.vb, and Associations/clsAssociationTypeCode.vb).
Outcome The library stays read-only; persistence must occur in another package.
Source Business/SAIF.Business.View.Policy/clsPolicyData.vb, Business/SAIF.Business.View.Policy/clsTradingAs.vb, Business/SAIF.Business.View.Policy/Associations/clsAssociationTypeCode.vb

Inherited business rules

Rules in this section originate from base classes provided by the SAIF.Framework.Core dependency. They are enforced by inherited behaviour rather than by code in this library, and they apply to every business object and collection documented in the API reference.

From clsBusinessBase (SAIF.Framework.Core)

INH-001: Broken rules determine object validity

Field Value
Statement A business object is valid only while its broken-rules collection is empty; every registered rule is re-evaluated when its associated property changes.†
Trigger A property registered through AddBusinessRules changes, or IsValid is read.
Enforcement clsBusinessBase maintains a clsRulesManager instance and recomputes the broken-rules collection on property change.†
Outcome IsValid reports false and BrokenRulesCollection carries the rule messages until the condition clears.†
Origin SAIF.Framework.Core — clsBusinessBase
Source Retrieved from indexed documentation via Legends CLI

INH-002: Retrieval is mediated by the data portal, not by the object itself

Field Value
Statement A business object never opens a connection directly; it supplies SQL and parameters through its Criteria object and the data portal executes the request.†
Trigger A shared factory method calls the framework retrieve entry point.
Enforcement clsBusinessBase orchestrates BeforeRetrieve, portal execution, and AfterRetrieve around an IPortalRequest.†
Outcome All database access in this library is funnelled through a single, auditable execution path.†
Origin SAIF.Framework.Core — clsBusinessBase
Source Retrieved from indexed documentation via Legends CLI

INH-003: Lifecycle hooks are the only supported extension points

Field Value
Statement Derived types customise persistence behaviour exclusively through the protected BeforeRetrieve and AfterRetrieve overrides.†
Trigger The framework executes a retrieve request.
Enforcement clsBusinessBase declares the overridable hooks and invokes them around portal execution.†
Outcome Every retrieval in this library follows the same predictable sequence, which is why each SQL document names a lifecycle method.†
Origin SAIF.Framework.Core — clsBusinessBase
Source Retrieved from indexed documentation via Legends CLI

From clsBusinessCollectionBase (SAIF.Framework.Core)

INH-004: Collections track added, removed, and deleted members

Field Value
Statement A business collection maintains a deleted-items list alongside its live members so that removals can be distinguished from absences.†
Trigger An item is removed from the collection.
Enforcement clsBusinessCollectionBase moves the item into its deleted-items list rather than discarding it.†
Outcome ContainsDeleted on the policy-period and affiliated-policy collections can answer questions about removed members.†
Origin SAIF.Framework.Core — clsBusinessCollectionBase
Source Retrieved from indexed documentation via Legends CLI

Notes

  • Rule identifiers are stable within this library: BR-001 through BR-021 cover locally enforced behaviour and INH- identifiers cover behaviour inherited from SAIF.Framework.Core.
  • BR-001, BR-003, BR-004, BR-005, BR-006, BR-007, and BR-008 together form the complete authorization matrix. The matching enforcement points are catalogued on the Security and authorization page.
  • BR-011 and BR-014 are enforced by members that the source marks <Obsolete>. They remain in force for existing callers but are superseded by the Associations property and the association type code table.
  • The group-membership check behind BR-006 runs against a second, SQL Server data store that is configured separately from the Oracle data portal. See Configuration.

Note: Statements marked with † are derived from dependency library documentation via the Legends CLI. Statements marked with * were inferred from code structure or contextual evidence.

Sources

  • Business/SAIF.Business.View.Policy/clsPolicySecurity.vb
  • Business/SAIF.Business.View.Policy/clsPolicyData.vb
  • Business/SAIF.Business.View.Policy/clsNonEmployerAccount.vb
  • Business/SAIF.Business.View.Policy/clsAffiliatedPolicyCollection.vb
  • Business/SAIF.Business.View.Policy/clsTradingAs.vb
  • Business/SAIF.Business.View.Policy/PolicyAssociations.vb
  • Business/SAIF.Business.View.Policy/Associations/clsAssociationTypeCode.vb

Stored procedure business rules

Rules in this section are enforced inside the Oracle stored procedures and functions that this library calls. They are not implemented in .NET code, but they change the values that callers observe.

Rule ID Rule Source Link
PROC-RULE-001 The per-row cancellation status is always computed live, not stored pk73094_policy_data.getpolicy Details
PROC-RULE-002 Sales-plan name is masked for reduced-form (RF) policy periods pk72846_view_policy.getviewdetail Details
PROC-RULE-003 A policy has a coverage gap indicator when getgapindicator returns non-zero pk72846_view_policy.getviewdetail Details
PROC-RULE-004 A policy is flagged as a combination-wrap sub-account only when a sibling policy in the same experience-rating combination carries policy_relationship_code = 'WRAP' pk72846_view_policy.getviewdetail Details
PROC-RULE-005 Manual (policyholder-portal) affiliation takes priority over all other affiliation types, but only for policyholder users pk72846_view_policy.getpolicyaffiliatetype Details
PROC-RULE-006 Affiliation family precedence after the manual check is wrap-up/leasing, then sub-account/state-agency, then experience combination, then premium-discount combination pk72846_view_policy.getpolicyaffiliatetype Details
PROC-RULE-007 The parent policy number is derived from the affiliate type rather than stored directly pk72846_view_policy.getparentpolicy Details
PROC-RULE-008 The legal name shown for a wrap-up chain cascades from the policy to its wrap-up relationship policy to that policy's rate account pk72846_view_policy.getwrapuplegalname Details
PROC-RULE-009 A coverage gap exists between two consecutive periods unless the period is flat-cancelled or a PMS prospect period pk72846_view_policy.getgaps Details
PROC-RULE-010 The agency and producer shown for a policy are always resolved through the current agent-of-record rather than a stored foreign key pk72846_view_policy.getagency Details
PROC-RULE-011 When the caller allows mail-address fallback and no active claim address exists, the mailing address type is substituted for the claim type pk72846_view_policy.getpolicyaddress Details
PROC-RULE-012 When multiple contacts exist for a location, only the highest-priority contact type is returned pk72846_view_policy.getpolicyaddressbylocseqnum Details
PROC-RULE-013 Risk-type code, sales-plan name, risk-type factor, and standard premium are masked for reduced-form periods until the information page has printed pk72846_view_policy.getpolicyperiods Details
PROC-RULE-014 The affiliated-policy list and its optional totals row are keyed to a relationship-code family selected from the caller's affiliate-type prefix pk72846_view_policy.getpolicyaffiliatelist Details
PROC-RULE-015 A team member's employee-status code can be overridden by an alias mapping pk72846_view_policy.team_assign_query Details
PROC-RULE-016 A policy "has a waiver" is defined purely as having at least one waiver-detail row Pk82033_ThirdParty.get_policy_waiver_count Details
PROC-RULE-017 Employer-liability limits fall back through a fixed hierarchy from policy-specific current limits to legacy non-WCIS defaults coveragelimits_pkg.getSpecificLimitsForPolicyNum Details
PROC-RULE-018 Cancellation and collection status is derived from a fixed priority order gated by the policy's status group sp72268_get_cancel_status Details
PROC-RULE-019 Coverage-bound status is a thin Y/N wrapper over an external boolean check sp73089_get_policy_bound_flag Details
PROC-RULE-020 Information-page-printed status is a thin Y/N wrapper over an external boolean check sp72347_info_page_printed_yn Details
PROC-RULE-021 External client e-mail lookup is a case-insensitive, trimmed exact match on both mail identifier and last name sp73341_external_client_lookup Details
PROC-RULE-022 External client e-mail lookup (legacy path) is a trimmed exact match on both mail identifier and last name cp_external_client_lookup Details
PROC-RULE-023 Only active, non-test registrant rows are eligible for the legacy e-mail lookup cp_external_client_lookup Details
PROC-RULE-024 When multiple registrant rows match the legacy e-mail lookup, the most recently updated row wins cp_external_client_lookup Details