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:
-
Startup: Opens all six files in sequence via
0000-DALYTRAN-OPENthrough0500-TCATBALF-OPEN. Any open failure triggers9910-DISPLAY-IO-STATUS(formats the file status for display) followed by9999-ABEND-PROGRAM(abnormal termination viaCALL 'CEE3ABD'). -
Main processing loop: Runs
PERFORM UNTIL END-OF-FILE = 'Y', driven by1000-DALYTRAN-GET-NEXT, which reads one record from the daily transaction file (DALYTRAN-FILE). A file status of10setsEND-OF-FILEto stop the loop; any other non-zero status abends the program. -
Validation (
1500-VALIDATE-TRAN): For each transaction read: 1500-A-LOOKUP-XREFlooks 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.-
If the card lookup succeeds,
1500-B-LOOKUP-ACCTreads 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. -
Branch on validation result:
- If
WS-VALIDATION-FAIL-REASON = 0,2000-POST-TRANSACTIONis performed: it builds aTRAN-RECORDfrom the daily transaction fields, stamps it with a DB2-format processing timestamp (Z-GET-DB2-FORMAT-TIMESTAMP), then performs2700-UPDATE-TCATBAL(updates/creates the transaction category balance),2800-UPDATE-ACCOUNT-REC(updates account running balances), and2900-WRITE-TRANSACTION-FILE(writes the posted transaction to the output transaction file). -
Otherwise,
2500-WRITE-REJECT-RECwrites the raw transaction plus the failure reason/description to the rejects file, and the reject counter is incremented. -
Category balance update (
2700-UPDATE-TCATBAL): Attempts to read the transaction category balance record for the account/type/category key. If not found (status23), it flagsWS-CREATE-TRANCAT-REC = 'Y'and calls2700-A-CREATE-TCATBAL-RECto initialize and write a new balance record; otherwise it calls2700-B-UPDATE-TCATBAL-RECto add the transaction amount to the existing balance and rewrite it. -
Shutdown: After the loop ends, all files are closed (
9000–9500paragraphs), transaction/reject counts are displayed, andRETURN-CODEis set to 4 if any rejects occurred, beforeGOBACK.
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 callsCEE3ABDto abend the whole job — there is no retry or partial-failure handling. - Silent validation failure on account rewrite: In
2800-UPDATE-ACCOUNT-REC, anINVALID KEYon theREWRITEsetsWS-VALIDATION-FAIL-REASONto 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 toTRANFILEin2900-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 = 4if 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-TIMESTAMPbuilds a DB2-style timestamp string purely via string manipulation fromFUNCTION CURRENT-DATE— there is no actual DB2 or CICS interaction in this program (confirmed by emptycics_commandsandsql_tablesin the parsed facts). - Comment-only extra validation hook: The comment
* ADD MORE VALIDATIONS HEREin1500-VALIDATE-TRANindicates 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 |