Case Study 1: Multi-Screen Account Management Application

[IBM Enterprise COBOL]

Background

Cornerstone National Bank is replacing its aging green-screen account management system with a modernized CICS application. The existing system consists of twelve separate CICS transactions, each with its own program, that were developed independently over two decades. Tellers must memorize twelve different transaction codes, navigate inconsistent screen layouts, and manually re-enter customer information when moving between functions. A task that should take thirty seconds -- looking up a customer, viewing their account, and posting a deposit -- requires three separate transactions and nearly two minutes of key entry.

The replacement application consolidates the most common teller operations into a single, menu-driven CICS application with seamless navigation between screens. The new application uses a single transaction code (ACMG) and manages all screen flow internally using COMMAREA-based state management, XCTL for screen-to-screen navigation, and TS queues for browse list support.

This case study walks through the complete design and implementation of the four-screen application: a main menu, an account inquiry screen, a transaction entry screen, and a confirmation screen.


Problem Statement

The application must support the following workflow:

  1. Main Menu -- The teller enters a customer account number and selects an action: Inquiry, Deposit, Withdrawal, or Transfer.
  2. Account Inquiry -- Displays the account details including customer name, account type, balances, and the last ten transactions. Supports PF7/PF8 paging through the transaction history.
  3. Transaction Entry -- Allows the teller to enter a deposit, withdrawal, or transfer amount. Validates the amount against business rules (minimum deposit, sufficient funds for withdrawals, valid target account for transfers).
  4. Confirmation -- Displays a summary of the pending transaction and asks the teller to confirm or cancel. Upon confirmation, the transaction is posted and a receipt reference number is generated.

Navigation rules: - PF3 from any screen returns to the previous screen - PF12 from any screen returns to the main menu - ENTER processes the current screen's action - Clear key ends the transaction


Application Architecture

Screen Flow

                    +-------------------+
                    |    MAIN MENU      |
                    |  (ACMGMENU map)   |
                    +--------+----------+
                             |
              +--------------+--------------+
              |                             |
     +--------v---------+        +---------v--------+
     | ACCOUNT INQUIRY  |        | TRANSACTION ENTRY|
     | (ACMGINQ map)    |        | (ACMGTXN map)    |
     +--------+---------+        +---------+--------+
              |                             |
              |  PF7/PF8: page              |  ENTER: validate
              |  through TSQ                |
              |                    +--------v--------+
              |                    |  CONFIRMATION   |
              |                    |  (ACMGCNF map)  |
              |                    +-----------------+

COMMAREA Design

The COMMAREA carries all state information between pseudo-conversational interactions:

       01  WS-COMMAREA.
      *    Header section
           05  CA-VERSION              PIC 9(02) VALUE 01.
           05  CA-EYE-CATCHER         PIC X(08) VALUE 'ACMGCA  '.
      *    Navigation state
           05  CA-CURRENT-SCREEN       PIC X(04).
               88  CA-MENU-SCREEN          VALUE 'MENU'.
               88  CA-INQ-SCREEN           VALUE 'INQY'.
               88  CA-TXN-SCREEN           VALUE 'TXNE'.
               88  CA-CNF-SCREEN           VALUE 'CONF'.
           05  CA-PREV-SCREEN          PIC X(04).
           05  CA-ACTION-CODE          PIC X(01).
               88  CA-ACTION-INQUIRY       VALUE 'I'.
               88  CA-ACTION-DEPOSIT       VALUE 'D'.
               88  CA-ACTION-WITHDRAWAL    VALUE 'W'.
               88  CA-ACTION-TRANSFER      VALUE 'T'.
      *    Account context
           05  CA-ACCOUNT-NUM          PIC X(12).
           05  CA-CUST-NAME            PIC X(30).
           05  CA-ACCT-TYPE            PIC X(02).
           05  CA-CURRENT-BAL          PIC S9(11)V99 COMP-3.
           05  CA-AVAIL-BAL            PIC S9(11)V99 COMP-3.
      *    Transaction context
           05  CA-TXN-AMOUNT           PIC S9(09)V99 COMP-3.
           05  CA-TXN-TARGET-ACCT      PIC X(12).
           05  CA-TXN-REF-NUM          PIC X(16).
           05  CA-TXN-TIMESTAMP        PIC X(26).
      *    Browse state (for inquiry paging)
           05  CA-TSQ-NAME             PIC X(08).
           05  CA-TSQ-TOTAL-ITEMS      PIC 9(05) VALUE 0.
           05  CA-CURRENT-PAGE         PIC 9(03) VALUE 1.
           05  CA-PAGE-SIZE            PIC 9(02) VALUE 10.
      *    Error message
           05  CA-MESSAGE              PIC X(79).
      *    Filler for expansion
           05  CA-FILLER               PIC X(50).

The COMMAREA is 300 bytes -- well within the 32,763-byte COMMAREA limit. The version field and eye-catcher support future upgrades. The navigation state fields (CA-CURRENT-SCREEN, CA-PREV-SCREEN) implement the state machine that controls screen flow.


BMS Map Definitions

