Sunday, June 14, 2026

Component Interface Questionaries

 --------------------------------------------------------------------------------

Q1. What is a PeopleSoft Component Interface (CI), and how does it differ from

    direct SQL manipulation?

--------------------------------------------------------------------------------


ANSWER:

A PeopleSoft Component Interface (CI) is a PeopleTools object that provides

programmatic access to a PeopleSoft component (page) using the same business

logic, validations, and PeopleCode events that run when a user interacts with

the component online. It acts as a wrapper around the component, exposing its

fields, keys, and methods to external programs, batch processes, or integration

points.


Key Characteristics:

- Mimics online component behavior programmatically

- Executes all PeopleCode events (FieldChange, RowInsert, SaveEdit, etc.)

- Respects buffer structure (scroll levels)

- Maintains data integrity via built-in validations

- Can be called from AE, external Java programs, or web services


Difference from Direct SQL:

  CI Approach                         | Direct SQL Approach

  ------------------------------------|--------------------------------------

  Triggers PeopleCode events          | Bypasses all PeopleCode

  Respects business rules             | No business rule enforcement

  Slower (event overhead)             | Faster (direct DB writes)

  Audit trail maintained              | No automatic audit trail

  Correct for business data           | Risk of corrupt data

  Uses Component buffer               | Direct table access

  Recommended for data integrity      | Used only for reference/config data


REAL-TIME SCENARIO:

Project: Oracle HCM to PeopleSoft HCM migration

- Team initially used SQL inserts to load employee personal data

- Result: Missing audit rows, broken effective-dated sequences,

  workflow notifications not triggered

- Switched to CI-based loading

- All PeopleCode validations executed, Workforce Administration rules applied,

  workflow triggered correctly


COMMON MISTAKES:

- Using SQL inserts for transactional data that has PeopleCode business rules

- Thinking CI is always slower without considering data integrity costs

- Not understanding that CI fires SaveEdit, SavePreChange, SavePostChange events


BEST PRACTICES:

- Use CI for any transactional data load where business rules must execute

- Use SQL only for reference/lookup data loads with no business logic

- Always prototype with a small dataset before bulk loading


INTERVIEW TIP:

Emphasize that CI is not just a convenience -- it is the only correct approach

for loading data that has associated business logic, workflows, or audit trails.


FOLLOW-UP QUESTIONS:

- When would you choose direct SQL over CI?

- How does CI handle effective-dated records?

- What happens if SaveEdit PeopleCode fails during CI execution?


--------------------------------------------------------------------------------

Q2. Explain the CI object structure in detail. What are its key components?

--------------------------------------------------------------------------------


ANSWER:

The CI object structure mirrors the underlying component buffer hierarchy.

It consists of:


1. SESSION OBJECT

   - Root entry point for any CI operation

   - Created using %Session (in PeopleCode) or GetSession() (Java API)

   - Controls mode (interactive/non-interactive), error behavior


2. COMPONENT INTERFACE OBJECT

   - Obtained via Session.GetCompIntfc("CI_NAME")

   - Has GetKeys, FindKeys, CreateKeys, properties, collections, methods


3. KEYS

   - GetKeys:    Keys used to retrieve an existing record (Get operation)

   - FindKeys:   Keys used to search for records (Find operation)

   - CreateKeys: Keys used to create a new record (Create operation)

   - Example: For JOB component, GetKey = EMPLID + EMPL_RCD


4. PROPERTIES

   - Correspond to fields in the component

   - Level-0 fields appear as direct properties on the CI object

   - Example: CI.PERSONAL_DATA.NAME, CI.JOB.DEPTID


5. COLLECTIONS

   - Correspond to scroll levels (Level 1, 2, 3 in the component)

   - Accessed using array-style indexing: Collection.Item(index) [1-based]

   - Example: CI.JOBCollection.Item(1).EFFDT


6. STANDARD METHODS

   - Get()    : Retrieve an existing record using GetKeys

   - Create() : Initialize a new record

   - Find()   : Search using FindKeys, returns a rowset of matches

   - Save()   : Save the current transaction

   - Cancel() : Discard changes


7. USER-DEFINED METHODS

   - Custom PeopleCode methods exposed on the CI

   - Defined in the component PeopleCode (CI Definition tab)


