Skip to content

CBTRN02C

Source: cbl/CBTRN02C.cbl

Type: Batch program

CBTRN02C — Daily Transaction Posting Program

Purpose

CBTRN02C is a batch COBOL program in the CardDemo application that posts a daily batch of credit card transactions to the account and category-balance masters. For each transaction it validates the card number and account against reference data, checks credit limit and account expiration, then either posts the transaction (updating balances and writing it to the permanent transaction file) or writes it to a rejects file with a reason code. It is executed as job step POSTTRAN.STEP15.

How it works

The main paragraph (PROCEDURE DIVISION, from line 193) drives a straightforward open → loop → close structure:

  1. Startup: Opens all six files in sequence via 0000-DALYTRAN-OPEN through 0500-TCATBALF-OPEN. Any open failure triggers 9910-DISPLAY-IO-STATUS (formats the file status for display) followed by 9999-ABEND-PROGRAM (abnormal termination via CALL 'CEE3ABD').

  2. Main processing loop: Runs PERFORM UNTIL END-OF-FILE = 'Y', driven by 1000-DALYTRAN-GET-NEXT, which reads one record from the daily transaction file (DALYTRAN-FILE). A file status of 10 sets END-OF-FILE to stop the loop; any other non-zero status abends the program.

  3. Validation (1500-VALIDATE-TRAN): For each transaction read:

  4. 1500-A-LOOKUP-XREF looks up the card number in the cross-reference file (XREF-FILE). If not found, sets fail reason 100 ("INVALID CARD NUMBER FOUND") and skips further validation.
  5. If the card lookup succeeds, 1500-B-LOOKUP-ACCT reads the account master (ACCOUNT-FILE) using the account ID from the xref record. If not found, sets fail reason 101. If found, it computes a projected balance (ACCT-CURR-CYC-CREDIT - ACCT-CURR-CYC-DEBIT + DALYTRAN-AMT) and rejects with reason 102 ("OVERLIMIT TRANSACTION") if it exceeds the credit limit, and rejects with reason 103 if the account expiration date is earlier than the transaction's origination timestamp.

  6. Branch on validation result:

  7. If WS-VALIDATION-FAIL-REASON = 0, 2000-POST-TRANSACTION is performed: it builds a TRAN-RECORD from the daily transaction fields, stamps it with a DB2-format processing timestamp (Z-GET-DB2-FORMAT-TIMESTAMP), then performs 2700-UPDATE-TCATBAL (updates/creates the transaction category balance), 2800-UPDATE-ACCOUNT-REC (updates account running balances), and 2900-WRITE-TRANSACTION-FILE (writes the posted transaction to the output transaction file).
  8. Otherwise, 2500-WRITE-REJECT-REC writes the raw transaction plus the failure reason/description to the rejects file, and the reject counter is incremented.

  9. Category balance update (2700-UPDATE-TCATBAL): Attempts to read the transaction category balance record for the account/type/category key. If not found (status 23), it flags WS-CREATE-TRANCAT-REC = 'Y' and calls 2700-A-CREATE-TCATBAL-REC to initialize and write a new balance record; otherwise it calls 2700-B-UPDATE-TCATBAL-REC to add the transaction amount to the existing balance and rewrite it.

  10. Shutdown: After the loop ends, all files are closed (90009500 paragraphs), transaction/reject counts are displayed, and RETURN-CODE is set to 4 if any rejects occurred, before GOBACK.

Every I/O operation across the program follows the same pattern: check the file status, and on any unexpected status, call 9910-DISPLAY-IO-STATUS to log the status code and 9999-ABEND-PROGRAM to terminate via CEE3ABD.

Inputs & outputs

File / DD Access Role
DALYTRAN (DALYTRAN-FILE) Sequential input Daily transactions to be validated and posted (one record per transaction)
XREFFILE (XREF-FILE) Indexed random, input Card-number-to-account cross-reference lookup
ACCTFILE (ACCOUNT-FILE) Indexed random, I/O Account master — read for validation, rewritten with updated balances
TCATBALF (TCATBAL-FILE) Indexed random, I/O Transaction category balance master — read, then written (new) or rewritten (existing) per account/type/category key
TRANFILE (TRANSACT-FILE) Indexed output Permanent record of successfully posted transactions
DALYREJS (DALYREJS-FILE) Sequential output Rejected transactions, each with a validation-failure reason code/description appended

