Skip to content

Application code scoping

Application code scoping maintains BUSONLINE_APPS_CODE, the lookup table that scopes MENU_PAGE records to a particular application via PAG.APPLICATION_CODE = APP.CODE. clsApplicationCode follows the standard BOF CRUD lifecycle; clsApplicationCodeCollection adds an active-only retrieval mode that treats a null ACTIVE_CODE as active by default.

Field Value
Operation ID OP-MNU-05
Trigger Caller requests clsApplicationCode/clsApplicationCodeCollection by key, active-only, or in full, or calls Save() after Create()/retrieve
Inputs Code (key lookup); Code, ApplicationPath (description), IsActive (insert/update)
Outputs Populated clsApplicationCode/clsApplicationCodeCollection; on save, a persisted row or an error message on DML contention
Primary components clsApplicationCode, clsApplicationCodeCollection
Entry point Business\SAIF.Business.Menu\clsApplicationCode.vb

Steps

  1. Retrieve a single application code. clsApplicationCode.GetApplicationCode creates a Criteria with the requested Code and invokes the data portal; BeforeRetrieve binds :Code and executes RetrieveSQL (SQL-012, BUSONLINE_APPS_CODE). AfterRetrieve fills the object (Code, ApplicationPath, and IsActive derived from NVL(ACTIVE_CODE,'Y')) and marks it old.
  2. Retrieve active codes only. clsApplicationCodeCollection.GetActiveApplicationCodes sets ActiveOnly = True on the criteria; BeforeRetrieve detects this and executes RetrieveActiveSQL (SQL-013), which appends WHERE NVL(ACTIVE_CODE, 'Y') = 'Y' — codes with a null ACTIVE_CODE are treated as active by default (BR-MNU-03).
  3. Retrieve all codes. clsApplicationCodeCollection.GetAllApplicationCodes leaves ActiveOnly false, so BeforeRetrieve executes the unfiltered RetrieveSQL (SQL-014) instead, returning both active and inactive codes.
  4. Create a new application code. clsApplicationCode.NewApplicationCode calls Create(), which sets m_Code = MyCriteria.Code directly — no sequence generation, since Code is a caller-supplied natural key.*
  5. Save (insert) the code. BeforeInsert binds Code (max length 5), ApplicationPath (max length 65), and IsActive converted to a Y/N string, then executes InsertSQL (SQL-005, BUSONLINE_APPS_CODE).
  6. On success (RowsAffected = 1): AfterInsert calls MarkOld().
  7. On failure: AddErrorMessage("InsertError", "Insert Failed") (BR-MNU-02).
  8. Update the code's path or active flag. BeforeUpdate binds ApplicationPath, IsActive, and the key Code, then executes UpdateSQL (SQL-031, BUSONLINE_APPS_CODE). AfterUpdate applies the row-count check, calling MarkOld() on success or adding UpdateError with BOC.Messages.DBContentionError otherwise (BR-MNU-02).
  9. Delete the code. BeforeDelete binds Code and executes DeleteSQL (SQL-038, BUSONLINE_APPS_CODE). AfterDelete calls MarkNew() on a rows-affected value of 1, or adds a DeleteError otherwise (BR-MNU-02).
  10. In-memory lookup by application path. clsApplicationCodeCollection.ItemByAppPath filters the already-loaded collection in memory (trimmed, upper-cased comparison) to resolve a clsApplicationCode by its display path without a further database round trip.
  11. Consume the scoping in menu rendering. The menu authorization data lookup operation's UNION queries join BUSONLINE_APPS_CODE to MENU_PAGE on APP.CODE = PAG.APPLICATION_CODE to resolve ApplicationPath for display alongside each returned menu item.

Process flow

The following diagram visualizes the retrieve/save control flow for application codes, including the active-only filter.

flowchart TD
    Start([Caller requests application code<br>by key, active, all, or new]) --> Which{Operation?}
    Which -->|Retrieve by key| RetKey[Execute RetrieveSQL<br>with Code parameter]
    Which -->|Retrieve active only| ActiveCheck[Execute RetrieveActiveSQL:<br>NVL ACTIVE_CODE,'Y' = 'Y']
    Which -->|Retrieve all| RetAll[Execute unfiltered RetrieveSQL]
    Which -->|Create new| Assign[Set Code from criteria<br>no sequence lookup]
    Assign --> SaveCall{Save called?}
    SaveCall -->|Yes| Insert[Execute InsertSQL]
    Insert --> Rows{RowsAffected = 1?}
    Rows -->|Yes| Ok([MarkOld])
    Rows -->|No| Err([AddErrorMessage: InsertError])

Failure and edge-case behavior

  • Every insert, update, and delete enforces a strict rows-affected-equals-1 check; any other value raises InsertError, UpdateError, or DeleteError and the object is not marked clean (BR-MNU-02).
  • A null ACTIVE_CODE is treated as active by default via NVL(ACTIVE_CODE, 'Y') in both the single-object retrieve and the active-only collection retrieve, so an application code is active unless explicitly marked otherwise (BR-MNU-03).
  • Code is a caller-supplied natural key (no sequence), so two concurrent callers creating the same Code will conflict at the database's primary-key constraint rather than through this library's own logic.*
  • The UpdateSQL text has a typo in its SET clause parameter name (:ApplicaitonPath instead of :ApplicationPath); because ADO.NET binds parameters positionally rather than by name for this call, the misspelling does not affect execution, but it is a latent maintainability defect.*

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.Menu\clsApplicationCode.vb
  • Business\SAIF.Business.Menu\clsApplicationCodeCollection.vb