CI HIERARCHY DIAGRAM:

  Session

  +-- Component Interface Object (CI)

       +-- GetKeys  (EMPLID, EMPL_RCD)

       +-- FindKeys (EMPLID)

       +-- CreateKeys (BUSINESS_UNIT, JOURNAL_ID)

       +-- Properties (Level-0 fields)

       |    +-- CI.SETID

       |    +-- CI.EFFDT

       +-- Collections (Scroll Levels)

            +-- Collection (Level-1)

            |    +-- Properties

            |    +-- Sub-Collection (Level-2)

            |         +-- Properties

            +-- Item(1).FIELD_NAME


REAL-TIME SCENARIO:

Working on a custom benefits enrollment CI for Open Enrollment:

- Session created in AE

- CI = Session.GetCompIntfc("CI_BEN_ENROLL")

- GetKey1 = EMPLID

- GetKey2 = BENEFIT_PROGRAM

- Level-1 Collection = BenefitCollection (plan elections)

- Level-2 Sub-collection = DependentCollection (per plan)

- Save() triggered all enrollment workflow notifications


COMMON MISTAKES:

- Confusing GetKeys with FindKeys (GetKeys require exact values)

- Forgetting that collections are 1-based indexed (not 0-based)

- Not checking if a property is exposed in CI definition


BEST PRACTICES:

- Always document the key structure of each CI you build

- Validate exposed properties match what the integration partner needs

- Keep CI collections shallow -- deep nesting causes performance issues


INTERVIEW TIP:

Draw the CI hierarchy on a whiteboard if asked. Show:

Session -> CI Object -> Keys -> Properties -> Collections.

This demonstrates architectural clarity.


FOLLOW-UP QUESTIONS:

- How many scroll levels can a CI support?

- What is the difference between a Collection and a Property?

- How do you add a new row to a collection?


--------------------------------------------------------------------------------

Q3. What are GetKeys, FindKeys, and CreateKeys? When is each used?

--------------------------------------------------------------------------------


ANSWER:

These three key types serve distinct purposes in CI operations:


GETKEYS:

- Purpose: Uniquely identify an existing record to retrieve it

- Operation: Used with the Get() method

- Requirement: All GetKeys must be populated before calling Get()

- Behavior: Returns False if record not found

- Example: For CI_JOB -- EMPLID and EMPL_RCD are GetKeys


  PeopleCode Example:

  &oCI.EMPLID = "EMP0001";

  &oCI.EMPL_RCD = 0;

  If &oCI.Get() Then

     /* Record loaded */

  Else

     /* Record not found */

  End-If;


FINDKEYS:

- Purpose: Search for records matching partial criteria

- Operation: Used with the Find() method

- Returns: A rowset-like collection of matching records

- Example: Search by EMPLID only to get all job records for that employee


  PeopleCode Example:

  &oCI.EMPLID = "EMP0001";

  &oCollection = &oCI.Find();

  For &i = 1 To &oCollection.Count

     /* Process each matching record */

  End-For;


CREATEKEYS:

- Purpose: Define keys for creating a new record

- Operation: Used with the Create() method

- Behavior: Initializes the component buffer for a new record

- Example: For vouchers -- BUSINESS_UNIT and VOUCHER_ID are CreateKeys


  PeopleCode Example:

  &oCI.BUSINESS_UNIT = "US001";

  &oCI.VOUCHER_ID = "NEXT";

  &oCI.Create();

  /* Now populate other fields */


KEY COMPARISON TABLE:

  Key Type   | Method  | Returns              | Requires Exact Values?

  -----------|---------|----------------------|------------------------

  GetKeys    | Get()   | Single record        | Yes

  FindKeys   | Find()  | Collection of rows   | No (partial OK)

  CreateKeys | Create()| Empty new buffer     | Depends on autonumber


REAL-TIME SCENARIO:

Supplier onboarding integration:

- CreateKeys: SETID + VENDOR_ID (NEXT for auto-generated)

- Create() called to initialize new vendor record

- Properties set for vendor name, address, payment terms

- Save() called -- system auto-generated VENDOR_ID returned

- FindKeys used in reconciliation job to search vendors by NAME


COMMON MISTAKES:

- Calling Get() without setting all GetKeys -- causes runtime error

- Using GetKeys when you should use FindKeys (bulk searches)

- Not handling the case where Get() returns False


BEST PRACTICES:

- Always validate GetKey values before calling Get()

- Handle Get() = False explicitly with meaningful error messages

- Use FindKeys for validation/lookup; GetKeys for actual processing


INTERVIEW TIP:

Be ready to write code for all three scenarios. Interviewers often ask:

"Show me how you'd retrieve an employee's job record using CI."


FOLLOW-UP QUESTIONS:

- What happens if Get() fails? How do you handle it?

- Can you use Find() with no keys set? What happens?

- How are CreateKeys different for components with auto-numbered keys?


--------------------------------------------------------------------------------

Q4. Explain Collections in Component Interface. How do you navigate and

    manipulate multi-level scroll data?

--------------------------------------------------------------------------------


ANSWER:

Collections in CI represent scroll level data (Level 1, 2, 3) in the component

buffer. Each collection maps to a child record/scroll in the component.


COLLECTION BASICS:

- A Collection is an array of CI row objects

- Accessed via: CI.CollectionName.Item(index)  [1-based index]

- Count property: CI.CollectionName.Count

- Each item has its own properties and sub-collections


COLLECTION OPERATIONS:


1. READING EXISTING DATA:

  Local ApiObject &oCI, &oJobColl, &oJobRow;

  &oCI = &oSession.GetCompIntfc("CI_JOB");

  &oCI.EMPLID = "EMP0001";

  &oCI.EMPL_RCD = 0;

  If &oCI.Get() Then

     &oJobColl = &oCI.JOBCollection;

     For &i = 1 To &oJobColl.Count

        &oJobRow = &oJobColl.Item(&i);

        MessageBox(0, "", 0, 0, "DEPTID: " | &oJobRow.DEPTID);

     End-For;

  End-If;


2. INSERTING A NEW ROW:

  &oNewRow = &oJobColl.InsertItem(&oJobColl.Count + 1);

  &oNewRow.EFFDT = %Date;

  &oNewRow.EFFSEQ = 0;

  &oNewRow.ACTION = "PAY";

  &oNewRow.DEPTID = "DEPT001";

  &oCI.Save();


3. DELETING A ROW:

  &oJobColl.DeleteItem(2);  /* Delete the 2nd row */


4. MULTI-LEVEL (LEVEL-2) NAVIGATION:

  Local ApiObject &oL1, &oL1Row, &oL2, &oL2Row;

  &oL1 = &oCI.BenefitProgramCollection;

  For &i = 1 To &oL1.Count

     &oL1Row = &oL1.Item(&i);

     &oL2 = &oL1Row.BenefitPlanCollection;

     For &j = 1 To &oL2.Count

        &oL2Row = &oL2.Item(&j);

        /* Process level-2 data */

     End-For;

  End-For;


REAL-TIME SCENARIO:

Payroll deduction interface for benefits third-party provider:

- Level-0: Employee header (EMPLID, BENEFIT_PROGRAM)

- Level-1: Each benefit plan enrollment (PLAN_TYPE, BENEFIT_PLAN)

- Level-2: Each dependent covered under that plan

- InsertItem used to add new benefit elections from external file

- DeleteItem used to remove terminated coverages


COLLECTION COUNT vs ITEM INDEX:

- Count returns total rows in the collection

- Item(1) is the first row  [1-based, NOT 0-based]

- Item(Count) is the last row

- InsertItem(Count + 1) appends a new row at end


COMMON MISTAKES:

- Using 0-based indexing (Item(0) causes runtime error)

- Not checking Count before looping (empty collection has Count = 0)

- Forgetting that InsertItem fires RowInsert PeopleCode

- Modifying collection while iterating


BEST PRACTICES:

- Always check collection.Count > 0 before iterating

- Use InsertItem rather than direct row creation

- Log both the row index and key fields when errors occur


INTERVIEW TIP:

Draw Level-0 -> Level-1 -> Level-2 hierarchy and explain navigation.

Mention that InsertItem fires PeopleCode events -- this often surprises candidates.


FOLLOW-UP QUESTIONS:

- What happens to PeopleCode events when you call InsertItem?

- How do you handle a required Level-1 row when creating a new record?

- What is the maximum number of scroll levels in a CI?


--------------------------------------------------------------------------------

Q5. What are Standard Methods vs User-Defined Methods in CI?

    How do you expose a custom method?

--------------------------------------------------------------------------------


ANSWER:

STANDARD METHODS (Built-in):

  Method      | Purpose

  ------------|-----------------------------------------------

  Get()       | Load existing record using GetKeys

  Create()    | Initialize a new record using CreateKeys

  Find()      | Search using FindKeys, return match collection

  Save()      | Save current record to database

  Cancel()    | Discard changes, reset CI state

  GetPropertyByName() | Retrieve property value dynamically


USER-DEFINED METHODS:

- Custom PeopleCode functions exposed as CI methods

- Defined in Application Designer -> Component Interface -> Methods tab

- Useful for exposing complex business logic as a single callable operation


HOW TO EXPOSE A CUSTOM METHOD:

Step 1: Write PeopleCode function in component record FieldFormula

        or Application Class:

  Function CalculateProration(&StartDate As date, &EndDate As date)

     Returns number

     /* Business logic */

     Return &ProratedAmount;

  End-Function;


Step 2: In Application Designer, open the CI definition

Step 3: Go to Methods tab

Step 4: Add method name and map to PeopleCode function

Step 5: Save and build


CALLING A USER-DEFINED METHOD:

  Local ApiObject &oCI;

  &oCI = &oSession.GetCompIntfc("CI_PAYROLL");

  &oCI.EMPLID = "EMP001";

  &oCI.Get();

  Local number &Amount;

  &Amount = &oCI.CalculateProration(%Date - 30, %Date);


REAL-TIME SCENARIO:

Global Payroll implementation:

- CI exposed with standard Get/Save for payroll element entry

- User-defined method "ValidatePayElement" exposed on CI

- Third-party payroll engine called this method before submitting data

- Method internally ran complex eligibility rules in PeopleCode

- Returned True/False with error message


COMMON MISTAKES:

- Trying to expose methods that use interactive functions (DoModal, etc.)

- Not testing user-defined methods in non-interactive mode

- Forgetting to add the method to the Permission List


BEST PRACTICES:

- Keep user-defined CI methods stateless and side-effect free

- Document input/output parameters clearly

- Test in both AE context and Java API context


INTERVIEW TIP:

Explain that user-defined methods are like a "service layer" on top of CI --

they let you expose atomic business operations to external systems cleanly.


FOLLOW-UP QUESTIONS:

- Can a user-defined CI method call other CIs internally?

- How do you pass complex data structures to a CI method?

- What limitations exist for user-defined CI methods?


--------------------------------------------------------------------------------

Q6. Explain Interactive Mode vs Non-Interactive Mode in Component Interface.

--------------------------------------------------------------------------------


ANSWER:

INTERACTIVE MODE:

- Used when the calling program can interact with pop-up dialogs

- Supports DoModal, transfer functions, WinMessage

- Session connected to an active user session with browser context

- Less common in integration scenarios


NON-INTERACTIVE MODE:

- Designed for batch/automated processing (Application Engine, Java API)

- No user interaction -- all prompts and dialogs suppressed

- Error messages captured in error collection, not displayed as pop-ups

- Standard mode for CI-based data integration


SETTING NON-INTERACTIVE MODE (Java API):

  PeopleSoftSession session = new PeopleSoftSession();

  session.connect(1, "SERVER_NAME", "PEOPLESOFT", "PS", "PS");

  session.setInteractiveMode(false);

  CompIntfc ci = session.getCompIntfc("CI_PERSONAL_DATA");


IN PEOPLECODE (Application Engine):

  /* %Session in AE is already non-interactive by default */

  Local ApiObject &oSession;

  &oSession = %Session;


KEY BEHAVIORAL DIFFERENCES:

  Feature                | Interactive       | Non-Interactive

  -----------------------|-------------------|------------------

  Pop-up dialogs         | Displayed         | Suppressed

  Error handling         | User sees errors  | Error collection

  PeopleCode events      | All fire          | All fire

  Batch processing       | Not suitable      | Designed for this

  Session origin         | Browser session   | API session

  Performance            | Lower             | Higher throughput


NON-INTERACTIVE ERROR HANDLING:

  If Not &oCI.Save() Then

     Local ApiObject &oErrors;

     &oErrors = &oCI.GetErrors();

     For &i = 1 To &oErrors.Count

        Local ApiObject &oError;

        &oError = &oErrors.Item(&i);

        MessageBox(0,"",0,0, "Error: " | &oError.Text |

                   " Field: " | &oError.Field);

     End-For;

  End-If;


