Skip to content

CBSTM03A

Source: cbl/CBSTM03A.CBL

Type: Batch program

CBSTM03A — Program Documentation

Purpose

CBSTM03A generates customer account statements from card transaction data, producing two parallel output formats: a plain-text statement file and an HTML-formatted statement file. It runs as a batch step (CREASTMT.STEP040) that joins card cross-reference, customer, account, and transaction data to build one statement per account, listing basic account details (balance, FICO score) followed by a list of transactions and their total. This is a CardDemo sample program explicitly designed to exercise legacy COBOL patterns (control block addressing, ALTER/GO TO, COMP-3, 2D tables) for modernization tooling testing.

How it works

  1. Startup (lines before 0000-START) — The program inspects mainframe control blocks (PSA → TCB → TIOT) purely to DISPLAY the job/step name and list DD names with their UCB validity. This has no effect on business logic. It then opens STMT-FILE and HTML-FILE and initializes the in-memory transaction table.

  2. File-open sequencing via ALTER/GO TO0000-START is a dispatcher driven by WS-FL-DD, using the classic COBOL ALTER statement to redirect the paragraph 8100-FILE-OPEN's GO TO target. The sequence is:

  3. Open TRNXFILE (8100-TRNXFILE-OPEN) → read first transaction record → switch to READTRNX mode
  4. 8500-READTRNX-READ loops, reading all transaction records into an in-memory table (WS-TRNX-TABLE, keyed by card number, up to 51 cards × 10 transactions each) grouped by card number, counting transactions per card (WS-TRCT)
  5. Once transactions are exhausted, switches to XREFFILE, opens it (8200-XREFFILE-OPEN), then CUSTFILE (8300-CUSTFILE-OPEN), then ACCTFILE (8400-ACCTFILE-OPEN), finally falling into 1000-MAINLINE.

  6. Main processing loop (1000-MAINLINE) — For each cross-reference record:

  7. 1000-XREFFILE-GET-NEXT reads the next XREF record (via subroutine call, see below); return code '10' signals end-of-file.
  8. 2000-CUSTFILE-GET looks up the customer record by XREF-CUST-ID.
  9. 3000-ACCTFILE-GET looks up the account record by XREF-ACCT-ID.
  10. 5000-CREATE-STATEMENT writes the statement header/basic-details block to both the text file (ST-LINE0ST-LINE12) and HTML file (5100-WRITE-HTML-HEADER, 5200-WRITE-HTML-NMADBS).
  11. 4000-TRNXFILE-GET scans the in-memory transaction table (WS-CARD-TBL) for entries matching the current card number, writes each matching transaction via 6000-WRITE-TRANS, accumulates WS-TOTAL-AMT, then writes the totals/footer lines to both files.
  12. The loop repeats until END-OF-FILE = 'Y'.

  13. Shutdown1000-MAINLINE performs the four file-close paragraphs (91009400), then closes STMT-FILE/HTML-FILE, and 9999-GOBACK ends the program.

  14. Actual file I/O is delegated — None of TRNXFILE, XREFFILE, CUSTFILE, ACCTFILE are declared as COBOL files in this program (no SELECT/FD). All reads/opens/closes for them are performed by passing a request block (WS-M03B-AREA) to CALL 'CBSTM03B', which presumably owns the actual file definitions. Return code WS-M03B-RC drives success/failure/eof handling here.

Inputs & outputs

Name Type Purpose
TRNXFILE (DD, via WS-FL-DD/CBSTM03B) Input Transaction detail records, read sequentially and buffered into an in-memory table keyed by card number. Accessed only through subroutine CBSTM03B, not a native COBOL file.
XREFFILE (via CBSTM03B) Input Card cross-reference records (CARD-XREF-RECORD, copybook CVACT03Y), read sequentially; drives the main loop and supplies XREF-CUST-ID/XREF-ACCT-ID/XREF-CARD-NUM.
CUSTFILE (via CBSTM03B) Input Customer master, read by key (XREF-CUST-ID); copybook CUSTREC supplies name, address, FICO score.
ACCTFILE (via CBSTM03B) Input Account master, read by key (XREF-ACCT-ID); copybook CVACT01Y supplies account ID and current balance.
STMT-FILE / DD STMTFILE Output Fixed 80-byte plain-text statement records (FD-STMTFILE-REC), one per account, including header, name/address, balance/FICO, transaction lines, and totals.
HTML-FILE / DD HTMLFILE Output Fixed 100-byte HTML statement records (FD-HTMLFILE-REC) forming an HTML table document per account, mirroring the text statement content.
Copybook COSTM01 Layout Statement working-storage layout (not detailed in source shown but included in WORKING-STORAGE).
Copybook CVACT03Y Layout Card cross-reference record layout (CARD-XREF-RECORD).
Copybook CUSTREC Layout Customer record layout.
Copybook CVACT01Y Layout Account record layout.