ACMGMMS  DFHMSD TYPE=MAP,MODE=INOUT,LANG=COBOL,TIOAPFX=YES,      X
               STORAGE=AUTO,CTRL=(FREEKB,FRSET)
ACMGMENU DFHMDI SIZE=(24,80),LINE=1,COLUMN=1
         DFHMDF POS=(01,01),LENGTH=79,                              X
               ATTRB=(ASKIP,BRT),                                   X
               INITIAL='CORNERSTONE NATIONAL BANK - ACCOUNT MANAGEMEX
               NT'
         DFHMDF POS=(02,01),LENGTH=79,ATTRB=(ASKIP),               X
               INITIAL='-----------------------------------------------X
               --------------------------------'
         DFHMDF POS=(04,03),LENGTH=15,ATTRB=(ASKIP),               X
               INITIAL='Account Number:'
ACCTNO   DFHMDF POS=(04,19),LENGTH=12,ATTRB=(UNPROT,BRT,IC,FSET)
         DFHMDF POS=(04,32),LENGTH=1,ATTRB=(ASKIP)
         DFHMDF POS=(06,03),LENGTH=25,ATTRB=(ASKIP),               X
               INITIAL='Select Action:'
         DFHMDF POS=(08,05),LENGTH=30,ATTRB=(ASKIP),               X
               INITIAL='1. Account Inquiry'
         DFHMDF POS=(09,05),LENGTH=30,ATTRB=(ASKIP),               X
               INITIAL='2. Deposit'
         DFHMDF POS=(10,05),LENGTH=30,ATTRB=(ASKIP),               X
               INITIAL='3. Withdrawal'
         DFHMDF POS=(11,05),LENGTH=30,ATTRB=(ASKIP),               X
               INITIAL='4. Transfer'
         DFHMDF POS=(13,03),LENGTH=10,ATTRB=(ASKIP),               X
               INITIAL='Selection:'
ACTION   DFHMDF POS=(13,14),LENGTH=1,ATTRB=(UNPROT,BRT,FSET)
         DFHMDF POS=(13,16),LENGTH=1,ATTRB=(ASKIP)
         DFHMDF POS=(22,01),LENGTH=79,ATTRB=(ASKIP),               X
               INITIAL='PF3=Exit  ENTER=Submit'
MSGFLD   DFHMDF POS=(23,01),LENGTH=79,ATTRB=(ASKIP,BRT)
         DFHMDF POS=(24,01),LENGTH=79,ATTRB=(ASKIP),               X
               INITIAL='ACMG V1.0   Cornerstone National Bank'
         DFHMSD TYPE=FINAL
         END

Account Inquiry Map

The inquiry map displays account details and a scrollable transaction list:

ACMGIMS  DFHMSD TYPE=MAP,MODE=INOUT,LANG=COBOL,TIOAPFX=YES,      X
               STORAGE=AUTO,CTRL=(FREEKB,FRSET)
ACMGINQ  DFHMDI SIZE=(24,80),LINE=1,COLUMN=1
         DFHMDF POS=(01,01),LENGTH=40,ATTRB=(ASKIP,BRT),           X
               INITIAL='ACCOUNT INQUIRY'
IACCTNO  DFHMDF POS=(01,50),LENGTH=12,ATTRB=(ASKIP)
         DFHMDF POS=(03,03),LENGTH=12,ATTRB=(ASKIP),               X
               INITIAL='Customer:'
ICNAME   DFHMDF POS=(03,16),LENGTH=30,ATTRB=(ASKIP)
         DFHMDF POS=(04,03),LENGTH=12,ATTRB=(ASKIP),               X
               INITIAL='Acct Type:'
IACTYPE  DFHMDF POS=(04,16),LENGTH=15,ATTRB=(ASKIP)
         DFHMDF POS=(05,03),LENGTH=12,ATTRB=(ASKIP),               X
               INITIAL='Status:'
IASTATUS DFHMDF POS=(05,16),LENGTH=10,ATTRB=(ASKIP)
         DFHMDF POS=(06,03),LENGTH=15,ATTRB=(ASKIP),               X
               INITIAL='Current Bal:'
ICURBAL  DFHMDF POS=(06,19),LENGTH=16,ATTRB=(ASKIP)
         DFHMDF POS=(07,03),LENGTH=15,ATTRB=(ASKIP),               X
               INITIAL='Available Bal:'
IAVLBAL  DFHMDF POS=(07,19),LENGTH=16,ATTRB=(ASKIP)
         DFHMDF POS=(09,01),LENGTH=79,ATTRB=(ASKIP),               X
               INITIAL='--- RECENT TRANSACTIONS -----------------------X
               --'
         DFHMDF POS=(10,01),LENGTH=79,ATTRB=(ASKIP),               X
               INITIAL='Date       Type   Amount           Description'