REAL-TIME SCENARIO:

Benefits open enrollment mass update job:

- Application Engine ran in non-interactive mode

- CI loaded 15,000 employee benefit elections overnight

- All save errors captured in error collection and written to error table

- Operations team reviewed error table next morning

- Re-run logic built for failed records only

- Zero user interaction required


COMMON MISTAKES:

- Using WinMessage inside CI-called PeopleCode in non-interactive mode

- Not implementing error collection processing (silently ignoring failures)

- Expecting pop-up error messages in batch mode


BEST PRACTICES:

- Always code for non-interactive mode in batch CI programs

- Implement comprehensive error collection processing

- Write all errors to a staging error table for operations review


INTERVIEW TIP:

Mention that some PeopleCode constructs (Transfer, DoModal) are invalid in

non-interactive mode and will cause runtime errors.


FOLLOW-UP QUESTIONS:

- How does error collection work in non-interactive mode?

- What PeopleCode functions are not allowed in non-interactive mode?

- How do you test a CI in non-interactive mode during development?


--------------------------------------------------------------------------------

Q7. How does the CI Session Object work? What are its key methods and properties?

--------------------------------------------------------------------------------


ANSWER:

The Session Object is the root of all CI operations. It represents a connection

to PeopleSoft and provides the gateway to all Component Interface objects.


OBTAINING THE SESSION OBJECT:


In PeopleCode (within PeopleSoft):

  Local ApiObject &oSession;

  &oSession = %Session;

  /* %Session is the built-in session in PeopleCode context */


In Java (external application):

  import PeopleSoft.PeopleTools.*;

  PeopleSoftSession session = new PeopleSoftSession();

  int rc = session.connect(1, "APPSERVER_NAME", "DB_NAME", "USERID", "PSWD");


SESSION OBJECT KEY METHODS:

  Method                         | Purpose

  -------------------------------|----------------------------------------

  GetCompIntfc(name)             | Get a CI object by name

  getCompIntfc(name)             | Java API equivalent

  SetInteractiveMode(bool)       | Toggle interactive/non-interactive

  GetErrors()                    | Get error collection from last operation

  ReturnToServer()               | Disconnect (Java)

  disconnect()                   | Java API: end session

  SetAuthToken(token)            | Set auth token for SSO scenarios


SESSION PROPERTIES:

  Property              | Description

  ----------------------|-------------------------------------------

  PSMessages            | Collection of messages/errors

  LogFence              | Controls trace log level

  TraceFlags            | Bit flags for trace output


COMPLETE SESSION WORKFLOW (PeopleCode AE):

  Local ApiObject &oSession, &oCI;

  &oSession = %Session;

  &oCI = &oSession.GetCompIntfc("CI_PERSONAL_DATA");

  If None(&oCI) Then

     MessageBox(0,"",0,0,"CI not found - check name and permissions");

     Exit(1);

  End-If;

  &oCI.EMPLID = "EMP001";

  If &oCI.Get() Then

     &oCI.NAME = "Smith, John";

     &oCI.Save();

  End-If;


SESSION IN JAVA API (External System):

  PeopleSoftSession psSession = null;

  try {

     psSession = new PeopleSoftSession();

     int rc = psSession.connect(1, "APPSVR01:9000", "HRMS91",

                                "PSUSER", "PSPASS");

     if (rc != 0) throw new Exception("Connect failed: " + rc);

     CompIntfc oCI = psSession.getCompIntfc("CI_JOB_DATA");

     oCI.setInteractiveMode(false);

     // ... operations ...

  } finally {

     if (psSession != null) psSession.disconnect();

  }


REAL-TIME SCENARIO:

SAP HR to PeopleSoft position sync:

- Java middleware obtained session for each batch run

- Session reused across 500 CI calls (session pooling pattern)

- &oSession.GetErrors() checked after every Save()

- Session disconnected gracefully in finally block

- Connection failures handled with retry logic


COMMON MISTAKES:

- Not disconnecting Java sessions (causes App Server connection leaks)

- Using %Session outside of PeopleCode context

- Not checking the return code of connect() in Java


BEST PRACTICES:

- Always disconnect Java sessions in finally blocks

- Reuse sessions across multiple CI operations (performance)

