Favorite menu management¶
Favorite menu management maintains MENU_FAVORITE, per-user bookmarks that let a user pin frequently used menu items for quick access. Each favorite carries a display order, an optional employee ID, and an optional ItemInactiveDate that supports soft deactivation without a hard delete. clsMenuFavoriteCollection can retrieve all favorites or scope to a single user; the menu authorization data lookup operation folds a user's active favorites into the authorized-item projection.
| Field | Value |
|---|---|
| Operation ID | OP-MNU-03 |
| Trigger | Caller requests clsMenuFavorite/clsMenuFavoriteCollection by key, by user ID, or in full, or calls Save() after Create()/retrieve |
| Inputs | MenuFavoriteSeqNum (key lookup); UserID (user-scoped retrieve); MenuItemSeqNum, UserID, MenuOrder, UserEmplID, ItemInactiveDate (insert/update) |
| Outputs | Populated clsMenuFavorite/clsMenuFavoriteCollection; on save, a new sequence-generated favorite, an updated row, or an error message on DML contention |
| Primary components | clsMenuFavorite, clsMenuFavoriteCollection |
| Entry point | Business\SAIF.Business.Menu\clsMenuFavorite.vb |
Steps¶
- Retrieve a single favorite.
clsMenuFavorite.GetMenuFavoritecreates aCriteriawith the requestedMenuFavoriteSeqNumand invokes the data portal;BeforeRetrievebinds the key and executesRetrieveSQL(SQL-019, MENU_FAVORITE).AfterRetrievefills the object (includingItemInactiveDateas aclsSmartDate) and marks it old. - Retrieve favorites for a user.
clsMenuFavoriteCollection.GetMenuFavoritesForUsersupplies a non-emptyUserID;BeforeRetrievedetectsMyCriteria.UserID.Trim.Length > 0and executesRetrieveByUserIDSQL(SQL-020, MENU_FAVORITE) with:UserIDbound. - If
UserIDis empty:clsMenuFavoriteCollection.GetAllMenuFavoritesexecutes the unfilteredRetrieveSQL(SQL-021) instead, returning every favorite for every user. - Create a new favorite.
clsMenuFavorite.NewMenuFavoritecallsCreate();BeforeCreate/AfterCreateexecute a scalar request forMENU_FAVORITE_SEQ.NEXTVAL FROM DUAL(SQL-001, DUAL) and seedMenuFavoriteSeqNumon the object and its criteria before marking it new and clean. - Save (insert) the favorite.
BeforeInsertbinds the generated sequence, the targetMenuItemSeqNum,UserID,UserEmplID, andMenuOrder, then executesInsertSQL(SQL-007, MENU_FAVORITE). - On success (
RowsAffected = 1):AfterInsertcallsMarkOld(). - On failure:
AddErrorMessage("InsertError", "Insert Failed")(BR-MNU-02). - Update or deactivate a favorite.
BeforeUpdatebinds the mutable fields includingItemInactiveDate, then executesUpdateSQL(SQL-033, MENU_FAVORITE). - Setting
ItemInactiveDateto a value (rather than clearing it viaSetItemInactiveDateNull) is the soft-deactivation path: the row remains in the table but is excluded from future favorite-lookup results that filter onITEM_INACTIVE_DATE IS NULL(BR-MNU-05). AfterUpdateapplies the row-count check, callingMarkOld()on success or addingUpdateErrorwithBOC.Messages.DBContentionErrorotherwise (BR-MNU-02).- Hard-delete a favorite.
BeforeDeletebinds the key and executesDeleteSQL(SQL-040, MENU_FAVORITE).AfterDeletecallsMarkNew()on a rows-affected value of1, or adds aDeleteErrorotherwise (BR-MNU-02). - Fold favorites into authorized-item lookup. The menu authorization data lookup operation's per-user UNION query includes a favorites leg that filters on
FAV.MENU_USER = :MenuUser AND FAV.ITEM_INACTIVE_DATE IS NULL, so only active (non-deactivated) favorites for that specific user appear in the authorized-item projection (BR-MNU-05).
Process flow¶
The following diagram visualizes the retrieve and deactivation control flow for favorites.
flowchart TD
Start([Caller requests favorites<br>by key, user, all, or new]) --> Which{Operation?}
Which -->|Retrieve by key| RetKey[Execute RetrieveSQL<br>with key parameter]
Which -->|Retrieve by user| UserCheck{UserID provided?}
UserCheck -->|Yes| RetUser[Execute RetrieveByUserIDSQL]
UserCheck -->|No| RetAll[Execute unfiltered RetrieveSQL]
Which -->|Create new| Seq[Obtain NEXTVAL from<br>MENU_FAVORITE_SEQ]
Seq --> SaveCall{Save called?}
SaveCall -->|Insert| Insert[Execute InsertSQL]
SaveCall -->|Update: set ItemInactiveDate| Deactivate[Execute UpdateSQL<br>row remains, excluded from active lookups]
Insert --> Rows{RowsAffected = 1?}
Deactivate --> Rows
Rows -->|Yes| Ok([MarkOld])
Rows -->|No| Err([AddErrorMessage])
Failure and edge-case behavior¶
- Every insert, update, and delete enforces a strict rows-affected-equals-1 check; any other value raises
InsertError,UpdateError, orDeleteErrorand the object is not marked clean (BR-MNU-02). - Soft deactivation (setting
ItemInactiveDate) and hard delete are two independent paths; a deactivated favorite still occupies a row and a sequence value, and must be explicitly deleted if the row itself needs to be removed. GetAllMenuFavoritesreturns every user's favorites with no filtering; a caller must apply its own access control before displaying results scoped to a single user.*ItemInactiveDateis represented as aclsSmartDate/nullableDate; a null value (the default) means the favorite is active, which the menu authorization data lookup operation relies on for itsIS NULLfilter (BR-MNU-05).
Related documentation¶
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\clsMenuFavorite.vbBusiness\SAIF.Business.Menu\clsMenuFavoriteCollection.vb