* Transaction lines (10 rows)
TDATE1   DFHMDF POS=(11,01),LENGTH=10,ATTRB=(ASKIP)
TTYPE1   DFHMDF POS=(11,12),LENGTH=06,ATTRB=(ASKIP)
TAMNT1   DFHMDF POS=(11,19),LENGTH=16,ATTRB=(ASKIP)
TDESC1   DFHMDF POS=(11,36),LENGTH=40,ATTRB=(ASKIP)
* (Lines 2-10 follow the same pattern at POS rows 12-20)
TDATE2   DFHMDF POS=(12,01),LENGTH=10,ATTRB=(ASKIP)
TTYPE2   DFHMDF POS=(12,12),LENGTH=06,ATTRB=(ASKIP)
TAMNT2   DFHMDF POS=(12,19),LENGTH=16,ATTRB=(ASKIP)
TDESC2   DFHMDF POS=(12,36),LENGTH=40,ATTRB=(ASKIP)
TDATE3   DFHMDF POS=(13,01),LENGTH=10,ATTRB=(ASKIP)
TTYPE3   DFHMDF POS=(13,12),LENGTH=06,ATTRB=(ASKIP)
TAMNT3   DFHMDF POS=(13,19),LENGTH=16,ATTRB=(ASKIP)
TDESC3   DFHMDF POS=(13,36),LENGTH=40,ATTRB=(ASKIP)
* ... lines 4-10 omitted for brevity, same pattern ...
         DFHMDF POS=(21,01),LENGTH=40,ATTRB=(ASKIP)
IPAGMSG  DFHMDF POS=(21,45),LENGTH=30,ATTRB=(ASKIP)
         DFHMDF POS=(22,01),LENGTH=79,ATTRB=(ASKIP),               X
               INITIAL='PF3=Menu  PF7=Prev  PF8=Next  ENTER=Refresh'
IMSGFLD  DFHMDF POS=(23,01),LENGTH=79,ATTRB=(ASKIP,BRT)
         DFHMSD TYPE=FINAL
         END