Copybooks used for record layouts: CVACT01Y (account record), CVACT03Y (cross-reference record), CVTRA01Y (transaction category balance record), CVTRA05Y (transaction record), CVTRA06Y (daily transaction record). No CICS commands or SQL tables are used — this is a pure batch, VSAM/sequential-file program despite the DB2-style timestamp formatting.

Things to know

  • Hard-coded reason codes: Validation failures use fixed numeric codes (100 = invalid card, 101 = account not found, 102 = overlimit, 103 = expired account, 109 = account rewrite failure) with no central definition — these are scattered inline and would need to be documented/maintained carefully during any rewrite.
  • Abend on any unexpected I/O status: Every file operation (open, read, write, rewrite, close) treats any status other than '00' (or '23' for the category-balance "not found" case) as fatal and calls CEE3ABD to abend the whole job — there is no retry or partial-failure handling.
  • Silent validation failure on account rewrite: In 2800-UPDATE-ACCOUNT-REC, an INVALID KEY on the REWRITE sets WS-VALIDATION-FAIL-REASON to 109, but this happens after the transaction has already been counted as accepted and already posted to the category balance — the reject flag is set too late to prevent the category-balance update or to route this transaction to the reject file (it will still be written to TRANFILE in 2900-WRITE-TRANSACTION-FILE). This looks like a bug/gap in the reject-handling logic and should be flagged for review.
  • Return code convention: Program sets RETURN-CODE = 4 if any rejects occurred, otherwise leaves it at 0 (implicit success) — downstream job steps/schedulers likely branch on this.
  • DB2-format timestamp is cosmetic: Z-GET-DB2-FORMAT-TIMESTAMP builds a DB2-style timestamp string purely via string manipulation from FUNCTION CURRENT-DATE — there is no actual DB2 or CICS interaction in this program (confirmed by empty cics_commands and sql_tables in the parsed facts).
  • Comment-only extra validation hook: The comment * ADD MORE VALIDATIONS HERE in 1500-VALIDATE-TRAN indicates the validation logic is intentionally minimal/extensible; only three checks (card lookup, account lookup, limit, expiration) currently exist.
  • Field-level date comparison risk: The expiration check compares ACCT-EXPIRAION-DATE (note the typo in the original field name) against a substring of the transaction timestamp (DALYTRAN-ORIG-TS (1:10)) — this is a straight alphanumeric comparison of date-like strings, which only works correctly if both are in the same fixed format (e.g., YYYY-MM-DD); no explicit format validation is performed.
  • Commented-out DISPLAY statements throughout the code (e.g., displaying transaction/account details) suggest this was actively debugged and such tracing could be re-enabled if needed for troubleshooting.

Files

Logical file DD name
DALYTRAN-FILE DALYTRAN
TRANSACT-FILE TRANFILE
XREF-FILE XREFFILE
DALYREJS-FILE DALYREJS
ACCOUNT-FILE ACCTFILE
TCATBAL-FILE TCATBALF

Copybooks

CVACT01Y, CVACT03Y, CVTRA01Y, CVTRA05Y, CVTRA06Y

Calls

CEE3ABD

Executed by

POSTTRAN.STEP15

Paragraph flow

