Case Study 2: Designing a Loan Application Data Structure
Background
Meridian Community Credit Union (MCCU) serves approximately 180,000 members across three states. In 2024, the credit union launched a project to replace its paper-based loan application process with a fully digital system running on its IBM z/OS mainframe. The new system would accept loan applications from branch tellers, online banking portals, and a new mobile app -- all feeding into a single COBOL batch processing program that would evaluate applications nightly.
Roberto Diaz, a COBOL developer with 14 years of experience at MCCU, was tasked with designing the WORKING-STORAGE data structures for the loan application processing program. Roberto understood that the quality of the data design would directly determine the quality of every paragraph in the PROCEDURE DIVISION. A well-structured WORKING-STORAGE section would make the validation, scoring, and decision logic straightforward to implement. A poorly structured one would cause confusion, bugs, and costly rework.
This case study follows Roberto's design process as he builds a comprehensive WORKING-STORAGE layout for the loan application system, demonstrating group items, 88-level conditions, VALUE clause initialization, and the organizational principles covered in Chapter 4.
The Requirements
The loan application processing program must handle five loan products:
- Personal unsecured loans -- $1,000 to $25,000, terms of 12 to 60 months
- Auto loans (new vehicles) -- $5,000 to $75,000, terms of 24 to 72 months
- Auto loans (used vehicles) -- $3,000 to $50,000, terms of 24 to 60 months
- Home equity loans -- $10,000 to $250,000, terms of 60 to 240 months
- Share-secured loans -- $500 to $100,000, terms of 6 to 60 months
For each application, the program must:
- Capture and validate applicant personal information (name, SSN, date of birth, address, phone, email)
- Record employment information (employer, job title, years employed, employment status)
- Collect financial details (gross monthly income, monthly debt payments, existing MCCU accounts)
- Store the loan request parameters (product type, amount, term, purpose)
- Calculate the debt-to-income ratio and determine the risk tier
- Make an automated decision: approve, conditionally approve, deny, or refer to a loan officer
- Track processing statistics for the nightly batch report
Roberto's Design: The Complete Data Structure
Organizing the WORKING-STORAGE Section
Roberto began by sketching the major groups on a whiteboard. He identified seven logical sections:
- Program constants (product limits, rate tables, scoring thresholds)
- Processing flags and switches
- Counters and accumulators for the batch report
- The loan application record (applicant, employment, financial, loan request)
- Calculation work fields
- Decision result fields
- Display and report formatting fields
He then translated this design into COBOL, using the naming conventions established by MCCU's development standards.
The Complete Program
The following program demonstrates Roberto's full WORKING-STORAGE design with a PROCEDURE DIVISION that processes three sample loan applications and produces a summary.
IDENTIFICATION DIVISION.
PROGRAM-ID. LOANAPP.
*================================================================*
* Program: LOANAPP
* Description: Loan Application Processing - Data Structure Demo
* Author: Roberto Diaz
* Date: 2024-03-15
* Purpose: Demonstrates WORKING-STORAGE design for a loan
* application processing system at Meridian
* Community Credit Union.
*================================================================*
DATA DIVISION.
WORKING-STORAGE SECTION.
*================================================================*
* SECTION 1: PROGRAM CONSTANTS *
*================================================================*
01 WS-C-PROGRAM-INFO.
05 WS-C-PROGRAM-ID PIC X(08) VALUE 'LOANAPP '.
05 WS-C-PROGRAM-VER PIC X(05) VALUE '01.00'.
05 WS-C-INSTITUTION PIC X(30)
VALUE 'MERIDIAN COMMUNITY CU'.
*--- Loan product limits ---
01 WS-C-PERSONAL-LIMITS.
05 WS-C-PERS-MIN-AMT PIC 9(07)V99
VALUE 1000.00.
05 WS-C-PERS-MAX-AMT PIC 9(07)V99
VALUE 25000.00.
05 WS-C-PERS-MIN-TERM PIC 9(03) VALUE 012.
05 WS-C-PERS-MAX-TERM PIC 9(03) VALUE 060.
01 WS-C-AUTO-NEW-LIMITS.
05 WS-C-ANEW-MIN-AMT PIC 9(07)V99
VALUE 5000.00.
05 WS-C-ANEW-MAX-AMT PIC 9(07)V99
VALUE 75000.00.
05 WS-C-ANEW-MIN-TERM PIC 9(03) VALUE 024.
05 WS-C-ANEW-MAX-TERM PIC 9(03) VALUE 072.
01 WS-C-AUTO-USED-LIMITS.
05 WS-C-AUSD-MIN-AMT PIC 9(07)V99
VALUE 3000.00.
05 WS-C-AUSD-MAX-AMT PIC 9(07)V99
VALUE 50000.00.
05 WS-C-AUSD-MIN-TERM PIC 9(03) VALUE 024.
05 WS-C-AUSD-MAX-TERM PIC 9(03) VALUE 060.
01 WS-C-HOME-EQUITY-LIMITS.
05 WS-C-HEQL-MIN-AMT PIC 9(07)V99
VALUE 10000.00.
05 WS-C-HEQL-MAX-AMT PIC 9(07)V99
VALUE 250000.00.
05 WS-C-HEQL-MIN-TERM PIC 9(03) VALUE 060.
05 WS-C-HEQL-MAX-TERM PIC 9(03) VALUE 240.
01 WS-C-SHARE-SECURED-LIMITS.
05 WS-C-SSEC-MIN-AMT PIC 9(07)V99
VALUE 500.00.
05 WS-C-SSEC-MAX-AMT PIC 9(07)V99
VALUE 100000.00.
05 WS-C-SSEC-MIN-TERM PIC 9(03) VALUE 006.
05 WS-C-SSEC-MAX-TERM PIC 9(03) VALUE 060.
*--- DTI ratio thresholds ---
01 WS-C-DTI-THRESHOLDS.
05 WS-C-DTI-EXCELLENT PIC V9(4) VALUE 0.2800.
05 WS-C-DTI-GOOD PIC V9(4) VALUE 0.3600.
05 WS-C-DTI-FAIR PIC V9(4) VALUE 0.4300.
05 WS-C-DTI-MAX PIC V9(4) VALUE 0.5000.
*--- Credit score thresholds ---
01 WS-C-SCORE-THRESHOLDS.
05 WS-C-SCORE-EXCEL-MIN PIC 9(03) VALUE 740.
05 WS-C-SCORE-GOOD-MIN PIC 9(03) VALUE 670.
05 WS-C-SCORE-FAIR-MIN PIC 9(03) VALUE 580.
05 WS-C-SCORE-MINIMUM PIC 9(03) VALUE 500.
*--- Report formatting constants ---
01 WS-C-REPORT-SEP PIC X(60) VALUE ALL '='.
01 WS-C-DETAIL-SEP PIC X(60) VALUE ALL '-'.
*================================================================*
* SECTION 2: PROCESSING FLAGS AND SWITCHES *
*================================================================*
01 WS-F-EOF-FLAG PIC X(01) VALUE 'N'.
88 WS-EOF VALUE 'Y'.
88 WS-NOT-EOF VALUE 'N'.
01 WS-F-APP-VALID-FLAG PIC X(01) VALUE 'Y'.
88 WS-APP-IS-VALID VALUE 'Y'.
88 WS-APP-IS-INVALID VALUE 'N'.
01 WS-F-PROCESSING-FLAG PIC X(01) VALUE 'Y'.
88 WS-CONTINUE-PROCESSING VALUE 'Y'.
88 WS-STOP-PROCESSING VALUE 'N'.
*================================================================*
* SECTION 3: COUNTERS AND ACCUMULATORS *
*================================================================*
01 WS-CTR-APPLICATIONS.
05 WS-CTR-TOTAL-READ PIC 9(05) VALUE ZERO.
05 WS-CTR-APPROVED PIC 9(05) VALUE ZERO.
05 WS-CTR-COND-APPROVED PIC 9(05) VALUE ZERO.
05 WS-CTR-DENIED PIC 9(05) VALUE ZERO.
05 WS-CTR-REFERRED PIC 9(05) VALUE ZERO.
05 WS-CTR-ERRORS PIC 9(05) VALUE ZERO.
01 WS-CTR-BY-PRODUCT.
05 WS-CTR-PERSONAL PIC 9(05) VALUE ZERO.
05 WS-CTR-AUTO-NEW PIC 9(05) VALUE ZERO.
05 WS-CTR-AUTO-USED PIC 9(05) VALUE ZERO.
05 WS-CTR-HOME-EQUITY PIC 9(05) VALUE ZERO.
05 WS-CTR-SHARE-SECURED PIC 9(05) VALUE ZERO.
01 WS-ACC-AMOUNTS.
05 WS-ACC-TOTAL-REQUESTED PIC 9(11)V99 VALUE ZERO.
05 WS-ACC-TOTAL-APPROVED PIC 9(11)V99 VALUE ZERO.
05 WS-ACC-TOTAL-DENIED PIC 9(11)V99 VALUE ZERO.
*================================================================*
* SECTION 4: LOAN APPLICATION RECORD *
*================================================================*
*--- 4A: Application Header ---
01 WS-APP-HEADER.
05 WS-APP-ID PIC X(12).
05 WS-APP-DATE PIC 9(08).
05 WS-APP-DATE-PARTS REDEFINES WS-APP-DATE.
10 WS-APP-DATE-YYYY PIC 9(04).
10 WS-APP-DATE-MM PIC 9(02).
10 WS-APP-DATE-DD PIC 9(02).
05 WS-APP-BRANCH PIC X(04).
05 WS-APP-CHANNEL PIC X(01).
88 WS-CHANNEL-BRANCH VALUE 'B'.
88 WS-CHANNEL-ONLINE VALUE 'O'.
88 WS-CHANNEL-MOBILE VALUE 'M'.
88 WS-CHANNEL-PHONE VALUE 'P'.
88 WS-CHANNEL-VALID
VALUE 'B' 'O' 'M' 'P'.
*--- 4B: Applicant Personal Information ---
01 WS-APP-PERSONAL.
05 WS-APP-FIRST-NAME PIC X(20).
05 WS-APP-MIDDLE-INIT PIC X(01).
05 WS-APP-LAST-NAME PIC X(25).
05 WS-APP-SSN PIC X(09).
05 WS-APP-DOB PIC 9(08).
05 WS-APP-DOB-PARTS REDEFINES WS-APP-DOB.
10 WS-APP-DOB-YYYY PIC 9(04).
10 WS-APP-DOB-MM PIC 9(02).
10 WS-APP-DOB-DD PIC 9(02).
05 WS-APP-ADDRESS.
10 WS-APP-STREET PIC X(30).
10 WS-APP-CITY PIC X(20).
10 WS-APP-STATE PIC X(02).
10 WS-APP-ZIP PIC X(10).
05 WS-APP-PHONE-PRIMARY PIC X(10).
05 WS-APP-PHONE-ALT PIC X(10).
05 WS-APP-EMAIL PIC X(40).
*--- 4C: Employment Information ---
01 WS-APP-EMPLOYMENT.
05 WS-APP-EMP-STATUS PIC X(01).
88 WS-EMP-FULL-TIME VALUE 'F'.
88 WS-EMP-PART-TIME VALUE 'P'.
88 WS-EMP-SELF-EMPLOYED VALUE 'S'.
88 WS-EMP-RETIRED VALUE 'R'.
88 WS-EMP-UNEMPLOYED VALUE 'U'.
88 WS-EMP-ACTIVE
VALUE 'F' 'P' 'S' 'R'.
88 WS-EMP-VALID-STATUS
VALUE 'F' 'P' 'S' 'R' 'U'.
05 WS-APP-EMPLOYER-NAME PIC X(30).
05 WS-APP-JOB-TITLE PIC X(25).
05 WS-APP-YEARS-EMPLOYED PIC 9(02).
05 WS-APP-MONTHS-EMPLOYED PIC 9(02).
*--- 4D: Financial Information ---
01 WS-APP-FINANCIAL.
05 WS-APP-GROSS-MONTHLY PIC 9(07)V99.
05 WS-APP-OTHER-INCOME PIC 9(07)V99.
05 WS-APP-TOTAL-INCOME PIC 9(07)V99.
05 WS-APP-MONTHLY-DEBT PIC 9(07)V99.
05 WS-APP-CREDIT-SCORE PIC 9(03).
88 WS-SCORE-EXCELLENT VALUE 740 THRU 850.
88 WS-SCORE-GOOD VALUE 670 THRU 739.
88 WS-SCORE-FAIR VALUE 580 THRU 669.
88 WS-SCORE-POOR VALUE 500 THRU 579.
88 WS-SCORE-VERY-POOR VALUE 300 THRU 499.
88 WS-SCORE-VALID VALUE 300 THRU 850.
05 WS-APP-MCCU-MEMBER PIC X(01).
88 WS-IS-MEMBER VALUE 'Y'.
88 WS-NOT-MEMBER VALUE 'N'.
05 WS-APP-MEMBER-SINCE PIC 9(08).
05 WS-APP-SHARE-BALANCE PIC 9(09)V99.
*--- 4E: Loan Request Details ---
01 WS-APP-LOAN-REQUEST.
05 WS-APP-LOAN-TYPE PIC X(02).
88 WS-LOAN-PERSONAL VALUE 'PL'.
88 WS-LOAN-AUTO-NEW VALUE 'AN'.
88 WS-LOAN-AUTO-USED VALUE 'AU'.
88 WS-LOAN-HOME-EQUITY VALUE 'HE'.
88 WS-LOAN-SHARE-SECURED VALUE 'SS'.
88 WS-LOAN-TYPE-VALID
VALUE 'PL' 'AN' 'AU' 'HE' 'SS'.
05 WS-APP-LOAN-AMOUNT PIC 9(07)V99.
05 WS-APP-LOAN-TERM PIC 9(03).
05 WS-APP-LOAN-PURPOSE PIC X(30).
05 WS-APP-COLLATERAL-VAL PIC 9(09)V99.
05 WS-APP-COLLATERAL-DESC PIC X(40).
*================================================================*
* SECTION 5: CALCULATION WORK FIELDS *
*================================================================*
01 WS-WK-CALC-FIELDS.
05 WS-WK-DTI-RATIO PIC 9(01)V9(04) VALUE ZERO.
05 WS-WK-NEW-PAYMENT PIC 9(07)V99 VALUE ZERO.
05 WS-WK-TOTAL-DEBT PIC 9(07)V99 VALUE ZERO.
05 WS-WK-LTV-RATIO PIC 9(01)V9(04) VALUE ZERO.
05 WS-WK-MONTHLY-RATE PIC 9(01)V9(08) VALUE ZERO.
05 WS-WK-NUM-PAYMENTS PIC 9(03) VALUE ZERO.
05 WS-WK-POWER-FACTOR PIC 9(05)V9(10) VALUE ZERO.
05 WS-WK-TEMP-CALC PIC 9(09)V9(06) VALUE ZERO.
05 WS-WK-RISK-POINTS PIC 9(04) VALUE ZERO.
05 WS-WK-INTEREST-RATE PIC 9(02)V9(04) VALUE ZERO.
05 WS-WK-APPLICANT-AGE PIC 9(03) VALUE ZERO.
*--- Risk tier determination ---
01 WS-WK-RISK-TIER PIC X(01) VALUE SPACE.
88 WS-RISK-TIER-A VALUE 'A'.
88 WS-RISK-TIER-B VALUE 'B'.
88 WS-RISK-TIER-C VALUE 'C'.
88 WS-RISK-TIER-D VALUE 'D'.
88 WS-RISK-TIER-F VALUE 'F'.
88 WS-RISK-ACCEPTABLE
VALUE 'A' 'B' 'C'.
*--- Error message accumulation ---
01 WS-WK-ERROR-TABLE.
05 WS-WK-ERROR-COUNT PIC 9(02) VALUE ZERO.
05 WS-WK-ERROR-ENTRY OCCURS 15 TIMES.
10 WS-WK-ERR-CODE PIC X(04).
10 WS-WK-ERR-DESC PIC X(50).
*================================================================*
* SECTION 6: DECISION RESULT FIELDS *
*================================================================*
01 WS-DECISION-RESULT.
05 WS-DEC-STATUS PIC X(01) VALUE SPACE.
88 WS-DEC-APPROVED VALUE 'A'.
88 WS-DEC-COND-APPROVED VALUE 'C'.
88 WS-DEC-DENIED VALUE 'D'.
88 WS-DEC-REFERRED VALUE 'R'.
88 WS-DEC-PENDING VALUE 'P'.
05 WS-DEC-REASON-CODE PIC X(04) VALUE SPACES.
05 WS-DEC-REASON-DESC PIC X(50) VALUE SPACES.
05 WS-DEC-APPROVED-AMT PIC 9(07)V99 VALUE ZERO.
05 WS-DEC-APPROVED-RATE PIC 9(02)V9(04) VALUE ZERO.
05 WS-DEC-APPROVED-TERM PIC 9(03) VALUE ZERO.
05 WS-DEC-MONTHLY-PMT PIC 9(07)V99 VALUE ZERO.
05 WS-DEC-CONDITIONS PIC X(60) VALUE SPACES.
05 WS-DEC-OFFICER-ID PIC X(06) VALUE SPACES.
*================================================================*
* SECTION 7: DISPLAY AND REPORT FIELDS *
*================================================================*
01 WS-DSP-HEADER-LINE.
05 FILLER PIC X(05) VALUE SPACES.
05 FILLER PIC X(30)
VALUE 'LOAN APPLICATION DECISION RPT'.
05 FILLER PIC X(10) VALUE SPACES.
05 WS-DSP-RUN-DATE PIC X(10) VALUE SPACES.
01 WS-DSP-DETAIL-LINE.
05 FILLER PIC X(02) VALUE SPACES.
05 WS-DSP-APP-ID PIC X(12).
05 FILLER PIC X(02) VALUE SPACES.
05 WS-DSP-APP-NAME PIC X(30).
05 FILLER PIC X(02) VALUE SPACES.
05 WS-DSP-LOAN-TYPE PIC X(10).
05 FILLER PIC X(02) VALUE SPACES.
05 WS-DSP-AMOUNT PIC $$$,$$$, MATH1 $,$$$,$$9.99.
01 WS-DSP-FORMATTED-PCT PIC Z9.99.
01 WS-DSP-FORMATTED-COUNT PIC Z,ZZ9.
*--- Current date fields ---
01 WS-CURRENT-DATE-DATA.
05 WS-CURRENT-DATE.
10 WS-CURRENT-YEAR PIC 9(04).
10 WS-CURRENT-MONTH PIC 9(02).
10 WS-CURRENT-DAY PIC 9(02).
05 WS-CURRENT-TIME.
10 WS-CURRENT-HOUR PIC 9(02).
10 WS-CURRENT-MIN PIC 9(02).
10 WS-CURRENT-SEC PIC 9(02).
10 WS-CURRENT-HUND PIC 9(02).
05 WS-GMT-OFFSET PIC S9(04).
*--- Test data counter ---
01 WS-TEST-APP-NUMBER PIC 9(01) VALUE ZERO.
PROCEDURE DIVISION.
0000-MAIN-CONTROL.
PERFORM 1000-INITIALIZATION
PERFORM 2000-PROCESS-APPLICATIONS
PERFORM 3000-PRINT-SUMMARY
STOP RUN
.
*================================================================*
* 1000-INITIALIZATION: Set up working fields and date *
*================================================================*
1000-INITIALIZATION.
MOVE FUNCTION CURRENT-DATE TO WS-CURRENT-DATE-DATA
STRING WS-CURRENT-MONTH DELIMITED BY SIZE
'/' DELIMITED BY SIZE
WS-CURRENT-DAY DELIMITED BY SIZE
'/' DELIMITED BY SIZE
WS-CURRENT-YEAR DELIMITED BY SIZE
INTO WS-DSP-RUN-DATE
END-STRING
DISPLAY WS-C-REPORT-SEP
DISPLAY WS-DSP-HEADER-LINE
DISPLAY WS-C-REPORT-SEP
DISPLAY SPACES
.
*================================================================*
* 2000-PROCESS-APPLICATIONS: Process each test application *
*================================================================*
2000-PROCESS-APPLICATIONS.
PERFORM 2100-LOAD-APPLICATION-1
PERFORM 2500-EVALUATE-APPLICATION
PERFORM 2800-DISPLAY-RESULT
PERFORM 2100-LOAD-APPLICATION-2
PERFORM 2500-EVALUATE-APPLICATION
PERFORM 2800-DISPLAY-RESULT
PERFORM 2100-LOAD-APPLICATION-3
PERFORM 2500-EVALUATE-APPLICATION
PERFORM 2800-DISPLAY-RESULT
.
*================================================================*
* 2100-LOAD-APPLICATION-1: Strong applicant, personal loan *
*================================================================*
2100-LOAD-APPLICATION-1.
PERFORM 2050-CLEAR-APPLICATION
ADD 1 TO WS-CTR-TOTAL-READ
MOVE 'APP-20240301' TO WS-APP-ID
MOVE 20240301 TO WS-APP-DATE
MOVE 'BR01' TO WS-APP-BRANCH
SET WS-CHANNEL-BRANCH TO TRUE
MOVE 'MARGARET' TO WS-APP-FIRST-NAME
MOVE 'A' TO WS-APP-MIDDLE-INIT
MOVE 'THOMPSON' TO WS-APP-LAST-NAME
MOVE '555123456' TO WS-APP-SSN
MOVE 19820415 TO WS-APP-DOB
SET WS-EMP-FULL-TIME TO TRUE
MOVE 'FIRST NATIONAL BANK' TO WS-APP-EMPLOYER-NAME
MOVE 'BRANCH MANAGER' TO WS-APP-JOB-TITLE
MOVE 08 TO WS-APP-YEARS-EMPLOYED
MOVE 03 TO WS-APP-MONTHS-EMPLOYED
MOVE 6500.00 TO WS-APP-GROSS-MONTHLY
MOVE 0500.00 TO WS-APP-OTHER-INCOME
MOVE 7000.00 TO WS-APP-TOTAL-INCOME
MOVE 1200.00 TO WS-APP-MONTHLY-DEBT
MOVE 762 TO WS-APP-CREDIT-SCORE
SET WS-IS-MEMBER TO TRUE
MOVE 20160901 TO WS-APP-MEMBER-SINCE
MOVE 12500.00 TO WS-APP-SHARE-BALANCE
SET WS-LOAN-PERSONAL TO TRUE
MOVE 15000.00 TO WS-APP-LOAN-AMOUNT
MOVE 048 TO WS-APP-LOAN-TERM
MOVE 'HOME IMPROVEMENT' TO WS-APP-LOAN-PURPOSE
MOVE ZERO TO WS-APP-COLLATERAL-VAL
MOVE SPACES TO WS-APP-COLLATERAL-DESC
ADD 1 TO WS-CTR-PERSONAL
.
*================================================================*
* Load application 2: Risky applicant, auto loan *
*================================================================*
2100-LOAD-APPLICATION-2.
PERFORM 2050-CLEAR-APPLICATION
ADD 1 TO WS-CTR-TOTAL-READ
MOVE 'APP-20240302' TO WS-APP-ID
MOVE 20240301 TO WS-APP-DATE
MOVE 'BR03' TO WS-APP-BRANCH
SET WS-CHANNEL-ONLINE TO TRUE
MOVE 'DAVID' TO WS-APP-FIRST-NAME
MOVE 'R' TO WS-APP-MIDDLE-INIT
MOVE 'KELLEY' TO WS-APP-LAST-NAME
MOVE '555987654' TO WS-APP-SSN
MOVE 19950822 TO WS-APP-DOB
SET WS-EMP-PART-TIME TO TRUE
MOVE 'RIVERSIDE GROCERY' TO WS-APP-EMPLOYER-NAME
MOVE 'STOCK CLERK' TO WS-APP-JOB-TITLE
MOVE 01 TO WS-APP-YEARS-EMPLOYED
MOVE 04 TO WS-APP-MONTHS-EMPLOYED
MOVE 2200.00 TO WS-APP-GROSS-MONTHLY
MOVE 0000.00 TO WS-APP-OTHER-INCOME
MOVE 2200.00 TO WS-APP-TOTAL-INCOME
MOVE 1100.00 TO WS-APP-MONTHLY-DEBT
MOVE 548 TO WS-APP-CREDIT-SCORE
SET WS-IS-MEMBER TO TRUE
MOVE 20230601 TO WS-APP-MEMBER-SINCE
MOVE 00800.00 TO WS-APP-SHARE-BALANCE
SET WS-LOAN-AUTO-NEW TO TRUE
MOVE 32000.00 TO WS-APP-LOAN-AMOUNT
MOVE 072 TO WS-APP-LOAN-TERM
MOVE 'NEW VEHICLE PURCHASE' TO WS-APP-LOAN-PURPOSE
MOVE 28000.00 TO WS-APP-COLLATERAL-VAL
MOVE '2024 HONDA CIVIC' TO WS-APP-COLLATERAL-DESC
ADD 1 TO WS-CTR-AUTO-NEW
.
*================================================================*
* Load application 3: Moderate applicant, home equity *
*================================================================*
2100-LOAD-APPLICATION-3.
PERFORM 2050-CLEAR-APPLICATION
ADD 1 TO WS-CTR-TOTAL-READ
MOVE 'APP-20240303' TO WS-APP-ID
MOVE 20240301 TO WS-APP-DATE
MOVE 'BR02' TO WS-APP-BRANCH
SET WS-CHANNEL-BRANCH TO TRUE
MOVE 'SUSAN' TO WS-APP-FIRST-NAME
MOVE 'L' TO WS-APP-MIDDLE-INIT
MOVE 'MARTINEZ' TO WS-APP-LAST-NAME
MOVE '555456789' TO WS-APP-SSN
MOVE 19750930 TO WS-APP-DOB
SET WS-EMP-FULL-TIME TO TRUE
MOVE 'COUNTY SCHOOL DIST' TO WS-APP-EMPLOYER-NAME
MOVE 'TEACHER' TO WS-APP-JOB-TITLE
MOVE 15 TO WS-APP-YEARS-EMPLOYED
MOVE 00 TO WS-APP-MONTHS-EMPLOYED
MOVE 5200.00 TO WS-APP-GROSS-MONTHLY
MOVE 0300.00 TO WS-APP-OTHER-INCOME
MOVE 5500.00 TO WS-APP-TOTAL-INCOME
MOVE 1850.00 TO WS-APP-MONTHLY-DEBT
MOVE 698 TO WS-APP-CREDIT-SCORE
SET WS-IS-MEMBER TO TRUE
MOVE 20100315 TO WS-APP-MEMBER-SINCE
MOVE 08200.00 TO WS-APP-SHARE-BALANCE
SET WS-LOAN-HOME-EQUITY TO TRUE
MOVE 45000.00 TO WS-APP-LOAN-AMOUNT
MOVE 120 TO WS-APP-LOAN-TERM
MOVE 'KITCHEN RENOVATION' TO WS-APP-LOAN-PURPOSE
MOVE 185000.00 TO WS-APP-COLLATERAL-VAL
MOVE 'PRIMARY RESIDENCE' TO WS-APP-COLLATERAL-DESC
ADD 1 TO WS-CTR-HOME-EQUITY
.
*================================================================*
* 2050-CLEAR-APPLICATION: Reset per-application fields *
*================================================================*
2050-CLEAR-APPLICATION.
INITIALIZE WS-APP-HEADER
INITIALIZE WS-APP-PERSONAL
INITIALIZE WS-APP-EMPLOYMENT
INITIALIZE WS-APP-FINANCIAL
INITIALIZE WS-APP-LOAN-REQUEST
INITIALIZE WS-WK-CALC-FIELDS
INITIALIZE WS-WK-ERROR-TABLE
INITIALIZE WS-DECISION-RESULT
MOVE SPACE TO WS-WK-RISK-TIER
SET WS-APP-IS-VALID TO TRUE
SET WS-CONTINUE-PROCESSING TO TRUE
SET WS-DEC-PENDING TO TRUE
.
*================================================================*
* 2500-EVALUATE-APPLICATION: Run validation and scoring *
*================================================================*
2500-EVALUATE-APPLICATION.
PERFORM 2510-VALIDATE-LOAN-TYPE
IF WS-CONTINUE-PROCESSING
PERFORM 2520-VALIDATE-AMOUNT-TERM
END-IF
IF WS-CONTINUE-PROCESSING
PERFORM 2530-VALIDATE-EMPLOYMENT
END-IF
IF WS-CONTINUE-PROCESSING
PERFORM 2540-CALCULATE-DTI
END-IF
IF WS-CONTINUE-PROCESSING
PERFORM 2550-DETERMINE-RISK-TIER
END-IF
IF WS-CONTINUE-PROCESSING
PERFORM 2560-MAKE-DECISION
END-IF
ADD WS-APP-LOAN-AMOUNT TO WS-ACC-TOTAL-REQUESTED
.
*================================================================*
* 2510-VALIDATE-LOAN-TYPE: Check product type is valid *
*================================================================*
2510-VALIDATE-LOAN-TYPE.
IF NOT WS-LOAN-TYPE-VALID
ADD 1 TO WS-WK-ERROR-COUNT
MOVE 'E001' TO WS-WK-ERR-CODE(WS-WK-ERROR-COUNT)
MOVE 'Invalid loan product type'
TO WS-WK-ERR-DESC(WS-WK-ERROR-COUNT)
SET WS-APP-IS-INVALID TO TRUE
SET WS-STOP-PROCESSING TO TRUE
SET WS-DEC-DENIED TO TRUE
MOVE 'E001' TO WS-DEC-REASON-CODE
MOVE 'Invalid loan type' TO WS-DEC-REASON-DESC
ADD 1 TO WS-CTR-ERRORS
END-IF
.
*================================================================*
* 2520-VALIDATE-AMOUNT-TERM: Check within product limits *
*================================================================*
2520-VALIDATE-AMOUNT-TERM.
EVALUATE TRUE
WHEN WS-LOAN-PERSONAL
IF WS-APP-LOAN-AMOUNT < WS-C-PERS-MIN-AMT
OR WS-APP-LOAN-AMOUNT > WS-C-PERS-MAX-AMT
PERFORM 2525-AMOUNT-OUT-OF-RANGE
END-IF
IF WS-APP-LOAN-TERM < WS-C-PERS-MIN-TERM
OR WS-APP-LOAN-TERM > WS-C-PERS-MAX-TERM
PERFORM 2526-TERM-OUT-OF-RANGE
END-IF
WHEN WS-LOAN-AUTO-NEW
IF WS-APP-LOAN-AMOUNT < WS-C-ANEW-MIN-AMT
OR WS-APP-LOAN-AMOUNT > WS-C-ANEW-MAX-AMT
PERFORM 2525-AMOUNT-OUT-OF-RANGE
END-IF
IF WS-APP-LOAN-TERM < WS-C-ANEW-MIN-TERM
OR WS-APP-LOAN-TERM > WS-C-ANEW-MAX-TERM
PERFORM 2526-TERM-OUT-OF-RANGE
END-IF
WHEN WS-LOAN-AUTO-USED
IF WS-APP-LOAN-AMOUNT < WS-C-AUSD-MIN-AMT
OR WS-APP-LOAN-AMOUNT > WS-C-AUSD-MAX-AMT
PERFORM 2525-AMOUNT-OUT-OF-RANGE
END-IF
IF WS-APP-LOAN-TERM < WS-C-AUSD-MIN-TERM
OR WS-APP-LOAN-TERM > WS-C-AUSD-MAX-TERM
PERFORM 2526-TERM-OUT-OF-RANGE
END-IF
WHEN WS-LOAN-HOME-EQUITY
IF WS-APP-LOAN-AMOUNT < WS-C-HEQL-MIN-AMT
OR WS-APP-LOAN-AMOUNT > WS-C-HEQL-MAX-AMT
PERFORM 2525-AMOUNT-OUT-OF-RANGE
END-IF
IF WS-APP-LOAN-TERM < WS-C-HEQL-MIN-TERM
OR WS-APP-LOAN-TERM > WS-C-HEQL-MAX-TERM
PERFORM 2526-TERM-OUT-OF-RANGE
END-IF
WHEN WS-LOAN-SHARE-SECURED
IF WS-APP-LOAN-AMOUNT < WS-C-SSEC-MIN-AMT
OR WS-APP-LOAN-AMOUNT > WS-C-SSEC-MAX-AMT
PERFORM 2525-AMOUNT-OUT-OF-RANGE
END-IF
IF WS-APP-LOAN-TERM < WS-C-SSEC-MIN-TERM
OR WS-APP-LOAN-TERM > WS-C-SSEC-MAX-TERM
PERFORM 2526-TERM-OUT-OF-RANGE
END-IF
END-EVALUATE
.
2525-AMOUNT-OUT-OF-RANGE.
ADD 1 TO WS-WK-ERROR-COUNT
MOVE 'E002' TO WS-WK-ERR-CODE(WS-WK-ERROR-COUNT)
MOVE 'Loan amount outside product limits'
TO WS-WK-ERR-DESC(WS-WK-ERROR-COUNT)
.
2526-TERM-OUT-OF-RANGE.
ADD 1 TO WS-WK-ERROR-COUNT
MOVE 'E003' TO WS-WK-ERR-CODE(WS-WK-ERROR-COUNT)
MOVE 'Loan term outside product limits'
TO WS-WK-ERR-DESC(WS-WK-ERROR-COUNT)
.
*================================================================*
* 2530-VALIDATE-EMPLOYMENT: Check employment meets criteria *
*================================================================*
2530-VALIDATE-EMPLOYMENT.
IF NOT WS-EMP-VALID-STATUS
ADD 1 TO WS-WK-ERROR-COUNT
MOVE 'E004' TO WS-WK-ERR-CODE(WS-WK-ERROR-COUNT)
MOVE 'Invalid employment status code'
TO WS-WK-ERR-DESC(WS-WK-ERROR-COUNT)
END-IF
IF WS-EMP-UNEMPLOYED
IF NOT WS-LOAN-SHARE-SECURED
ADD 1 TO WS-WK-ERROR-COUNT
MOVE 'E005'
TO WS-WK-ERR-CODE(WS-WK-ERROR-COUNT)
MOVE 'Unemployed: only share-secured eligible'
TO WS-WK-ERR-DESC(WS-WK-ERROR-COUNT)
END-IF
END-IF
IF WS-WK-ERROR-COUNT > 0
SET WS-APP-IS-INVALID TO TRUE
SET WS-STOP-PROCESSING TO TRUE
SET WS-DEC-DENIED TO TRUE
MOVE 'E004' TO WS-DEC-REASON-CODE
MOVE 'Employment criteria not met'
TO WS-DEC-REASON-DESC
ADD 1 TO WS-CTR-ERRORS
END-IF
.
*================================================================*
* 2540-CALCULATE-DTI: Compute debt-to-income ratio *
*================================================================*
2540-CALCULATE-DTI.
IF WS-APP-TOTAL-INCOME > ZERO
COMPUTE WS-WK-DTI-RATIO ROUNDED =
WS-APP-MONTHLY-DEBT / WS-APP-TOTAL-INCOME
ELSE
MOVE 9.9999 TO WS-WK-DTI-RATIO
END-IF
.
*================================================================*
* 2550-DETERMINE-RISK-TIER: Score the applicant *
*================================================================*
2550-DETERMINE-RISK-TIER.
MOVE ZERO TO WS-WK-RISK-POINTS
* Credit score component (0-40 points)
EVALUATE TRUE
WHEN WS-SCORE-EXCELLENT
ADD 40 TO WS-WK-RISK-POINTS
WHEN WS-SCORE-GOOD
ADD 30 TO WS-WK-RISK-POINTS
WHEN WS-SCORE-FAIR
ADD 20 TO WS-WK-RISK-POINTS
WHEN WS-SCORE-POOR
ADD 10 TO WS-WK-RISK-POINTS
WHEN OTHER
ADD 00 TO WS-WK-RISK-POINTS
END-EVALUATE
* DTI ratio component (0-30 points)
EVALUATE TRUE
WHEN WS-WK-DTI-RATIO <= WS-C-DTI-EXCELLENT
ADD 30 TO WS-WK-RISK-POINTS
WHEN WS-WK-DTI-RATIO <= WS-C-DTI-GOOD
ADD 22 TO WS-WK-RISK-POINTS
WHEN WS-WK-DTI-RATIO <= WS-C-DTI-FAIR
ADD 12 TO WS-WK-RISK-POINTS
WHEN WS-WK-DTI-RATIO <= WS-C-DTI-MAX
ADD 05 TO WS-WK-RISK-POINTS
WHEN OTHER
ADD 00 TO WS-WK-RISK-POINTS
END-EVALUATE
* Employment stability component (0-20 points)
IF WS-EMP-FULL-TIME
ADD 10 TO WS-WK-RISK-POINTS
END-IF
IF WS-APP-YEARS-EMPLOYED >= 5
ADD 10 TO WS-WK-RISK-POINTS
ELSE
IF WS-APP-YEARS-EMPLOYED >= 2
ADD 05 TO WS-WK-RISK-POINTS
END-IF
END-IF
* Membership component (0-10 points)
IF WS-IS-MEMBER
ADD 05 TO WS-WK-RISK-POINTS
IF WS-APP-SHARE-BALANCE >= 5000.00
ADD 05 TO WS-WK-RISK-POINTS
END-IF
END-IF
* Assign tier based on total points
EVALUATE TRUE
WHEN WS-WK-RISK-POINTS >= 80
SET WS-RISK-TIER-A TO TRUE
WHEN WS-WK-RISK-POINTS >= 60
SET WS-RISK-TIER-B TO TRUE
WHEN WS-WK-RISK-POINTS >= 40
SET WS-RISK-TIER-C TO TRUE
WHEN WS-WK-RISK-POINTS >= 25
SET WS-RISK-TIER-D TO TRUE
WHEN OTHER
SET WS-RISK-TIER-F TO TRUE
END-EVALUATE
.
*================================================================*
* 2560-MAKE-DECISION: Determine the final lending decision *
*================================================================*
2560-MAKE-DECISION.
EVALUATE TRUE
WHEN WS-RISK-TIER-A
SET WS-DEC-APPROVED TO TRUE
MOVE WS-APP-LOAN-AMOUNT
TO WS-DEC-APPROVED-AMT
MOVE WS-APP-LOAN-TERM
TO WS-DEC-APPROVED-TERM
MOVE 'A001' TO WS-DEC-REASON-CODE
MOVE 'Approved: excellent risk profile'
TO WS-DEC-REASON-DESC
ADD 1 TO WS-CTR-APPROVED
ADD WS-APP-LOAN-AMOUNT
TO WS-ACC-TOTAL-APPROVED
WHEN WS-RISK-TIER-B
SET WS-DEC-APPROVED TO TRUE
MOVE WS-APP-LOAN-AMOUNT
TO WS-DEC-APPROVED-AMT
MOVE WS-APP-LOAN-TERM
TO WS-DEC-APPROVED-TERM
MOVE 'A002' TO WS-DEC-REASON-CODE
MOVE 'Approved: good risk profile'
TO WS-DEC-REASON-DESC
ADD 1 TO WS-CTR-APPROVED
ADD WS-APP-LOAN-AMOUNT
TO WS-ACC-TOTAL-APPROVED
WHEN WS-RISK-TIER-C
SET WS-DEC-COND-APPROVED TO TRUE
MOVE WS-APP-LOAN-AMOUNT
TO WS-DEC-APPROVED-AMT
MOVE WS-APP-LOAN-TERM
TO WS-DEC-APPROVED-TERM
MOVE 'C001' TO WS-DEC-REASON-CODE
MOVE 'Conditional: requires co-signer'
TO WS-DEC-REASON-DESC
MOVE 'CO-SIGNER OR ADDITIONAL COLLATERAL'
TO WS-DEC-CONDITIONS
ADD 1 TO WS-CTR-COND-APPROVED
WHEN WS-RISK-TIER-D
SET WS-DEC-REFERRED TO TRUE
MOVE 'R001' TO WS-DEC-REASON-CODE
MOVE 'Referred: marginal risk, officer review'
TO WS-DEC-REASON-DESC
MOVE 'LO0042' TO WS-DEC-OFFICER-ID
ADD 1 TO WS-CTR-REFERRED
WHEN WS-RISK-TIER-F
SET WS-DEC-DENIED TO TRUE
MOVE 'D001' TO WS-DEC-REASON-CODE
MOVE 'Denied: risk profile below minimum'
TO WS-DEC-REASON-DESC
ADD 1 TO WS-CTR-DENIED
ADD WS-APP-LOAN-AMOUNT
TO WS-ACC-TOTAL-DENIED
END-EVALUATE
.
*================================================================*
* 2800-DISPLAY-RESULT: Show the decision for this application *
*================================================================*
2800-DISPLAY-RESULT.
DISPLAY WS-C-DETAIL-SEP
DISPLAY ' Application: ' WS-APP-ID
DISPLAY ' Applicant: ' WS-APP-FIRST-NAME
' ' WS-APP-LAST-NAME
DISPLAY ' Product: ' WS-APP-LOAN-TYPE
MOVE WS-APP-LOAN-AMOUNT TO WS-DSP-FORMATTED-AMT
DISPLAY ' Amount: ' WS-DSP-FORMATTED-AMT
DISPLAY ' Term: ' WS-APP-LOAN-TERM ' months'
DISPLAY ' Credit Score: ' WS-APP-CREDIT-SCORE
MOVE WS-WK-DTI-RATIO TO WS-DSP-FORMATTED-PCT
DISPLAY ' DTI Ratio: ' WS-DSP-FORMATTED-PCT '%'
DISPLAY ' Risk Points: ' WS-WK-RISK-POINTS
' Tier: ' WS-WK-RISK-TIER
EVALUATE TRUE
WHEN WS-DEC-APPROVED
DISPLAY ' Decision: *** APPROVED ***'
WHEN WS-DEC-COND-APPROVED
DISPLAY ' Decision: CONDITIONALLY APPROVED'
DISPLAY ' Conditions: '
WS-DEC-CONDITIONS
WHEN WS-DEC-DENIED
DISPLAY ' Decision: *** DENIED ***'
WHEN WS-DEC-REFERRED
DISPLAY ' Decision: REFERRED TO OFFICER '
WS-DEC-OFFICER-ID
END-EVALUATE
DISPLAY ' Reason: ' WS-DEC-REASON-DESC
IF WS-WK-ERROR-COUNT > 0
DISPLAY ' Errors Found: ' WS-WK-ERROR-COUNT
END-IF
DISPLAY SPACES
.
*================================================================*
* 3000-PRINT-SUMMARY: Nightly batch processing summary *
*================================================================*
3000-PRINT-SUMMARY.
DISPLAY WS-C-REPORT-SEP
DISPLAY ' NIGHTLY PROCESSING SUMMARY'
DISPLAY WS-C-REPORT-SEP
DISPLAY SPACES
MOVE WS-CTR-TOTAL-READ TO WS-DSP-FORMATTED-COUNT
DISPLAY ' Total Applications: '
WS-DSP-FORMATTED-COUNT
MOVE WS-CTR-APPROVED TO WS-DSP-FORMATTED-COUNT
DISPLAY ' Approved: '
WS-DSP-FORMATTED-COUNT
MOVE WS-CTR-COND-APPROVED TO WS-DSP-FORMATTED-COUNT
DISPLAY ' Conditionally Approved: '
WS-DSP-FORMATTED-COUNT
MOVE WS-CTR-DENIED TO WS-DSP-FORMATTED-COUNT
DISPLAY ' Denied: '
WS-DSP-FORMATTED-COUNT
MOVE WS-CTR-REFERRED TO WS-DSP-FORMATTED-COUNT
DISPLAY ' Referred to Officer: '
WS-DSP-FORMATTED-COUNT
MOVE WS-CTR-ERRORS TO WS-DSP-FORMATTED-COUNT
DISPLAY ' Validation Errors: '
WS-DSP-FORMATTED-COUNT
DISPLAY SPACES
DISPLAY ' BY PRODUCT TYPE:'
MOVE WS-CTR-PERSONAL TO WS-DSP-FORMATTED-COUNT
DISPLAY ' Personal: '
WS-DSP-FORMATTED-COUNT
MOVE WS-CTR-AUTO-NEW TO WS-DSP-FORMATTED-COUNT
DISPLAY ' Auto (New): '
WS-DSP-FORMATTED-COUNT
MOVE WS-CTR-AUTO-USED TO WS-DSP-FORMATTED-COUNT
DISPLAY ' Auto (Used): '
WS-DSP-FORMATTED-COUNT
MOVE WS-CTR-HOME-EQUITY TO WS-DSP-FORMATTED-COUNT
DISPLAY ' Home Equity: '
WS-DSP-FORMATTED-COUNT
MOVE WS-CTR-SHARE-SECURED TO WS-DSP-FORMATTED-COUNT
DISPLAY ' Share Secured: '
WS-DSP-FORMATTED-COUNT
DISPLAY SPACES
MOVE WS-ACC-TOTAL-REQUESTED TO WS-DSP-FORMATTED-AMT
DISPLAY ' Total Requested: ' WS-DSP-FORMATTED-AMT
MOVE WS-ACC-TOTAL-APPROVED TO WS-DSP-FORMATTED-AMT
DISPLAY ' Total Approved: ' WS-DSP-FORMATTED-AMT
MOVE WS-ACC-TOTAL-DENIED TO WS-DSP-FORMATTED-AMT
DISPLAY ' Total Denied: ' WS-DSP-FORMATTED-AMT
DISPLAY SPACES
DISPLAY WS-C-REPORT-SEP
.
Solution Walkthrough
Step 1: Constants as the Foundation
Roberto placed all product limits, thresholds, and scoring boundaries at the top of WORKING-STORAGE. Each loan product has its own 01-level group (WS-C-PERSONAL-LIMITS, WS-C-AUTO-NEW-LIMITS, etc.), making it trivial to locate and modify product parameters. When MCCU later added a sixth loan product -- a small-dollar emergency loan -- Roberto simply added a new WS-C-EMERGENCY-LIMITS group and a new 88-level value under WS-APP-LOAN-TYPE. No existing constant definitions needed modification.
The DTI thresholds and credit score thresholds are similarly isolated. When MCCU's board of directors adjusted the "fair" DTI threshold from 0.43 to 0.40, Roberto changed a single VALUE clause. Every paragraph that tested DTI ranges through the 88-level conditions continued to work without modification.
Step 2: The Application Record as a Group Hierarchy
The loan application data is organized into five logical sub-groups under separate 01-level items: header, personal, employment, financial, and loan request. This design provides several advantages:
-
Selective initialization. The
2050-CLEAR-APPLICATIONparagraph initializes each group individually. If a future enhancement requires preserving the header while resetting the financial details (for example, when the same applicant submits multiple loan requests), Roberto can initialize onlyWS-APP-FINANCIALandWS-APP-LOAN-REQUEST. -
Readable references. Field names like
WS-APP-CREDIT-SCOREandWS-APP-YEARS-EMPLOYEDare immediately meaningful. A maintenance programmer encounteringIF WS-SCORE-EXCELLENTin the PROCEDURE DIVISION can trace it back toWS-APP-CREDIT-SCOREand see the threshold (740 THRU 850) without consulting any external documentation. -
Group-level operations. MCCU later added a feature to write the entire application record to an audit file. Because the groups are cleanly defined, the WRITE statement could reference each 01-level group directly.
Step 3: 88-Level Conditions as Business Language
Roberto's most impactful design decision was the systematic use of 88-level conditions. Every field that participates in any decision has condition names:
- Loan type has individual values (
WS-LOAN-PERSONAL,WS-LOAN-AUTO-NEW) and a composite validation condition (WS-LOAN-TYPE-VALID). - Employment status has individual values, a composite "actively employed" condition (
WS-EMP-ACTIVE), and a validation condition (WS-EMP-VALID-STATUS). - Credit score has range-based conditions using THRU that exactly match MCCU's credit policy tiers.
- Decision status has conditions for each possible outcome, enabling EVALUATE TRUE in the display logic.
- Risk tier has both individual tiers and a composite "acceptable risk" condition (
WS-RISK-ACCEPTABLE).
The composite conditions deserve special attention. WS-EMP-ACTIVE combines full-time, part-time, self-employed, and retired into a single condition. This means the business rule "applicant must be actively employed" can be tested with IF WS-EMP-ACTIVE instead of enumerating four codes. When MCCU later added a "contract worker" employment status ('C'), the developer added the value to WS-EMP-ACTIVE and WS-EMP-VALID-STATUS, and every reference to those conditions in the PROCEDURE DIVISION automatically included the new status.
Step 4: The Error Table for Multi-Error Reporting
The error message table (WS-WK-ERROR-TABLE) uses OCCURS to allow accumulating up to 15 errors per application. This is critical for user experience: rather than rejecting an application on the first error and forcing the applicant to resubmit repeatedly, the system collects all validation failures and reports them together. The branch teller or online form can display all issues at once.
Step 5: The Reset Strategy
The 2050-CLEAR-APPLICATION paragraph demonstrates a crucial design decision: which fields to reset between applications and which to preserve. The application data, calculation fields, error table, and decision result are all initialized. The counters, accumulators, and program constants are never initialized -- they must persist across all applications in the batch run.
Roberto uses INITIALIZE rather than MOVE SPACES or MOVE ZEROS because the application record contains both alphanumeric and numeric fields. INITIALIZE correctly sets alphanumeric fields to SPACES and numeric fields to ZEROS, while MOVE SPACES would corrupt the numeric fields.
Lessons Learned
1. REDEFINES for Date Flexibility
Roberto defined the application date as a numeric field (PIC 9(08)) with a REDEFINES that breaks it into year, month, and day components. This allows the program to store the date as a single value (for sorting and comparison) while also accessing individual components (for age calculation, month-end processing, and display formatting). This dual-access pattern appears throughout production COBOL systems wherever dates are used.
2. The "Valid" Composite Condition
Adding a composite 88-level condition that combines all valid values for a field (like WS-LOAN-TYPE-VALID and WS-EMP-VALID-STATUS) is a simple practice that dramatically simplifies validation logic. Instead of testing each valid value individually, one condition check handles them all. When new valid values are added, only the composite condition and the individual condition definitions need updating.
3. Separating Calculation Fields from Application Data
Roberto placed all calculation work fields in their own group (WS-WK-CALC-FIELDS), separate from the application data. This separation means the calculation fields can be initialized without disturbing the application record, and the application record can be written to an audit file without including intermediate calculation artifacts.
4. Display Fields Sized for Formatting
The display fields (WS-DSP-FORMATTED-AMT, WS-DSP-FORMATTED-PCT, WS-DSP-FORMATTED-COUNT) are defined with numeric-edited PIC clauses that include currency signs, commas, and decimal points. Roberto sized these fields to accommodate the maximum values from the corresponding work fields. A common mistake is under-sizing display fields, which causes asterisk overflow in reports -- a defect that is embarrassing but not always caught in testing.
5. Risk Scoring Through WORKING-STORAGE Design
The risk tier determination uses a point-based scoring system where points are accumulated in WS-WK-RISK-POINTS and then mapped to a risk tier through EVALUATE. This design makes the scoring model transparent and auditable. When MCCU's compliance team asked to review the scoring criteria, Roberto could walk them through the WORKING-STORAGE definitions and the scoring paragraph in a single meeting. The thresholds were all visible as VALUE clauses, and the point assignments were clear in the EVALUATE structure.
Discussion Questions
-
Roberto defined five separate 01-level groups for the product limits. An alternative design would be a single table with OCCURS 5 TIMES, indexed by product type. What are the advantages and disadvantages of each approach? When would the table approach be preferable?
-
The error table uses OCCURS 15 TIMES. How would you determine the right number of entries? What happens if the application has more than 15 errors? How would you handle this in the PROCEDURE DIVISION?
-
The composite 88-level condition
WS-EMP-ACTIVEincludes retired status. A business analyst argues that retired applicants should be handled differently from actively employed ones. How would you restructure the 88-level conditions to accommodate this change while minimizing impact on existing code? -
Roberto uses INITIALIZE for clearing application fields between records. What would happen if he used
MOVE SPACES TO WS-APP-FINANCIALinstead? How would the resulting data corruption manifest during processing? -
The risk scoring model assigns up to 100 points across four categories. If MCCU wanted to add a fifth category (asset verification, worth up to 15 points), what WORKING-STORAGE changes would be needed? What PROCEDURE DIVISION changes would be needed? How does the separation of constants from logic help with this kind of enhancement?
-
Examine the REDEFINES on
WS-APP-DATE. If you needed to display the date as "March 15, 2024" rather than "20240315", what additional WORKING-STORAGE items would you define? Would you use REDEFINES, a separate display field, or both?