Main Program

       IDENTIFICATION DIVISION.
       PROGRAM-ID. ACMGMAIN.
      *================================================================*
      * CORNERSTONE NATIONAL BANK                                      *
      * ACCOUNT MANAGEMENT - MAIN CONTROLLER PROGRAM                   *
      *                                                                *
      * This program implements a four-screen CICS application         *
      * using pseudo-conversational design with COMMAREA state         *
      * management. It handles:                                        *
      *   - Main Menu (account selection and action choice)            *
      *   - Account Inquiry (with TSQ-based paging)                    *
      *   - Transaction Entry (deposit/withdrawal/transfer)            *
      *   - Confirmation (review and commit)                           *
      *================================================================*

       DATA DIVISION.
       WORKING-STORAGE SECTION.

       01  WS-PROGRAM-ID              PIC X(08) VALUE 'ACMGMAIN'.

      * COMMAREA definition
       01  WS-COMMAREA.
           05  CA-VERSION              PIC 9(02) VALUE 01.
           05  CA-EYE-CATCHER         PIC X(08) VALUE 'ACMGCA  '.
           05  CA-CURRENT-SCREEN       PIC X(04).
               88  CA-MENU-SCREEN          VALUE 'MENU'.
               88  CA-INQ-SCREEN           VALUE 'INQY'.
               88  CA-TXN-SCREEN           VALUE 'TXNE'.
               88  CA-CNF-SCREEN           VALUE 'CONF'.
           05  CA-PREV-SCREEN          PIC X(04).
           05  CA-ACTION-CODE          PIC X(01).
               88  CA-ACTION-INQUIRY       VALUE 'I'.
               88  CA-ACTION-DEPOSIT       VALUE 'D'.
               88  CA-ACTION-WITHDRAWAL    VALUE 'W'.
               88  CA-ACTION-TRANSFER      VALUE 'T'.
           05  CA-ACCOUNT-NUM          PIC X(12).
           05  CA-CUST-NAME            PIC X(30).
           05  CA-ACCT-TYPE            PIC X(02).
           05  CA-CURRENT-BAL          PIC S9(11)V99 COMP-3.
           05  CA-AVAIL-BAL            PIC S9(11)V99 COMP-3.
           05  CA-TXN-AMOUNT           PIC S9(09)V99 COMP-3.
           05  CA-TXN-TARGET-ACCT      PIC X(12).
           05  CA-TXN-REF-NUM          PIC X(16).
           05  CA-TXN-TIMESTAMP        PIC X(26).
           05  CA-TSQ-NAME             PIC X(08).
           05  CA-TSQ-TOTAL-ITEMS      PIC 9(05) VALUE 0.
           05  CA-CURRENT-PAGE         PIC 9(03) VALUE 1.
           05  CA-PAGE-SIZE            PIC 9(02) VALUE 10.
           05  CA-MESSAGE              PIC X(79).
           05  CA-FILLER               PIC X(50).

      * Symbolic map areas (generated by BMS assembly)
      * In production these would be COPY statements
       01  MENU-MAPI.
           05  FILLER                  PIC X(12).
           05  ACCTNO-I                PIC X(12).
           05  ACTION-I                PIC X(01).
       01  MENU-MAPO.
           05  FILLER                  PIC X(12).
           05  ACCTNO-O                PIC X(12).
           05  ACTION-O                PIC X(01).
           05  MSGFLD-O                PIC X(79).

      * DB2 host variables
       01  WS-DB2-FIELDS.
           05  WS-DB-ACCT-NUM         PIC X(12).
           05  WS-DB-CUST-NAME        PIC X(30).
           05  WS-DB-ACCT-TYPE        PIC X(02).
           05  WS-DB-STATUS            PIC X(01).
           05  WS-DB-CURRENT-BAL       PIC S9(11)V99 COMP-3.
           05  WS-DB-AVAIL-BAL         PIC S9(11)V99 COMP-3.

      * TSQ record for transaction history
       01  WS-TSQ-RECORD.
           05  WS-TSQ-DATE            PIC X(10).
           05  WS-TSQ-TYPE            PIC X(06).
           05  WS-TSQ-AMOUNT          PIC X(16).
           05  WS-TSQ-DESC            PIC X(40).
       01  WS-TSQ-REC-LEN            PIC S9(04) COMP
                                      VALUE 72.

      * Work fields
       01  WS-RESP                    PIC S9(08) COMP.
       01  WS-RESP2                   PIC S9(08) COMP.
       01  WS-CA-LENGTH               PIC S9(04) COMP.
       01  WS-MAP-LENGTH              PIC S9(04) COMP.
       01  WS-TSQ-ITEM                PIC S9(04) COMP.
       01  WS-START-ITEM              PIC 9(05).
       01  WS-LINE-IDX                PIC 9(02).
       01  WS-TOTAL-PAGES             PIC 9(03).
       01  WS-PAGE-MSG                PIC X(30).
       01  WS-FMT-BAL                 PIC -(11)9.99.
       01  WS-FMT-AMT                 PIC -(9)9.99.
       01  WS-AID-KEY                 PIC X(01).

       01  WS-ABSTIME                 PIC S9(15) COMP-3.
       01  WS-FORMATTED-TIME          PIC X(26).

       COPY DFHAID.
       COPY DFHBMSCA.

       LINKAGE SECTION.
       01  DFHCOMMAREA                PIC X(300).

       PROCEDURE DIVISION.
       0000-MAIN-CONTROL.
      *    Determine if this is first entry or a return
           IF EIBCALEN = ZERO
               PERFORM 1000-FIRST-TIME-ENTRY
           ELSE
               MOVE DFHCOMMAREA TO WS-COMMAREA
               MOVE EIBAID TO WS-AID-KEY
               PERFORM 0100-ROUTE-BY-STATE
           END-IF

           EXEC CICS RETURN
               TRANSID('ACMG')
               COMMAREA(WS-COMMAREA)
               LENGTH(LENGTH OF WS-COMMAREA)
           END-EXEC.

       0100-ROUTE-BY-STATE.
      *    Handle CLEAR key globally -- end transaction
           IF WS-AID-KEY = DFHCLEAR
               PERFORM 0200-CLEANUP-AND-EXIT
           END-IF

      *    Handle PF12 globally -- return to menu
           IF WS-AID-KEY = DFHPF12
               PERFORM 1000-FIRST-TIME-ENTRY
           ELSE
      *        Route based on current screen state
               EVALUATE TRUE
                   WHEN CA-MENU-SCREEN
                       PERFORM 2000-PROCESS-MENU
                   WHEN CA-INQ-SCREEN
                       PERFORM 3000-PROCESS-INQUIRY
                   WHEN CA-TXN-SCREEN
                       PERFORM 4000-PROCESS-TRANSACTION
                   WHEN CA-CNF-SCREEN
                       PERFORM 5000-PROCESS-CONFIRMATION
                   WHEN OTHER
                       PERFORM 1000-FIRST-TIME-ENTRY
               END-EVALUATE
           END-IF.

       0200-CLEANUP-AND-EXIT.
      *    Delete TSQ if it exists
           IF CA-TSQ-NAME NOT = SPACES
               EXEC CICS DELETEQ TS
                   QUEUE(CA-TSQ-NAME)
                   RESP(WS-RESP)
               END-EXEC
           END-IF
           EXEC CICS SEND CONTROL
               ERASE
               FREEKB
           END-EXEC
           EXEC CICS RETURN
           END-EXEC.

      *================================================================*
      * 1000 - FIRST TIME ENTRY: DISPLAY MAIN MENU                    *
      *================================================================*
       1000-FIRST-TIME-ENTRY.
           INITIALIZE WS-COMMAREA
           MOVE 01       TO CA-VERSION
           MOVE 'ACMGCA  ' TO CA-EYE-CATCHER
           MOVE 'MENU'   TO CA-CURRENT-SCREEN
           MOVE SPACES   TO CA-MESSAGE

           EXEC CICS SEND
               MAP('ACMGMENU')
               MAPSET('ACMGMMS')
               ERASE
               RESP(WS-RESP)
           END-EXEC

           IF WS-RESP NOT = DFHRESP(NORMAL)
               PERFORM 9000-SEND-ERROR
           END-IF.

      *================================================================*
      * 2000 - PROCESS MENU SCREEN INPUT                               *
      *================================================================*
       2000-PROCESS-MENU.
      *    Receive the menu map
           EXEC CICS RECEIVE
               MAP('ACMGMENU')
               MAPSET('ACMGMMS')
               INTO(MENU-MAPI)
               RESP(WS-RESP)
           END-EXEC

           IF WS-RESP NOT = DFHRESP(NORMAL)
               MOVE 'Error receiving menu input'
                   TO CA-MESSAGE
               PERFORM 1000-FIRST-TIME-ENTRY
           ELSE
      *        Validate account number
               IF ACCTNO-I = SPACES OR ACCTNO-I = LOW-VALUES
                   MOVE 'Please enter an account number'
                       TO CA-MESSAGE
                   PERFORM 2900-RESEND-MENU
               ELSE
                   MOVE ACCTNO-I TO CA-ACCOUNT-NUM
      *            Validate action selection
                   EVALUATE ACTION-I
                       WHEN '1'
                           SET CA-ACTION-INQUIRY TO TRUE
                       WHEN '2'
                           SET CA-ACTION-DEPOSIT TO TRUE
                       WHEN '3'
                           SET CA-ACTION-WITHDRAWAL TO TRUE
                       WHEN '4'
                           SET CA-ACTION-TRANSFER TO TRUE
                       WHEN OTHER
                           MOVE 'Invalid selection. Choose 1-4.'
                               TO CA-MESSAGE
                           PERFORM 2900-RESEND-MENU
                   END-EVALUATE

      *            Look up the account in DB2
                   PERFORM 2100-LOOKUP-ACCOUNT
               END-IF
           END-IF.

       2100-LOOKUP-ACCOUNT.
           MOVE CA-ACCOUNT-NUM TO WS-DB-ACCT-NUM

           EXEC SQL
               SELECT CUST_NAME, ACCT_TYPE, ACCT_STATUS,
                      CURRENT_BAL, AVAILABLE_BAL
               INTO :WS-DB-CUST-NAME,
                    :WS-DB-ACCT-TYPE,
                    :WS-DB-STATUS,
                    :WS-DB-CURRENT-BAL,
                    :WS-DB-AVAIL-BAL
               FROM ACCOUNT_MASTER
               WHERE ACCT_NUMBER = :WS-DB-ACCT-NUM
           END-EXEC

           EVALUATE SQLCODE
               WHEN 0
                   MOVE WS-DB-CUST-NAME TO CA-CUST-NAME
                   MOVE WS-DB-ACCT-TYPE TO CA-ACCT-TYPE
                   MOVE WS-DB-CURRENT-BAL TO CA-CURRENT-BAL
                   MOVE WS-DB-AVAIL-BAL TO CA-AVAIL-BAL
                   EVALUATE TRUE
                       WHEN CA-ACTION-INQUIRY
                           PERFORM 3100-LOAD-HISTORY-TSQ
                           MOVE 'INQY' TO CA-CURRENT-SCREEN
                           MOVE 'MENU' TO CA-PREV-SCREEN
                           PERFORM 3200-SEND-INQUIRY-MAP
                       WHEN CA-ACTION-DEPOSIT
                           OR CA-ACTION-WITHDRAWAL
                           OR CA-ACTION-TRANSFER
                           MOVE 'TXNE' TO CA-CURRENT-SCREEN
                           MOVE 'MENU' TO CA-PREV-SCREEN
                           PERFORM 4100-SEND-TXN-MAP
                   END-EVALUATE
               WHEN +100
                   MOVE 'Account not found. Please verify.'
                       TO CA-MESSAGE
                   PERFORM 2900-RESEND-MENU
               WHEN OTHER
                   STRING 'Database error. SQLCODE='
                       SQLCODE
                       DELIMITED BY SIZE
                       INTO CA-MESSAGE
                   PERFORM 2900-RESEND-MENU
           END-EVALUATE.

       2900-RESEND-MENU.
           MOVE CA-MESSAGE TO MSGFLD-O
           EXEC CICS SEND
               MAP('ACMGMENU')
               MAPSET('ACMGMMS')
               FROM(MENU-MAPO)
               DATAONLY
               RESP(WS-RESP)
           END-EXEC.

      *================================================================*
      * 3000 - PROCESS ACCOUNT INQUIRY (with TSQ paging)              *
      *================================================================*
       3000-PROCESS-INQUIRY.
           IF WS-AID-KEY = DFHPF3
      *        Return to menu
               PERFORM 0300-DELETE-TSQ
               PERFORM 1000-FIRST-TIME-ENTRY
           ELSE IF WS-AID-KEY = DFHPF7
      *        Page backward
               IF CA-CURRENT-PAGE > 1
                   SUBTRACT 1 FROM CA-CURRENT-PAGE
               END-IF
               PERFORM 3200-SEND-INQUIRY-MAP
           ELSE IF WS-AID-KEY = DFHPF8
      *        Page forward
               COMPUTE WS-TOTAL-PAGES =
                   (CA-TSQ-TOTAL-ITEMS + CA-PAGE-SIZE - 1)
                   / CA-PAGE-SIZE
               IF CA-CURRENT-PAGE < WS-TOTAL-PAGES
                   ADD 1 TO CA-CURRENT-PAGE
               END-IF
               PERFORM 3200-SEND-INQUIRY-MAP
           ELSE
      *        ENTER - refresh the display
               PERFORM 3200-SEND-INQUIRY-MAP
           END-IF.

       0300-DELETE-TSQ.
           IF CA-TSQ-NAME NOT = SPACES
               EXEC CICS DELETEQ TS
                   QUEUE(CA-TSQ-NAME)
                   RESP(WS-RESP)
               END-EXEC
               MOVE SPACES TO CA-TSQ-NAME
           END-IF.

       3100-LOAD-HISTORY-TSQ.
      *    Build a unique TSQ name using terminal ID
           STRING 'AH' EIBTRMID
               DELIMITED BY SIZE
               INTO CA-TSQ-NAME

      *    Delete any existing TSQ from a prior session
           EXEC CICS DELETEQ TS
               QUEUE(CA-TSQ-NAME)
               RESP(WS-RESP)
           END-EXEC

      *    Query transaction history from DB2
      *    Write each row to the TSQ for paging support
           MOVE 0 TO CA-TSQ-TOTAL-ITEMS
           MOVE 1 TO CA-CURRENT-PAGE

           EXEC SQL DECLARE HIST_CURSOR CURSOR FOR
               SELECT POST_DATE, TXN_TYPE, TXN_AMOUNT,
                      DESCRIPTION
               FROM TRANSACTION_HISTORY
               WHERE ACCT_NUMBER = :CA-ACCOUNT-NUM
               ORDER BY POST_DATE DESC
               FETCH FIRST 100 ROWS ONLY
           END-EXEC

           EXEC SQL OPEN HIST_CURSOR END-EXEC

           PERFORM UNTIL SQLCODE NOT = 0
               EXEC SQL FETCH HIST_CURSOR
                   INTO :WS-TSQ-DATE,
                        :WS-TSQ-TYPE,
                        :WS-TSQ-AMOUNT,
                        :WS-TSQ-DESC
               END-EXEC
               IF SQLCODE = 0
                   EXEC CICS WRITEQ TS
                       QUEUE(CA-TSQ-NAME)
                       FROM(WS-TSQ-RECORD)
                       LENGTH(WS-TSQ-REC-LEN)
                       RESP(WS-RESP)
                   END-EXEC
                   ADD 1 TO CA-TSQ-TOTAL-ITEMS
               END-IF
           END-PERFORM

           EXEC SQL CLOSE HIST_CURSOR END-EXEC.

       3200-SEND-INQUIRY-MAP.
      *    This paragraph populates and sends the inquiry map
      *    It reads the appropriate page of data from the TSQ

      *    Calculate the page message
           COMPUTE WS-TOTAL-PAGES =
               (CA-TSQ-TOTAL-ITEMS + CA-PAGE-SIZE - 1)
               / CA-PAGE-SIZE
           IF WS-TOTAL-PAGES = 0
               MOVE 1 TO WS-TOTAL-PAGES
           END-IF
           STRING 'Page ' CA-CURRENT-PAGE
               ' of ' WS-TOTAL-PAGES
               DELIMITED BY SIZE
               INTO WS-PAGE-MSG

      *    Read TSQ items for the current page
           COMPUTE WS-START-ITEM =
               (CA-CURRENT-PAGE - 1) * CA-PAGE-SIZE + 1

           PERFORM VARYING WS-LINE-IDX FROM 1 BY 1
               UNTIL WS-LINE-IDX > CA-PAGE-SIZE
               COMPUTE WS-TSQ-ITEM =
                   WS-START-ITEM + WS-LINE-IDX - 1
               IF WS-TSQ-ITEM <= CA-TSQ-TOTAL-ITEMS
                   EXEC CICS READQ TS
                       QUEUE(CA-TSQ-NAME)
                       INTO(WS-TSQ-RECORD)
                       LENGTH(WS-TSQ-REC-LEN)
                       ITEM(WS-TSQ-ITEM)
                       RESP(WS-RESP)
                   END-EXEC
      *            Map TSQ data to screen fields
      *            (In production, this would populate the
      *             symbolic map output area for each line)
               END-IF
           END-PERFORM

      *    Send the map
           EXEC CICS SEND
               MAP('ACMGINQ')
               MAPSET('ACMGIMS')
               ERASE
               RESP(WS-RESP)
           END-EXEC.

      *================================================================*
      * 4000 - PROCESS TRANSACTION ENTRY                               *
      *================================================================*
       4000-PROCESS-TRANSACTION.
           IF WS-AID-KEY = DFHPF3
      *        Return to menu
               PERFORM 1000-FIRST-TIME-ENTRY
           ELSE
      *        Receive transaction entry map
               PERFORM 4200-RECEIVE-TXN-MAP
           END-IF.

       4100-SEND-TXN-MAP.
      *    Populate and send the transaction entry screen
      *    Display account info and prompt for amount
           EXEC CICS SEND
               MAP('ACMGTXN')
               MAPSET('ACMGTMS')
               ERASE
               RESP(WS-RESP)
           END-EXEC.

       4200-RECEIVE-TXN-MAP.
      *    Receive the transaction amount from the teller
      *    Validate business rules

      *    For deposits: minimum $1.00
           IF CA-ACTION-DEPOSIT
               IF CA-TXN-AMOUNT < 1.00
                   MOVE 'Minimum deposit is $1.00'
                       TO CA-MESSAGE
                   PERFORM 4100-SEND-TXN-MAP
               ELSE
                   MOVE 'CONF' TO CA-CURRENT-SCREEN
                   MOVE 'TXNE' TO CA-PREV-SCREEN
                   PERFORM 5100-SEND-CONFIRM-MAP
               END-IF
           END-IF

      *    For withdrawals: check available balance
           IF CA-ACTION-WITHDRAWAL
               IF CA-TXN-AMOUNT > CA-AVAIL-BAL
                   MOVE 'Insufficient funds for withdrawal'
                       TO CA-MESSAGE
                   PERFORM 4100-SEND-TXN-MAP
               ELSE
                   MOVE 'CONF' TO CA-CURRENT-SCREEN
                   MOVE 'TXNE' TO CA-PREV-SCREEN
                   PERFORM 5100-SEND-CONFIRM-MAP
               END-IF
           END-IF

      *    For transfers: validate target account exists
           IF CA-ACTION-TRANSFER
               PERFORM 4300-VALIDATE-TARGET-ACCT
           END-IF.

       4300-VALIDATE-TARGET-ACCT.
           MOVE CA-TXN-TARGET-ACCT TO WS-DB-ACCT-NUM
           EXEC SQL
               SELECT ACCT_STATUS
               INTO :WS-DB-STATUS
               FROM ACCOUNT_MASTER
               WHERE ACCT_NUMBER = :WS-DB-ACCT-NUM
           END-EXEC
           IF SQLCODE = 0
               IF WS-DB-STATUS = 'O'
                   MOVE 'CONF' TO CA-CURRENT-SCREEN
                   MOVE 'TXNE' TO CA-PREV-SCREEN
                   PERFORM 5100-SEND-CONFIRM-MAP
               ELSE
                   MOVE 'Target account is not open'
                       TO CA-MESSAGE
                   PERFORM 4100-SEND-TXN-MAP
               END-IF
           ELSE
               MOVE 'Target account not found'
                   TO CA-MESSAGE
               PERFORM 4100-SEND-TXN-MAP
           END-IF.

      *================================================================*
      * 5000 - PROCESS CONFIRMATION                                    *
      *================================================================*
       5000-PROCESS-CONFIRMATION.
           IF WS-AID-KEY = DFHPF3
      *        Return to transaction entry
               MOVE 'TXNE' TO CA-CURRENT-SCREEN
               PERFORM 4100-SEND-TXN-MAP
           ELSE IF WS-AID-KEY = DFHENTER
      *        Teller confirmed - post the transaction
               PERFORM 5200-POST-TRANSACTION
           ELSE
               MOVE 'Press ENTER to confirm or PF3 to cancel'
                   TO CA-MESSAGE
               PERFORM 5100-SEND-CONFIRM-MAP
           END-IF.

       5100-SEND-CONFIRM-MAP.
      *    Display confirmation screen with transaction summary
           EXEC CICS SEND
               MAP('ACMGCNF')
               MAPSET('ACMGCMS')
               ERASE
               RESP(WS-RESP)
           END-EXEC.

       5200-POST-TRANSACTION.
      *    Get timestamp for the transaction
           EXEC CICS ASKTIME
               ABSTIME(WS-ABSTIME)
           END-EXEC
           EXEC CICS FORMATTIME
               ABSTIME(WS-ABSTIME)
               DATESEP('/')
               TIMESEP(':')
               FULLDATE(CA-TXN-TIMESTAMP)
           END-EXEC

      *    Generate reference number
           STRING 'TXN' EIBTRMID WS-ABSTIME(1:9)
               DELIMITED BY SIZE
               INTO CA-TXN-REF-NUM

      *    Update account balance in DB2
           EVALUATE TRUE
               WHEN CA-ACTION-DEPOSIT
                   EXEC SQL
                       UPDATE ACCOUNT_MASTER
                       SET CURRENT_BAL =
                           CURRENT_BAL + :CA-TXN-AMOUNT,
                           AVAILABLE_BAL =
                           AVAILABLE_BAL + :CA-TXN-AMOUNT,
                           LAST_ACTIVITY = CURRENT DATE
                       WHERE ACCT_NUMBER = :CA-ACCOUNT-NUM
                   END-EXEC
               WHEN CA-ACTION-WITHDRAWAL
                   EXEC SQL
                       UPDATE ACCOUNT_MASTER
                       SET CURRENT_BAL =
                           CURRENT_BAL - :CA-TXN-AMOUNT,
                           AVAILABLE_BAL =
                           AVAILABLE_BAL - :CA-TXN-AMOUNT,
                           LAST_ACTIVITY = CURRENT DATE
                       WHERE ACCT_NUMBER = :CA-ACCOUNT-NUM
                   END-EXEC
               WHEN CA-ACTION-TRANSFER
                   EXEC SQL
                       UPDATE ACCOUNT_MASTER
                       SET CURRENT_BAL =
                           CURRENT_BAL - :CA-TXN-AMOUNT,
                           AVAILABLE_BAL =
                           AVAILABLE_BAL - :CA-TXN-AMOUNT,
                           LAST_ACTIVITY = CURRENT DATE
                       WHERE ACCT_NUMBER = :CA-ACCOUNT-NUM
                   END-EXEC
                   EXEC SQL
                       UPDATE ACCOUNT_MASTER
                       SET CURRENT_BAL =
                           CURRENT_BAL + :CA-TXN-AMOUNT,
                           AVAILABLE_BAL =
                           AVAILABLE_BAL + :CA-TXN-AMOUNT,
                           LAST_ACTIVITY = CURRENT DATE
                       WHERE ACCT_NUMBER =
                           :CA-TXN-TARGET-ACCT
                   END-EXEC
           END-EVALUATE

           IF SQLCODE = 0
               EXEC CICS SYNCPOINT END-EXEC
               STRING 'Transaction posted. Ref: '
                   CA-TXN-REF-NUM
                   DELIMITED BY SIZE
                   INTO CA-MESSAGE
               PERFORM 1000-FIRST-TIME-ENTRY
           ELSE
               EXEC CICS SYNCPOINT ROLLBACK END-EXEC
               STRING 'Transaction failed. SQLCODE='
                   SQLCODE '. Please retry.'
                   DELIMITED BY SIZE
                   INTO CA-MESSAGE
               PERFORM 4100-SEND-TXN-MAP
           END-IF.

      *================================================================*
      * 9000 - ERROR HANDLING                                          *
      *================================================================*
       9000-SEND-ERROR.
           MOVE SPACES TO CA-MESSAGE
           STRING 'System error. RESP=' WS-RESP
               ' RESP2=' WS-RESP2
               '. Contact support.'
               DELIMITED BY SIZE
               INTO CA-MESSAGE

           EXEC CICS SEND TEXT
               FROM(CA-MESSAGE)
               LENGTH(LENGTH OF CA-MESSAGE)
               ERASE
               RESP(WS-RESP)
           END-EXEC

           EXEC CICS RETURN END-EXEC.