No CICS commands or SQL tables are used — this is pure batch COBOL with subroutine-mediated file access.

Things to know

  • Uses ALTER + GO TO0000-START/8100-FILE-OPEN use the legacy ALTER verb to change the destination of a GO TO at runtime. This is a self-modifying-code pattern that is hard to trace statically and is flagged in the source comments as intentional (to stress-test modernization tooling). Any refactoring tool must handle this control flow carefully; it does not behave like a normal PERFORM.
  • All external file I/O goes through CALL 'CBSTM03B', not native COBOL OPEN/READ/WRITE/CLOSE verbs, for TRNXFILE, XREFFILE, CUSTFILE, ACCTFILE. The actual physical file assignments, VSAM/QSAM details, and error semantics live in CBSTM03B, which is not shown here — behavior of return codes '00', '04', '10', and others is inferred from calling code, not verified against CBSTM03B source.
  • In-memory transaction table is hard-limited: WS-TRNX-TABLE holds at most 51 cards (OCCURS 51) with 10 transactions each (OCCURS 10). Any card with more than 51 distinct cards in a batch, or more than 10 transactions per card, will cause a table-overflow condition. No explicit bounds-checking/error handling for this limit is visible in the shown code — this is a risk if input volumes exceed these hard-coded sizes.
  • Error handling is uniform but abrupt: nearly every I/O paragraph checks WS-M03B-RC and calls 9999-ABEND-PROGRAM on unexpected codes, which displays a message and calls CEE3ABD (LE abend) — there is no recovery/retry logic, the job simply abends.
  • Only 1000-XREFFILE-GET-NEXT treats RC '10' as expected end-of-file; other GET paragraphs (CUSTFILE, ACCTFILE) treat any non-'00' code as an error, so a missing customer/account (e.g., broken cross-reference) will abend the whole job rather than skip the record.
  • Statement totals field ST-TOTAL-TRAMT/WS-TOTAL-AMT is described as "Total EXP" (total expense) in the text file, accumulated across all transactions per account — labeled as such in the layout (ST-LINE14A), though the field simply sums TRNX-AMT, so it is a net sum, not necessarily "expenses only" (no separate credit/debit distinction is visible in the shown code).
  • Control-block/TIOT inspection code at the top of PROCEDURE DIVISION (PSA/TCB/TIOT addressing) is diagnostic/display-only and has no effect on program logic or outputs — safe to ignore functionally, but reflects direct mainframe memory addressing that has no equivalent in non-mainframe environments and will need to be removed or stubbed during modernization.
  • Hard-coded HTML content: bank name ("Bank of XYZ"), address ("410 Terry Ave N, Seattle WA 99999"), and styling are embedded as level-88 literals directly in the program (HTML-L16HTML-L18), meaning any branding change requires a code change/recompile.
  • CR-CNT/CR-JMP/TR-CNT/TR-JMP are used both as table subscripts and loop-control counters shared across paragraphs (8500-READTRNX-READ populates them, 4000-TRNXFILE-GET consumes them) — the coupling between these paragraphs via shared working-storage state (rather than parameters) is a maintenance risk.

Files

Logical file DD name
STMT-FILE STMTFILE
HTML-FILE HTMLFILE

Copybooks

COSTM01, CUSTREC, CVACT01Y, CVACT03Y

Calls

CBSTM03B, CEE3ABD

Executed by

CREASTMT.STEP040

Paragraph flow