- Check GetErrors() after every Save(), not just at end


INTERVIEW TIP:

Distinguish between %Session (PeopleCode built-in) and Java's

PeopleSoftSession. Interviewers value candidates who understand both contexts.


FOLLOW-UP QUESTIONS:

- How do you implement session pooling for CI?

- What is the impact of not disconnecting a Java session?

- How do you pass authentication tokens for SSO?


--------------------------------------------------------------------------------

Q8. What is the CI Object Hierarchy for a multi-scroll component?

    Describe with a real example using JOB_DATA.

--------------------------------------------------------------------------------


ANSWER:

For a component with multiple scroll levels (like JOB_DATA), the CI object

hierarchy directly mirrors the page buffer structure.


REAL EXAMPLE: JOB_DATA Component Interface (CI_JOB_DATA)


Component Page Structure:

  Level 0: PERSONAL_DATA (EMPLID)

  Level 1: EMPLOYMENT (EMPLID, EMPL_RCD)

  Level 2: JOB (EMPLID, EMPL_RCD, EFFDT, EFFSEQ)

  Level 3: JOB_JR (Compensation rates)


CI Object Hierarchy:

  &oCI (CI_JOB_DATA)

  +-- GetKeys: EMPLID, EMPL_RCD

  +-- Properties (Level-0): EMPLID, NAME, etc.

  +-- EMPLOYMENTCollection (Level-1):

       +-- Item(1):

            +-- EMPL_RCD, EMPL_STATUS, etc.

            +-- JOBCollection (Level-2):

                 +-- Item(n):

                      +-- EFFDT, ACTION, DEPTID, JOBCODE

                      +-- JOB_JRCollection (Level-3):

                           +-- Item(1):

                                +-- COMPRATE, CURRENCY_CD


PEOPLECODE NAVIGATION (3 levels):

  Local ApiObject &oCI, &oL1, &oL2, &oL3;

  Local ApiObject &oL1Row, &oL2Row, &oL3Row;

  &oCI = %Session.GetCompIntfc("CI_JOB_DATA");

  &oCI.EMPLID = "EMP001";

  &oCI.EMPL_RCD = 0;

  If &oCI.Get() Then

     &oL1 = &oCI.EMPLOYMENTCollection;

     For &i = 1 To &oL1.Count

        &oL1Row = &oL1.Item(&i);

        &oL2 = &oL1Row.JOBCollection;

        For &j = 1 To &oL2.Count

           &oL2Row = &oL2.Item(&j);

           MessageBox(0,"",0,0,"Action: " | &oL2Row.ACTION);

           &oL3 = &oL2Row.JOB_JRCollection;

           For &k = 1 To &oL3.Count

              &oL3Row = &oL3.Item(&k);

              MessageBox(0,"",0,0,"Rate: " | &oL3Row.COMPRATE);

           End-For;

        End-For;

     End-For;

  End-If;


REAL-TIME SCENARIO:

Compensation review mass update:

- CI_JOB_DATA used to update compensation rates during merit cycle

- Navigate to Level-2 (JOB) to find current active row

- Insert new Level-2 row with ACTION = "PAY", new EFFDT

- Navigate to Level-3 (JOB_JR) under new row

- InsertItem for each pay component with new COMPRATE

- Save() triggered all compensation PeopleCode validations


COMMON MISTAKES:

- Assuming Level-1 always has exactly one row (it may have multiple)

- Not setting EFFDT and EFFSEQ when inserting Level-2 rows

- Forgetting Level-3 rows must be inserted after Level-2 is created


BEST PRACTICES:

- Always traverse all levels methodically; never assume row counts

- Insert required Level-3 rows immediately after Level-2 creation

- Log each level's key fields when writing error messages


INTERVIEW TIP:

Walk through this example step by step. Showing you understand 3-level

navigation instantly distinguishes you from average candidates.


FOLLOW-UP QUESTIONS:

- How do you find the most recent effective-dated row in a Level-2 collection?

- What happens if you try to insert a Level-3 row without a Level-2 parent?

- How does a 3-level CI perform vs a 2-level CI for bulk loading?


No comments:

Post a Comment

PEOPLESOFT FLUID — COMPREHENSIVE Q&A

 In-Depth Interview & Real-Time Reference Guide (2025-26) =================================================== TABLE OF CONTENTS: 1. FLUI...