Solution Walkthrough

State Machine via COMMAREA

The application's state machine is encoded in the CA-CURRENT-SCREEN field of the COMMAREA. When CICS restarts the program after user input, the first action is to read this field and route to the appropriate handler. The CA-PREV-SCREEN field enables backward navigation: pressing PF3 always takes the teller to the screen that was displayed before the current one.

This pattern eliminates the need for separate CICS programs for each screen. All four screens are managed by a single program, reducing inter-program communication overhead and simplifying deployment.

TSQ for Transaction History Paging

The account inquiry screen displays the last 100 transactions, ten per page. Loading all 100 rows into the COMMAREA would consume significant space and would be wasteful since the teller typically views only the first page. Instead, the program writes the query results to a Temporary Storage Queue (TSQ) and reads only the current page's rows on each display.

The TSQ name is built from the terminal ID ('AH' + EIBTRMID), ensuring uniqueness across concurrent users. The TSQ is deleted when the teller leaves the inquiry screen or ends the transaction.

RESP/RESP2 Error Handling

Every CICS API call includes RESP(WS-RESP) to capture the return code. The program never uses HANDLE CONDITION or HANDLE ABEND -- it uses the modern inline error checking pattern exclusively. This makes the error handling explicit and visible at each call site, avoiding the control flow complications of the older HANDLE approach.