flowchart TD
    0000_START["0000-START"]
    1000_MAINLINE["1000-MAINLINE"]
    9999_GOBACK["9999-GOBACK"]
    1000_XREFFILE_GET_NEXT["1000-XREFFILE-GET-NEXT"]
    2000_CUSTFILE_GET["2000-CUSTFILE-GET"]
    3000_ACCTFILE_GET["3000-ACCTFILE-GET"]
    4000_TRNXFILE_GET["4000-TRNXFILE-GET"]
    5000_CREATE_STATEMENT["5000-CREATE-STATEMENT"]
    5100_WRITE_HTML_HEADER["5100-WRITE-HTML-HEADER"]
    5100_EXIT["5100-EXIT"]
    5200_WRITE_HTML_NMADBS["5200-WRITE-HTML-NMADBS"]
    5200_EXIT["5200-EXIT"]
    6000_WRITE_TRANS["6000-WRITE-TRANS"]
    8100_FILE_OPEN["8100-FILE-OPEN"]
    8100_TRNXFILE_OPEN["8100-TRNXFILE-OPEN"]
    8200_XREFFILE_OPEN["8200-XREFFILE-OPEN"]
    8300_CUSTFILE_OPEN["8300-CUSTFILE-OPEN"]
    8400_ACCTFILE_OPEN["8400-ACCTFILE-OPEN"]
    8500_READTRNX_READ["8500-READTRNX-READ"]
    8599_EXIT["8599-EXIT"]
    9100_TRNXFILE_CLOSE["9100-TRNXFILE-CLOSE"]
    9200_XREFFILE_CLOSE["9200-XREFFILE-CLOSE"]
    9300_CUSTFILE_CLOSE["9300-CUSTFILE-CLOSE"]
    9400_ACCTFILE_CLOSE["9400-ACCTFILE-CLOSE"]
    9999_ABEND_PROGRAM["9999-ABEND-PROGRAM"]
    0000_START -.-> 8100_FILE_OPEN
    0000_START -.-> 8500_READTRNX_READ
    0000_START -.-> 9999_GOBACK
    1000_MAINLINE --> 1000_XREFFILE_GET_NEXT
    1000_MAINLINE --> 2000_CUSTFILE_GET
    1000_MAINLINE --> 3000_ACCTFILE_GET
    1000_MAINLINE --> 4000_TRNXFILE_GET
    1000_MAINLINE --> 5000_CREATE_STATEMENT
    1000_MAINLINE --> 9100_TRNXFILE_CLOSE
    1000_MAINLINE --> 9200_XREFFILE_CLOSE
    1000_MAINLINE --> 9300_CUSTFILE_CLOSE
    1000_MAINLINE --> 9400_ACCTFILE_CLOSE
    1000_XREFFILE_GET_NEXT --> 9999_ABEND_PROGRAM
    2000_CUSTFILE_GET --> 9999_ABEND_PROGRAM
    3000_ACCTFILE_GET --> 9999_ABEND_PROGRAM
    4000_TRNXFILE_GET --> 6000_WRITE_TRANS
    5000_CREATE_STATEMENT --> 5100_WRITE_HTML_HEADER
    5000_CREATE_STATEMENT --> 5200_WRITE_HTML_NMADBS
    8100_FILE_OPEN -.-> 8100_TRNXFILE_OPEN
    8100_TRNXFILE_OPEN -.-> 0000_START
    8100_TRNXFILE_OPEN --> 9999_ABEND_PROGRAM
    8200_XREFFILE_OPEN -.-> 0000_START
    8200_XREFFILE_OPEN --> 9999_ABEND_PROGRAM
    8300_CUSTFILE_OPEN -.-> 0000_START
    8300_CUSTFILE_OPEN --> 9999_ABEND_PROGRAM
    8400_ACCTFILE_OPEN -.-> 1000_MAINLINE
    8400_ACCTFILE_OPEN --> 9999_ABEND_PROGRAM
    8500_READTRNX_READ -.-> 8500_READTRNX_READ
    8500_READTRNX_READ -.-> 8599_EXIT
    8500_READTRNX_READ --> 9999_ABEND_PROGRAM
    8599_EXIT -.-> 0000_START
    9100_TRNXFILE_CLOSE --> 9999_ABEND_PROGRAM
    9200_XREFFILE_CLOSE --> 9999_ABEND_PROGRAM
    9300_CUSTFILE_CLOSE --> 9999_ABEND_PROGRAM
    9400_ACCTFILE_CLOSE --> 9999_ABEND_PROGRAM

Paragraphs

Paragraph Line Performs
0000-START 296
1000-MAINLINE 316 1000-XREFFILE-GET-NEXT, 2000-CUSTFILE-GET, 3000-ACCTFILE-GET, 5000-CREATE-STATEMENT, 4000-TRNXFILE-GET, 9100-TRNXFILE-CLOSE
9999-GOBACK 341
1000-XREFFILE-GET-NEXT 345 9999-ABEND-PROGRAM
2000-CUSTFILE-GET 368 9999-ABEND-PROGRAM
3000-ACCTFILE-GET 392 9999-ABEND-PROGRAM
4000-TRNXFILE-GET 416 6000-WRITE-TRANS
5000-CREATE-STATEMENT 458 5100-WRITE-HTML-HEADER, 5200-WRITE-HTML-NMADBS
5100-WRITE-HTML-HEADER 506
5100-EXIT 554
5200-WRITE-HTML-NMADBS 558
5200-EXIT 671
6000-WRITE-TRANS 675
8100-FILE-OPEN 726
8100-TRNXFILE-OPEN 730 9999-ABEND-PROGRAM, 9999-ABEND-PROGRAM
8200-XREFFILE-OPEN 765 9999-ABEND-PROGRAM
8300-CUSTFILE-OPEN 783 9999-ABEND-PROGRAM
8400-ACCTFILE-OPEN 801 9999-ABEND-PROGRAM
8500-READTRNX-READ 818 9999-ABEND-PROGRAM
8599-EXIT 849
9100-TRNXFILE-CLOSE 856 9999-ABEND-PROGRAM
9200-XREFFILE-CLOSE 873 9999-ABEND-PROGRAM
9300-CUSTFILE-CLOSE 889 9999-ABEND-PROGRAM
9400-ACCTFILE-CLOSE 905 9999-ABEND-PROGRAM
9999-ABEND-PROGRAM 921