flowchart TD
    0000_DALYTRAN_OPEN["0000-DALYTRAN-OPEN"]
    0100_TRANFILE_OPEN["0100-TRANFILE-OPEN"]
    0200_XREFFILE_OPEN["0200-XREFFILE-OPEN"]
    0300_DALYREJS_OPEN["0300-DALYREJS-OPEN"]
    0400_ACCTFILE_OPEN["0400-ACCTFILE-OPEN"]
    0500_TCATBALF_OPEN["0500-TCATBALF-OPEN"]
    1000_DALYTRAN_GET_NEXT["1000-DALYTRAN-GET-NEXT"]
    1500_VALIDATE_TRAN["1500-VALIDATE-TRAN"]
    1500_A_LOOKUP_XREF["1500-A-LOOKUP-XREF"]
    1500_B_LOOKUP_ACCT["1500-B-LOOKUP-ACCT"]
    2000_POST_TRANSACTION["2000-POST-TRANSACTION"]
    2500_WRITE_REJECT_REC["2500-WRITE-REJECT-REC"]
    2700_UPDATE_TCATBAL["2700-UPDATE-TCATBAL"]
    2700_A_CREATE_TCATBAL_REC["2700-A-CREATE-TCATBAL-REC"]
    2700_B_UPDATE_TCATBAL_REC["2700-B-UPDATE-TCATBAL-REC"]
    2800_UPDATE_ACCOUNT_REC["2800-UPDATE-ACCOUNT-REC"]
    2900_WRITE_TRANSACTION_FILE["2900-WRITE-TRANSACTION-FILE"]
    9000_DALYTRAN_CLOSE["9000-DALYTRAN-CLOSE"]
    9100_TRANFILE_CLOSE["9100-TRANFILE-CLOSE"]
    9200_XREFFILE_CLOSE["9200-XREFFILE-CLOSE"]
    9300_DALYREJS_CLOSE["9300-DALYREJS-CLOSE"]
    9400_ACCTFILE_CLOSE["9400-ACCTFILE-CLOSE"]
    9500_TCATBALF_CLOSE["9500-TCATBALF-CLOSE"]
    Z_GET_DB2_FORMAT_TIMESTAMP["Z-GET-DB2-FORMAT-TIMESTAMP"]
    9999_ABEND_PROGRAM["9999-ABEND-PROGRAM"]
    9910_DISPLAY_IO_STATUS["9910-DISPLAY-IO-STATUS"]
    0000_DALYTRAN_OPEN --> 9910_DISPLAY_IO_STATUS
    0000_DALYTRAN_OPEN --> 9999_ABEND_PROGRAM
    0100_TRANFILE_OPEN --> 9910_DISPLAY_IO_STATUS
    0100_TRANFILE_OPEN --> 9999_ABEND_PROGRAM
    0200_XREFFILE_OPEN --> 9910_DISPLAY_IO_STATUS
    0200_XREFFILE_OPEN --> 9999_ABEND_PROGRAM
    0300_DALYREJS_OPEN --> 9910_DISPLAY_IO_STATUS
    0300_DALYREJS_OPEN --> 9999_ABEND_PROGRAM
    0400_ACCTFILE_OPEN --> 9910_DISPLAY_IO_STATUS
    0400_ACCTFILE_OPEN --> 9999_ABEND_PROGRAM
    0500_TCATBALF_OPEN --> 9910_DISPLAY_IO_STATUS
    0500_TCATBALF_OPEN --> 9999_ABEND_PROGRAM
    1000_DALYTRAN_GET_NEXT --> 9910_DISPLAY_IO_STATUS
    1000_DALYTRAN_GET_NEXT --> 9999_ABEND_PROGRAM
    1500_VALIDATE_TRAN --> 1500_A_LOOKUP_XREF
    1500_VALIDATE_TRAN --> 1500_B_LOOKUP_ACCT
    2000_POST_TRANSACTION --> 2700_UPDATE_TCATBAL
    2000_POST_TRANSACTION --> 2800_UPDATE_ACCOUNT_REC
    2000_POST_TRANSACTION --> 2900_WRITE_TRANSACTION_FILE
    2000_POST_TRANSACTION --> Z_GET_DB2_FORMAT_TIMESTAMP
    2500_WRITE_REJECT_REC --> 9910_DISPLAY_IO_STATUS
    2500_WRITE_REJECT_REC --> 9999_ABEND_PROGRAM
    2700_A_CREATE_TCATBAL_REC --> 9910_DISPLAY_IO_STATUS
    2700_A_CREATE_TCATBAL_REC --> 9999_ABEND_PROGRAM
    2700_B_UPDATE_TCATBAL_REC --> 9910_DISPLAY_IO_STATUS
    2700_B_UPDATE_TCATBAL_REC --> 9999_ABEND_PROGRAM
    2700_UPDATE_TCATBAL --> 2700_A_CREATE_TCATBAL_REC
    2700_UPDATE_TCATBAL --> 2700_B_UPDATE_TCATBAL_REC
    2700_UPDATE_TCATBAL --> 9910_DISPLAY_IO_STATUS
    2700_UPDATE_TCATBAL --> 9999_ABEND_PROGRAM
    2900_WRITE_TRANSACTION_FILE --> 9910_DISPLAY_IO_STATUS
    2900_WRITE_TRANSACTION_FILE --> 9999_ABEND_PROGRAM
    9000_DALYTRAN_CLOSE --> 9910_DISPLAY_IO_STATUS
    9000_DALYTRAN_CLOSE --> 9999_ABEND_PROGRAM
    9100_TRANFILE_CLOSE --> 9910_DISPLAY_IO_STATUS
    9100_TRANFILE_CLOSE --> 9999_ABEND_PROGRAM
    9200_XREFFILE_CLOSE --> 9910_DISPLAY_IO_STATUS
    9200_XREFFILE_CLOSE --> 9999_ABEND_PROGRAM
    9300_DALYREJS_CLOSE --> 9910_DISPLAY_IO_STATUS
    9300_DALYREJS_CLOSE --> 9999_ABEND_PROGRAM
    9400_ACCTFILE_CLOSE --> 9910_DISPLAY_IO_STATUS
    9400_ACCTFILE_CLOSE --> 9999_ABEND_PROGRAM
    9500_TCATBALF_CLOSE --> 9910_DISPLAY_IO_STATUS
    9500_TCATBALF_CLOSE --> 9999_ABEND_PROGRAM