Syncpoint for Transaction Integrity

The confirmation handler uses EXEC CICS SYNCPOINT after a successful DB2 update and EXEC CICS SYNCPOINT ROLLBACK if the update fails. For transfers, both the debit and credit updates must succeed as a unit -- the syncpoint commits both, and the rollback reverses both.


Discussion Questions

  1. The COMMAREA is 300 bytes. If the application grows to include ten more screens with additional context data, the COMMAREA might exceed its practical limits. At what point would you recommend migrating from COMMAREA to channels and containers? What changes to the program structure would this require?

  2. The TSQ-based paging pattern loads all 100 transaction history rows into the TSQ at once. For accounts with thousands of transactions, this could be slow. Design an alternative approach using DB2 cursor-based paging that fetches only one page of rows at a time. What are the trade-offs between the TSQ approach and the cursor approach?

  3. The transfer operation updates two account balances in separate SQL statements. If the CICS region fails between the two updates (after debiting the source but before crediting the target), what happens? How does the two-phase commit protocol protect against this scenario?

  4. The program uses a single transaction code (ACMG) for all four screens. An alternative design would use separate transaction codes for each screen with XCTL for navigation. Compare the two approaches in terms of security (transaction-level authorization), performance, and maintainability.

  5. The current design does not handle concurrent access. If two tellers try to post transactions to the same account simultaneously, a lost update could occur. How would you implement optimistic or pessimistic locking to prevent this? Which approach is more appropriate for a CICS environment?