Case Study 1: Building an ATM Interface Prototype
Background
First National Bank is modernizing its ATM fleet. Before investing in hardware integration and network connectivity, the development team has been asked to prototype the ATM user interface in COBOL. The prototype will run on a console terminal, simulating the flow that customers experience at a physical ATM.
This is a common approach in financial systems development: prototype the screen flow and business logic on a simple terminal before wiring up the hardware and communication layers. The COBOL business logic will eventually be reused in the production system -- the I/O layer is what changes.
Project Requirements
Functional Requirements
The ATM prototype must support the following user interactions:
-
Welcome Screen -- Display the bank branding, current date and time, and prompt the customer to insert their card (simulated by pressing Enter).
-
Card Entry -- Accept a 16-digit card number. Validate it against a stored list of valid cards. Display an error and return to the welcome screen if invalid.
-
PIN Entry -- Accept a 4-digit PIN. Allow up to 3 attempts. Lock the card after 3 failures. Display masked card number (only last 4 digits visible) for security.
-
Main Menu -- Display transaction options: Balance Inquiry, Withdrawal, Deposit, Another Transaction, and Exit/Remove Card.
-
Balance Inquiry -- Display the current account balance in currency-formatted output with the account number and timestamp.
-
Withdrawal -- Offer quick-amount buttons ($20, $40, $60, $100, $200) and a custom amount option. Validate that the withdrawal does not exceed the available balance. Deduct from the balance and confirm.
-
Deposit -- Accept a deposit amount. Add to the balance and confirm.
-
Receipt -- After each transaction, ask if the customer wants a receipt. If yes, display a formatted receipt with date, time, card (masked), account, transaction type, amount, and new balance.
-
Exit -- Thank the customer, remind them to take their card, and return to the welcome screen.
Non-Functional Requirements
- All currency amounts must be displayed with dollar signs, commas, and two decimal places.
- Card numbers must be masked as
****-****-****-XXXXwherever displayed. - The PIN must never be displayed on screen (not even in receipts).
- Each screen should have a consistent visual frame using border characters.
- The system clock should be used for date and time stamps.
Design Approach
Screen State Machine
The ATM interface follows a state machine pattern, where each screen represents a state and user actions cause transitions between states:
WELCOME --> CARD ENTRY --> PIN ENTRY --> MAIN MENU
| | |
| | +--> BALANCE --> RECEIPT? --> MAIN MENU
| | |
| | +--> WITHDRAW --> RECEIPT? --> MAIN MENU
| | |
| | +--> DEPOSIT --> RECEIPT? --> MAIN MENU
| | |
| | +--> EXIT --> WELCOME
| |
| +--> LOCKED --> EXIT
|
+--> INVALID --> WELCOME
In the COBOL implementation, this state machine is represented by a state variable with 88-level condition names:
01 WS-ATM-STATE PIC X(10) VALUE "WELCOME".
88 STATE-WELCOME VALUE "WELCOME".
88 STATE-CARD-ENTRY VALUE "CARD".
88 STATE-PIN-ENTRY VALUE "PIN".
88 STATE-MAIN-MENU VALUE "MENU".
88 STATE-BALANCE VALUE "BALANCE".
88 STATE-WITHDRAW VALUE "WITHDRAW".
88 STATE-DEPOSIT VALUE "DEPOSIT".
88 STATE-EXIT VALUE "EXIT".
The main processing loop uses EVALUATE TRUE to dispatch to the appropriate screen handler:
PERFORM UNTIL ATM-IS-STOPPED
EVALUATE TRUE
WHEN STATE-WELCOME PERFORM 200-WELCOME-SCREEN
WHEN STATE-CARD-ENTRY PERFORM 300-CARD-ENTRY-SCREEN
WHEN STATE-PIN-ENTRY PERFORM 400-PIN-ENTRY-SCREEN
WHEN STATE-MAIN-MENU PERFORM 500-MAIN-MENU-SCREEN
*> ... additional states
WHEN STATE-EXIT PERFORM 800-EXIT-SCREEN
SET ATM-IS-STOPPED TO TRUE
END-EVALUATE
END-PERFORM
Each screen handler is responsible for displaying its screen, accepting input, processing the input, and setting the next state.
Data Architecture
The prototype stores customer data in WORKING-STORAGE variables rather than a database. In a production system, these would be replaced with calls to a database or transaction processing system:
* Simulated customer record (would be DB2 in production)
01 WS-CUSTOMER-DATA.
05 WS-CARD-NUMBER PIC X(16).
05 WS-PIN PIC X(4).
05 WS-CUSTOMER-NAME PIC X(25).
05 WS-ACCOUNT-NUMBER PIC X(12).
05 WS-ACCOUNT-BALANCE PIC S9(9)V99.
Screen Layout Standards
Every screen follows a consistent template:
================================================ <-- Top border
| FIRST NATIONAL BANK - ATM | <-- Title bar
------------------------------------------------ <-- Divider
| | <-- Content area
| [Screen-specific content here] |
| |
------------------------------------------------ <-- Bottom divider
| [Status or instruction line] | <-- Footer
================================================ <-- Bottom border
This is implemented using DISPLAY statements with carefully sized strings:
01 WS-ATM-BORDER PIC X(48) VALUE ALL "=".
01 WS-ATM-DASH PIC X(48) VALUE ALL "-".
DISPLAY WS-ATM-BORDER
DISPLAY "| FIRST NATIONAL BANK - ATM |"
DISPLAY WS-ATM-DASH
The 48-character width was chosen to represent a typical ATM screen width while fitting comfortably in an 80-column terminal.
Key Implementation Details
Card Number Masking
Card numbers should only display the last 4 digits. This is a security requirement in financial systems (similar to PCI DSS compliance):
STRING "****-****-****-" DELIMITED SIZE
WS-CARD-NUMBER(13:4) DELIMITED SIZE
INTO WS-CARD-MASKED
END-STRING
The reference modification WS-CARD-NUMBER(13:4) extracts 4 characters starting at position 13, which are the last 4 digits of the 16-digit card number.
PIN Validation with Limited Attempts
The PIN entry handler tracks attempts and locks the card after 3 failures:
01 WS-PIN-ATTEMPTS PIC 9 VALUE 0.
ADD 1 TO WS-PIN-ATTEMPTS
IF WS-PIN-ENTERED = WS-PIN-CORRECT
MOVE "MENU" TO WS-ATM-STATE
ELSE
IF WS-PIN-ATTEMPTS >= 3
DISPLAY "*** CARD LOCKED ***"
MOVE "EXIT" TO WS-ATM-STATE
ELSE
DISPLAY "Incorrect PIN. Try again."
END-IF
END-IF
Withdrawal Validation
Withdrawals must not exceed the available balance:
IF WS-TXN-AMOUNT > WS-ACCOUNT-BALANCE
DISPLAY "*** INSUFFICIENT FUNDS ***"
MOVE "MENU" TO WS-ATM-STATE
ELSE
SUBTRACT WS-TXN-AMOUNT FROM WS-ACCOUNT-BALANCE
DISPLAY "WITHDRAWAL CONFIRMED"
END-IF
In a production system, additional validations would include daily withdrawal limits, denomination constraints (ATMs only dispense certain bill combinations), and multi-account checks.
Receipt Generation
The receipt is a formatted console display that mimics a paper receipt:
=================================
FIRST NATIONAL BANK
ATM RECEIPT
---------------------------------
Date: 2026-02-10
Time: 14:30:22
Card: ****-****-****-0366
Acct: CHK-00458721
---------------------------------
Transaction: WITHDRAWAL
Amount: $200.00
Balance: $15,047.83
---------------------------------
Ref: TXN-100001
Thank you for banking with us!
=================================
Each line is formatted using structured DISPLAY statements with edited PICTURE fields for currency amounts.
Testing the Prototype
Test Scenario 1: Successful Transaction Flow
- Start the program
- Press Enter at the welcome screen
- Enter valid card number: 4532015112830366
- Enter correct PIN: 1234
- Select "1" for Balance Inquiry
- Select "Y" for receipt
- Select "2" for Withdrawal
- Select "D" for $100
- Verify balance is reduced by $100
- Select "5" to exit
Test Scenario 2: PIN Lockout
- Start the program
- Enter valid card number
- Enter wrong PIN three times
- Verify "CARD LOCKED" message appears
- Verify program exits
Test Scenario 3: Insufficient Funds
- Complete login
- Attempt to withdraw more than the balance
- Verify "INSUFFICIENT FUNDS" message
- Verify balance is unchanged
- Verify return to main menu
Test Scenario 4: Deposit and Verify
- Complete login
- Note the starting balance
- Deposit $500
- Check balance -- should be starting balance + $500
- Withdraw $200
- Check balance -- should be starting balance + $300
From Prototype to Production
In a real ATM system, this prototype would evolve in several ways:
-
I/O Layer: The DISPLAY/ACCEPT statements would be replaced with hardware-specific I/O calls to the ATM device controller, or with BMS maps in a CICS environment.
-
Data Access: The hardcoded customer data would be replaced with DB2 queries or IMS database calls.
-
Security: PIN validation would use encrypted comparisons, and the session would implement timeouts.
-
Transaction Processing: Each transaction would be wrapped in a CICS unit of work with commit/rollback capabilities.
-
Networking: The ATM would communicate with a central authorization system for real-time balance checks and fraud detection.
However, the fundamental program structure -- the state machine, the validation logic, the formatted output -- would remain largely unchanged. This is why COBOL's console I/O is such a valuable prototyping tool: the business logic you develop at the console level transfers directly to production systems.
Source Code
The complete implementation is available in code/case-study-code.cob. Compile and run it with:
cobc -x case-study-code.cob
./case-study-code
Use the test card number 4532015112830366 and PIN 1234 to access the system.
Discussion Questions
-
Why does the ATM use a state machine pattern rather than a simple sequential flow? What advantage does this provide for adding new transaction types?
-
In a production system, why would the PIN never be stored in plain text in WORKING-STORAGE? What security measures would replace the approach used in this prototype?
-
The receipt shows the card number masked. What other data on the receipt might need to be protected, and how?
-
How would the program need to change if it supported multiple accounts per card (checking, savings, credit)?
-
What would be the impact of converting this program from DISPLAY/ACCEPT to CICS BMS maps? Which parts of the code would remain unchanged?