Paragraphs

Paragraph Line Performs
0000-DALYTRAN-OPEN 236 9910-DISPLAY-IO-STATUS, 9999-ABEND-PROGRAM
0100-TRANFILE-OPEN 254 9910-DISPLAY-IO-STATUS, 9999-ABEND-PROGRAM
0200-XREFFILE-OPEN 273 9910-DISPLAY-IO-STATUS, 9999-ABEND-PROGRAM
0300-DALYREJS-OPEN 291 9910-DISPLAY-IO-STATUS, 9999-ABEND-PROGRAM
0400-ACCTFILE-OPEN 309 9910-DISPLAY-IO-STATUS, 9999-ABEND-PROGRAM
0500-TCATBALF-OPEN 327 9910-DISPLAY-IO-STATUS, 9999-ABEND-PROGRAM
1000-DALYTRAN-GET-NEXT 345 9910-DISPLAY-IO-STATUS, 9999-ABEND-PROGRAM
1500-VALIDATE-TRAN 370 1500-A-LOOKUP-XREF, 1500-B-LOOKUP-ACCT
1500-A-LOOKUP-XREF 380
1500-B-LOOKUP-ACCT 393
2000-POST-TRANSACTION 424 Z-GET-DB2-FORMAT-TIMESTAMP, 2700-UPDATE-TCATBAL, 2800-UPDATE-ACCOUNT-REC, 2900-WRITE-TRANSACTION-FILE
2500-WRITE-REJECT-REC 446 9910-DISPLAY-IO-STATUS, 9999-ABEND-PROGRAM
2700-UPDATE-TCATBAL 467 9910-DISPLAY-IO-STATUS, 9999-ABEND-PROGRAM, 2700-A-CREATE-TCATBAL-REC, 2700-B-UPDATE-TCATBAL-REC
2700-A-CREATE-TCATBAL-REC 503 9910-DISPLAY-IO-STATUS, 9999-ABEND-PROGRAM
2700-B-UPDATE-TCATBAL-REC 526 9910-DISPLAY-IO-STATUS, 9999-ABEND-PROGRAM
2800-UPDATE-ACCOUNT-REC 545
2900-WRITE-TRANSACTION-FILE 562 9910-DISPLAY-IO-STATUS, 9999-ABEND-PROGRAM
9000-DALYTRAN-CLOSE 582 9910-DISPLAY-IO-STATUS, 9999-ABEND-PROGRAM
9100-TRANFILE-CLOSE 600 9910-DISPLAY-IO-STATUS, 9999-ABEND-PROGRAM
9200-XREFFILE-CLOSE 619 9910-DISPLAY-IO-STATUS, 9999-ABEND-PROGRAM
9300-DALYREJS-CLOSE 637 9910-DISPLAY-IO-STATUS, 9999-ABEND-PROGRAM
9400-ACCTFILE-CLOSE 655 9910-DISPLAY-IO-STATUS, 9999-ABEND-PROGRAM
9500-TCATBALF-CLOSE 674 9910-DISPLAY-IO-STATUS, 9999-ABEND-PROGRAM
Z-GET-DB2-FORMAT-TIMESTAMP 692
9999-ABEND-PROGRAM 707
9910-DISPLAY-IO-STATUS 714