Case Study 2: Batch Reconciliation and Exception Processing

Background

Every business day, Heartland Community Bank must reconcile the total of all individual account transactions against the general ledger (GL) summary entries. This reconciliation ensures that every dollar flowing through the bank's systems is accounted for -- that deposits, withdrawals, transfers, fees, and interest postings in the transaction detail files exactly match the aggregated entries in the general ledger.

When the reconciliation finds discrepancies, these are classified as exceptions that require investigation. Some exceptions can be resolved automatically (timing differences, rounding adjustments, known system offsets). Others require manual review by the accounting team.

Senior COBOL developer Sandra Kowalski designed and coded the batch reconciliation program, RECONMCH, which runs as part of the bank's nightly end-of-day cycle. The program reads two input files -- the daily transaction detail and the GL summary -- performs a matching algorithm, and produces three output files: matched items, unmatched items, and an exception report.

This case study presents the complete COBOL reconciliation program, explains the matching logic, and examines the exception handling workflow.

The Reconciliation Business Rules

The reconciliation follows specific rules established by the bank's accounting department:

  1. Matching criteria: A transaction detail record matches a GL summary record when both the account category code and the transaction type agree, and the aggregated transaction amounts for that category/type combination equal the GL summary amount within a tolerance of $0.01.

  2. Out-of-balance detection: If the total debits minus total credits in the transaction detail differs from the GL net change by more than $0.01, the entire day is flagged as out-of-balance.

  3. Automatic corrections: Rounding differences of $0.01 or less are adjusted automatically. Known system offsets (such as end-of-day interest accrual timing) are recognized and documented but not flagged as errors.

  4. Manual review threshold: Any single unmatched amount exceeding $10,000 is flagged for immediate supervisor review. Amounts between $100 and $10,000 are flagged for next-day review. Amounts under $100 are logged but not escalated.

  5. Balancing proof: The sum of all matched amounts plus the sum of all unmatched amounts must equal the original transaction detail total. This is the "proof of reconciliation" that auditors verify.

Input File Layouts

The daily transaction detail file is sorted by account category and transaction type. Each record represents a single transaction:

       01  WS-TXN-DETAIL-REC.
           05 WS-TXN-ACCT-CATEGORY  PIC X(4).
           05 WS-TXN-TYPE-CODE      PIC X(3).
           05 WS-TXN-ACCT-NUM       PIC X(12).
           05 WS-TXN-DATE           PIC X(10).
           05 WS-TXN-SEQ-NUM        PIC 9(8).
           05 WS-TXN-AMOUNT         PIC S9(11)V99 COMP-3.
           05 WS-TXN-DR-CR-IND      PIC X(1).
              88 TXN-DEBIT                    VALUE 'D'.
              88 TXN-CREDIT                   VALUE 'C'.
           05 WS-TXN-DESCRIPTION    PIC X(40).
           05 WS-TXN-SOURCE-SYS     PIC X(3).
           05 WS-TXN-BRANCH         PIC X(4).
           05 WS-TXN-TELLER-ID      PIC X(6).
           05 FILLER                PIC X(53).

The GL summary file contains one record per account-category/transaction-type combination, showing the aggregated totals posted to the general ledger:

       01  WS-GL-SUMMARY-REC.
           05 WS-GL-ACCT-CATEGORY   PIC X(4).
           05 WS-GL-TYPE-CODE       PIC X(3).
           05 WS-GL-DEBIT-TOTAL     PIC S9(13)V99 COMP-3.
           05 WS-GL-CREDIT-TOTAL    PIC S9(13)V99 COMP-3.
           05 WS-GL-NET-AMOUNT      PIC S9(13)V99 COMP-3.
           05 WS-GL-ENTRY-COUNT     PIC 9(7).
           05 WS-GL-POST-DATE       PIC X(10).
           05 WS-GL-BATCH-ID        PIC X(8).
           05 FILLER                PIC X(65).

Complete COBOL Reconciliation Program

       IDENTIFICATION DIVISION.
       PROGRAM-ID. RECONMCH.
      *================================================================*
      * RECONMCH - Daily Transaction Reconciliation Program            *
      * Matches transaction detail against GL summary entries.         *
      * Produces matched, unmatched, and exception report files.       *
      *================================================================*

       ENVIRONMENT DIVISION.
       INPUT-OUTPUT SECTION.
       FILE-CONTROL.
           SELECT TXN-DETAIL-FILE ASSIGN TO TXNDTL
               FILE STATUS IS WS-TXN-FS.
           SELECT GL-SUMMARY-FILE ASSIGN TO GLSUMM
               FILE STATUS IS WS-GL-FS.
           SELECT MATCHED-FILE    ASSIGN TO MATCHED
               FILE STATUS IS WS-MAT-FS.
           SELECT UNMATCHED-FILE  ASSIGN TO UNMATCH
               FILE STATUS IS WS-UNM-FS.
           SELECT EXCEPTION-RPT   ASSIGN TO EXCPRPT
               FILE STATUS IS WS-EXC-FS.

       DATA DIVISION.
       FILE SECTION.

       FD  TXN-DETAIL-FILE
           RECORDING MODE IS F
           RECORD CONTAINS 150 CHARACTERS.
       01  TXN-DETAIL-INPUT     PIC X(150).

       FD  GL-SUMMARY-FILE
           RECORDING MODE IS F
           RECORD CONTAINS 120 CHARACTERS.
       01  GL-SUMMARY-INPUT     PIC X(120).

       FD  MATCHED-FILE
           RECORDING MODE IS F
           RECORD CONTAINS 200 CHARACTERS.
       01  MATCHED-OUTPUT       PIC X(200).

       FD  UNMATCHED-FILE
           RECORDING MODE IS F
           RECORD CONTAINS 200 CHARACTERS.
       01  UNMATCHED-OUTPUT     PIC X(200).

       FD  EXCEPTION-RPT
           RECORDING MODE IS F
           RECORD CONTAINS 133 CHARACTERS.
       01  EXCEPTION-RPT-REC    PIC X(133).

       WORKING-STORAGE SECTION.

      *================================================================*
      * File status codes                                              *
      *================================================================*
       01  WS-TXN-FS            PIC XX VALUE '00'.
       01  WS-GL-FS             PIC XX VALUE '00'.
       01  WS-MAT-FS            PIC XX VALUE '00'.
       01  WS-UNM-FS            PIC XX VALUE '00'.
       01  WS-EXC-FS            PIC XX VALUE '00'.

      *================================================================*
      * Transaction detail record (working copy)                       *
      *================================================================*
       01  WS-TXN-DETAIL-REC.
           05 WS-TXN-ACCT-CATEGORY  PIC X(4).
           05 WS-TXN-TYPE-CODE      PIC X(3).
           05 WS-TXN-ACCT-NUM       PIC X(12).
           05 WS-TXN-DATE           PIC X(10).
           05 WS-TXN-SEQ-NUM        PIC 9(8).
           05 WS-TXN-AMOUNT         PIC S9(11)V99 COMP-3.
           05 WS-TXN-DR-CR-IND      PIC X(1).
              88 TXN-DEBIT                    VALUE 'D'.
              88 TXN-CREDIT                   VALUE 'C'.
           05 WS-TXN-DESCRIPTION    PIC X(40).
           05 WS-TXN-SOURCE-SYS     PIC X(3).
           05 WS-TXN-BRANCH         PIC X(4).
           05 WS-TXN-TELLER-ID      PIC X(6).
           05 FILLER                PIC X(53).

      *================================================================*
      * GL summary record (working copy)                               *
      *================================================================*
       01  WS-GL-SUMMARY-REC.
           05 WS-GL-ACCT-CATEGORY   PIC X(4).
           05 WS-GL-TYPE-CODE       PIC X(3).
           05 WS-GL-DEBIT-TOTAL     PIC S9(13)V99 COMP-3.
           05 WS-GL-CREDIT-TOTAL    PIC S9(13)V99 COMP-3.
           05 WS-GL-NET-AMOUNT      PIC S9(13)V99 COMP-3.
           05 WS-GL-ENTRY-COUNT     PIC 9(7).
           05 WS-GL-POST-DATE       PIC X(10).
           05 WS-GL-BATCH-ID        PIC X(8).
           05 FILLER                PIC X(65).

      *================================================================*
      * Composite keys for matching                                    *
      *================================================================*
       01  WS-TXN-MATCH-KEY.
           05 WS-TXN-KEY-CAT       PIC X(4).
           05 WS-TXN-KEY-TYPE      PIC X(3).

       01  WS-GL-MATCH-KEY.
           05 WS-GL-KEY-CAT        PIC X(4).
           05 WS-GL-KEY-TYPE       PIC X(3).

      *================================================================*
      * Accumulation fields for transaction group totals               *
      *================================================================*
       01  WS-GROUP-ACCUM.
           05 WS-GRP-DEBIT-TOTAL   PIC S9(13)V99 VALUE ZEROS.
           05 WS-GRP-CREDIT-TOTAL  PIC S9(13)V99 VALUE ZEROS.
           05 WS-GRP-NET-AMOUNT    PIC S9(13)V99 VALUE ZEROS.
           05 WS-GRP-ENTRY-COUNT   PIC 9(7)      VALUE ZEROS.

      *================================================================*
      * Reconciliation variance fields                                 *
      *================================================================*
       01  WS-VARIANCE.
           05 WS-VAR-DEBIT        PIC S9(13)V99  VALUE ZEROS.
           05 WS-VAR-CREDIT       PIC S9(13)V99  VALUE ZEROS.
           05 WS-VAR-NET          PIC S9(13)V99  VALUE ZEROS.
           05 WS-VAR-COUNT        PIC S9(7)      VALUE ZEROS.

      *================================================================*
      * Grand total fields                                             *
      *================================================================*
       01  WS-GRAND-TOTALS.
           05 WS-GT-TXN-DEBITS    PIC S9(15)V99  VALUE ZEROS.
           05 WS-GT-TXN-CREDITS   PIC S9(15)V99  VALUE ZEROS.
           05 WS-GT-TXN-NET       PIC S9(15)V99  VALUE ZEROS.
           05 WS-GT-TXN-COUNT     PIC 9(9)       VALUE ZEROS.
           05 WS-GT-GL-DEBITS     PIC S9(15)V99  VALUE ZEROS.
           05 WS-GT-GL-CREDITS    PIC S9(15)V99  VALUE ZEROS.
           05 WS-GT-GL-NET        PIC S9(15)V99  VALUE ZEROS.
           05 WS-GT-GL-COUNT      PIC 9(9)       VALUE ZEROS.
           05 WS-GT-MATCHED-AMT   PIC S9(15)V99  VALUE ZEROS.
           05 WS-GT-UNMATCHED-AMT PIC S9(15)V99  VALUE ZEROS.

      *================================================================*
      * Processing counters                                            *
      *================================================================*
       01  WS-CTR.
           05 WS-TXN-RECORDS-READ  PIC 9(9)      VALUE ZEROS.
           05 WS-GL-RECORDS-READ   PIC 9(7)      VALUE ZEROS.
           05 WS-MATCHED-GROUPS    PIC 9(7)      VALUE ZEROS.
           05 WS-UNMATCHED-TXN     PIC 9(7)      VALUE ZEROS.
           05 WS-UNMATCHED-GL      PIC 9(7)      VALUE ZEROS.
           05 WS-EXCEPTIONS        PIC 9(7)      VALUE ZEROS.
           05 WS-AUTO-CORRECTIONS  PIC 9(7)      VALUE ZEROS.
           05 WS-MANUAL-REVIEWS    PIC 9(7)      VALUE ZEROS.

      *================================================================*
      * Tolerance and thresholds                                       *
      *================================================================*
       01  WS-MATCH-TOLERANCE      PIC S9(3)V99 VALUE +0.01.
       01  WS-SUPERVISOR-THRESHOLD PIC S9(7)V99 VALUE +10000.00.
       01  WS-REVIEW-THRESHOLD     PIC S9(5)V99 VALUE +100.00.

      *================================================================*
      * EOF flags                                                      *
      *================================================================*
       01  WS-TXN-EOF             PIC X VALUE 'N'.
           88 TXN-AT-END                       VALUE 'Y'.
       01  WS-GL-EOF              PIC X VALUE 'N'.
           88 GL-AT-END                        VALUE 'Y'.

      *================================================================*
      * Match result output record                                     *
      *================================================================*
       01  WS-MATCH-RESULT-REC.
           05 WS-MR-RESULT-CODE    PIC X(1).
              88 MR-MATCHED                    VALUE 'M'.
              88 MR-UNMATCHED-TXN              VALUE 'T'.
              88 MR-UNMATCHED-GL               VALUE 'G'.
              88 MR-AUTO-CORRECTED             VALUE 'A'.
           05 WS-MR-ACCT-CATEGORY  PIC X(4).
           05 WS-MR-TYPE-CODE      PIC X(3).
           05 WS-MR-TXN-DEBIT      PIC S9(13)V99 COMP-3.
           05 WS-MR-TXN-CREDIT     PIC S9(13)V99 COMP-3.
           05 WS-MR-TXN-NET        PIC S9(13)V99 COMP-3.
           05 WS-MR-TXN-COUNT      PIC 9(7).
           05 WS-MR-GL-DEBIT       PIC S9(13)V99 COMP-3.
           05 WS-MR-GL-CREDIT      PIC S9(13)V99 COMP-3.
           05 WS-MR-GL-NET         PIC S9(13)V99 COMP-3.
           05 WS-MR-GL-COUNT       PIC 9(7).
           05 WS-MR-VARIANCE       PIC S9(13)V99 COMP-3.
           05 FILLER               PIC X(83).

      *================================================================*
      * Exception report lines                                        *
      *================================================================*
       01  WS-EXC-HEADER-1.
           05 FILLER  PIC X(1)  VALUE '1'.
           05 FILLER  PIC X(20) VALUE SPACES.
           05 FILLER  PIC X(50)
               VALUE 'HEARTLAND COMMUNITY BANK'.
           05 FILLER  PIC X(40) VALUE SPACES.
           05 FILLER  PIC X(6)  VALUE 'PAGE: '.
           05 WS-EXH-PAGE PIC Z(4)9.
           05 FILLER  PIC X(11) VALUE SPACES.

       01  WS-EXC-HEADER-2.
           05 FILLER  PIC X(1)  VALUE ' '.
           05 FILLER  PIC X(20) VALUE SPACES.
           05 FILLER  PIC X(50)
               VALUE 'DAILY RECONCILIATION EXCEPTION REPORT'.
           05 FILLER  PIC X(62) VALUE SPACES.

       01  WS-EXC-HEADER-3.
           05 FILLER  PIC X(1)  VALUE ' '.
           05 FILLER  PIC X(20) VALUE SPACES.
           05 FILLER  PIC X(14) VALUE 'Report Date:  '.
           05 WS-EXH-DATE PIC X(10).
           05 FILLER  PIC X(88) VALUE SPACES.

       01  WS-EXC-COL-HDR.
           05 FILLER  PIC X(1)  VALUE '0'.
           05 FILLER  PIC X(2)  VALUE SPACES.
           05 FILLER  PIC X(8)  VALUE 'CATEGORY'.
           05 FILLER  PIC X(2)  VALUE SPACES.
           05 FILLER  PIC X(6)  VALUE 'TYPE'.
           05 FILLER  PIC X(2)  VALUE SPACES.
           05 FILLER  PIC X(10) VALUE 'STATUS'.
           05 FILLER  PIC X(2)  VALUE SPACES.
           05 FILLER  PIC X(18) VALUE '    TXN AMOUNT'.
           05 FILLER  PIC X(2)  VALUE SPACES.
           05 FILLER  PIC X(18) VALUE '     GL AMOUNT'.
           05 FILLER  PIC X(2)  VALUE SPACES.
           05 FILLER  PIC X(18) VALUE '     VARIANCE'.
           05 FILLER  PIC X(2)  VALUE SPACES.
           05 FILLER  PIC X(10) VALUE 'ACTION'.
           05 FILLER  PIC X(30) VALUE SPACES.

       01  WS-EXC-DETAIL-LINE.
           05 FILLER      PIC X(1)  VALUE ' '.
           05 FILLER      PIC X(2)  VALUE SPACES.
           05 WS-EXD-CAT  PIC X(4).
           05 FILLER      PIC X(6)  VALUE SPACES.
           05 WS-EXD-TYPE PIC X(3).
           05 FILLER      PIC X(5)  VALUE SPACES.
           05 WS-EXD-STATUS PIC X(10).
           05 FILLER      PIC X(2)  VALUE SPACES.
           05 WS-EXD-TXN-AMT PIC $$$,$$$,MATH1$,$$9.99-.
           05 FILLER      PIC X(2)  VALUE SPACES.
           05 WS-EXD-GL-AMT PIC $$$,MATH3$,$$$,$$9.99-.
           05 FILLER      PIC X(2)  VALUE SPACES.
           05 WS-EXD-VARIANCE PIC $$$,$$$,MATH6$,$$9.99-.
           05 FILLER      PIC X(2)  VALUE SPACES.
           05 WS-EXD-ACTION PIC X(10).
           05 FILLER      PIC X(24) VALUE SPACES.

       01  WS-EXC-TOTAL-LINE.
           05 FILLER      PIC X(1)  VALUE '0'.
           05 FILLER      PIC X(2)  VALUE SPACES.
           05 WS-EXT-LABEL PIC X(30).
           05 FILLER      PIC X(2)  VALUE SPACES.
           05 WS-EXT-VALUE PIC $$$,MATH8$,$$$,$$$,$$9.99-.
           05 FILLER      PIC X(74) VALUE SPACES.

       01  WS-EXC-SEPARATOR.
           05 FILLER      PIC X(1) VALUE ' '.
           05 FILLER      PIC X(2) VALUE SPACES.
           05 FILLER      PIC X(120) VALUE ALL '-'.
           05 FILLER      PIC X(10) VALUE SPACES.

      *================================================================*
      * Report control                                                 *
      *================================================================*
       01  WS-RPT-PAGE-COUNT      PIC 9(5) VALUE ZEROS.
       01  WS-RPT-LINE-COUNT      PIC 99   VALUE 99.
       01  WS-RPT-LINES-PER-PAGE  PIC 99   VALUE 55.

      *================================================================*
      * Work fields                                                    *
      *================================================================*
       01  WS-ABS-VARIANCE        PIC S9(13)V99 VALUE ZEROS.
       01  WS-SYS-DATE            PIC 9(8).
       01  WS-REPORT-DATE         PIC X(10).
       01  WS-OUT-OF-BALANCE      PIC X VALUE 'N'.
           88 DAY-OUT-OF-BALANCE               VALUE 'Y'.

       PROCEDURE DIVISION.

       0000-MAIN-CONTROL.
           PERFORM 1000-INITIALIZE
           PERFORM 2000-RECONCILE
           PERFORM 3000-PROOF-OF-RECONCILIATION
           PERFORM 4000-PRINT-SUMMARY
           PERFORM 9000-WRAP-UP
           STOP RUN.

      *================================================================*
      * 1000-INITIALIZE: Open files, initialize fields, print         *
      * report header.                                                 *
      *================================================================*
       1000-INITIALIZE.
           OPEN INPUT  TXN-DETAIL-FILE
           OPEN INPUT  GL-SUMMARY-FILE
           OPEN OUTPUT MATCHED-FILE
           OPEN OUTPUT UNMATCHED-FILE
           OPEN OUTPUT EXCEPTION-RPT

           IF WS-TXN-FS NOT = '00'
               DISPLAY 'ERROR: Cannot open transaction file. '
                   'Status: ' WS-TXN-FS
               MOVE 16 TO RETURN-CODE
               STOP RUN
           END-IF

           IF WS-GL-FS NOT = '00'
               DISPLAY 'ERROR: Cannot open GL summary file. '
                   'Status: ' WS-GL-FS
               MOVE 16 TO RETURN-CODE
               STOP RUN
           END-IF

           ACCEPT WS-SYS-DATE FROM DATE YYYYMMDD
           STRING WS-SYS-DATE(1:4) '-'
                  WS-SYS-DATE(5:2) '-'
                  WS-SYS-DATE(7:2)
               DELIMITED SIZE INTO WS-REPORT-DATE

           DISPLAY '============================================='
           DISPLAY ' RECONMCH - Daily Reconciliation'
           DISPLAY ' Date: ' WS-REPORT-DATE
           DISPLAY '============================================='
           .

      *================================================================*
      * 2000-RECONCILE: Main matching logic. Uses a merge-match       *
      * algorithm on two sorted files. Both files are sorted by        *
      * account category and transaction type.                         *
      *                                                                *
      * Algorithm:                                                     *
      *   1. Read one record from each file (priming reads).           *
      *   2. Compare keys:                                             *
      *      - If TXN key = GL key: accumulate TXN group, match.      *
      *      - If TXN key < GL key: TXN has no GL match.              *
      *      - If TXN key > GL key: GL has no TXN match.              *
      *   3. Repeat until both files are exhausted.                    *
      *================================================================*
       2000-RECONCILE.
      *    Priming reads
           PERFORM 2010-READ-TXN-DETAIL
           PERFORM 2020-READ-GL-SUMMARY

      *    Main matching loop
           PERFORM UNTIL TXN-AT-END AND GL-AT-END

      *        Build TXN match key
               IF NOT TXN-AT-END
                   MOVE WS-TXN-ACCT-CATEGORY TO WS-TXN-KEY-CAT
                   MOVE WS-TXN-TYPE-CODE     TO WS-TXN-KEY-TYPE
               END-IF

      *        Build GL match key
               IF NOT GL-AT-END
                   MOVE WS-GL-ACCT-CATEGORY  TO WS-GL-KEY-CAT
                   MOVE WS-GL-TYPE-CODE      TO WS-GL-KEY-TYPE
               END-IF

               EVALUATE TRUE
      *            Both files exhausted
                   WHEN TXN-AT-END AND GL-AT-END
                       CONTINUE

      *            TXN file exhausted: remaining GL records unmatched
                   WHEN TXN-AT-END
                       PERFORM 2300-GL-NO-MATCH
                       PERFORM 2020-READ-GL-SUMMARY

      *            GL file exhausted: remaining TXN records unmatched
                   WHEN GL-AT-END
                       PERFORM 2400-ACCUMULATE-TXN-GROUP
                       PERFORM 2200-TXN-NO-MATCH

      *            Keys match: accumulate TXN group and compare
                   WHEN WS-TXN-MATCH-KEY = WS-GL-MATCH-KEY
                       PERFORM 2400-ACCUMULATE-TXN-GROUP
                       PERFORM 2100-COMPARE-MATCH
                       PERFORM 2020-READ-GL-SUMMARY

      *            TXN key is lower: TXN group has no GL entry
                   WHEN WS-TXN-MATCH-KEY < WS-GL-MATCH-KEY
                       PERFORM 2400-ACCUMULATE-TXN-GROUP
                       PERFORM 2200-TXN-NO-MATCH

      *            GL key is lower: GL entry has no TXN detail
                   WHEN WS-TXN-MATCH-KEY > WS-GL-MATCH-KEY
                       PERFORM 2300-GL-NO-MATCH
                       PERFORM 2020-READ-GL-SUMMARY
               END-EVALUATE
           END-PERFORM
           .

      *================================================================*
      * 2010-READ-TXN-DETAIL: Read next transaction detail record.    *
      *================================================================*
       2010-READ-TXN-DETAIL.
           READ TXN-DETAIL-FILE INTO WS-TXN-DETAIL-REC
               AT END
                   MOVE 'Y' TO WS-TXN-EOF
               NOT AT END
                   ADD 1 TO WS-TXN-RECORDS-READ
           END-READ
           .

      *================================================================*
      * 2020-READ-GL-SUMMARY: Read next GL summary record.            *
      *================================================================*
       2020-READ-GL-SUMMARY.
           READ GL-SUMMARY-FILE INTO WS-GL-SUMMARY-REC
               AT END
                   MOVE 'Y' TO WS-GL-EOF
               NOT AT END
                   ADD 1 TO WS-GL-RECORDS-READ
                   ADD WS-GL-DEBIT-TOTAL  TO WS-GT-GL-DEBITS
                   ADD WS-GL-CREDIT-TOTAL TO WS-GT-GL-CREDITS
                   ADD WS-GL-NET-AMOUNT   TO WS-GT-GL-NET
                   ADD WS-GL-ENTRY-COUNT  TO WS-GT-GL-COUNT
           END-READ
           .

      *================================================================*
      * 2400-ACCUMULATE-TXN-GROUP: Read all transaction detail        *
      * records with the same category/type key and accumulate        *
      * their totals. This builds the aggregated TXN total to         *
      * compare against the GL summary record.                         *
      *================================================================*
       2400-ACCUMULATE-TXN-GROUP.
           MOVE ZEROS TO WS-GROUP-ACCUM
           MOVE WS-TXN-ACCT-CATEGORY TO WS-TXN-KEY-CAT
           MOVE WS-TXN-TYPE-CODE     TO WS-TXN-KEY-TYPE

           PERFORM UNTIL TXN-AT-END
               OR WS-TXN-ACCT-CATEGORY NOT = WS-TXN-KEY-CAT
               OR WS-TXN-TYPE-CODE NOT = WS-TXN-KEY-TYPE

               IF TXN-DEBIT
                   ADD WS-TXN-AMOUNT TO WS-GRP-DEBIT-TOTAL
               ELSE
                   ADD WS-TXN-AMOUNT TO WS-GRP-CREDIT-TOTAL
               END-IF
               ADD 1 TO WS-GRP-ENTRY-COUNT

               ADD WS-TXN-AMOUNT TO WS-GT-TXN-NET
               IF TXN-DEBIT
                   ADD WS-TXN-AMOUNT TO WS-GT-TXN-DEBITS
               ELSE
                   ADD WS-TXN-AMOUNT TO WS-GT-TXN-CREDITS
               END-IF
               ADD 1 TO WS-GT-TXN-COUNT

               PERFORM 2010-READ-TXN-DETAIL
           END-PERFORM

           COMPUTE WS-GRP-NET-AMOUNT =
               WS-GRP-DEBIT-TOTAL - WS-GRP-CREDIT-TOTAL
           .

      *================================================================*
      * 2100-COMPARE-MATCH: Compare accumulated TXN group totals     *
      * against the GL summary record. Determine if they match        *
      * within tolerance.                                              *
      *================================================================*
       2100-COMPARE-MATCH.
           COMPUTE WS-VAR-NET =
               WS-GRP-NET-AMOUNT - WS-GL-NET-AMOUNT
           COMPUTE WS-VAR-DEBIT =
               WS-GRP-DEBIT-TOTAL - WS-GL-DEBIT-TOTAL
           COMPUTE WS-VAR-CREDIT =
               WS-GRP-CREDIT-TOTAL - WS-GL-CREDIT-TOTAL
           COMPUTE WS-VAR-COUNT =
               WS-GRP-ENTRY-COUNT - WS-GL-ENTRY-COUNT

      *    Compute absolute value of net variance
           IF WS-VAR-NET < ZEROS
               COMPUTE WS-ABS-VARIANCE =
                   WS-VAR-NET * -1
           ELSE
               MOVE WS-VAR-NET TO WS-ABS-VARIANCE
           END-IF

           EVALUATE TRUE
      *        Exact match
               WHEN WS-ABS-VARIANCE = ZEROS
                   PERFORM 2110-WRITE-MATCHED
                   ADD 1 TO WS-MATCHED-GROUPS
                   ADD WS-GRP-NET-AMOUNT
                       TO WS-GT-MATCHED-AMT

      *        Within tolerance - auto-correct
               WHEN WS-ABS-VARIANCE <= WS-MATCH-TOLERANCE
                   PERFORM 2120-AUTO-CORRECT
                   ADD 1 TO WS-MATCHED-GROUPS
                   ADD 1 TO WS-AUTO-CORRECTIONS
                   ADD WS-GRP-NET-AMOUNT
                       TO WS-GT-MATCHED-AMT

      *        Out of tolerance - exception
               WHEN OTHER
                   PERFORM 2130-WRITE-EXCEPTION
                   ADD 1 TO WS-EXCEPTIONS
                   ADD WS-VAR-NET
                       TO WS-GT-UNMATCHED-AMT
           END-EVALUATE
           .

      *================================================================*
      * 2110-WRITE-MATCHED: Write a matched result record.            *
      *================================================================*
       2110-WRITE-MATCHED.
           INITIALIZE WS-MATCH-RESULT-REC
           MOVE 'M'                TO WS-MR-RESULT-CODE
           MOVE WS-TXN-KEY-CAT    TO WS-MR-ACCT-CATEGORY
           MOVE WS-TXN-KEY-TYPE   TO WS-MR-TYPE-CODE
           MOVE WS-GRP-DEBIT-TOTAL TO WS-MR-TXN-DEBIT
           MOVE WS-GRP-CREDIT-TOTAL TO WS-MR-TXN-CREDIT
           MOVE WS-GRP-NET-AMOUNT TO WS-MR-TXN-NET
           MOVE WS-GRP-ENTRY-COUNT TO WS-MR-TXN-COUNT
           MOVE WS-GL-DEBIT-TOTAL TO WS-MR-GL-DEBIT
           MOVE WS-GL-CREDIT-TOTAL TO WS-MR-GL-CREDIT
           MOVE WS-GL-NET-AMOUNT  TO WS-MR-GL-NET
           MOVE WS-GL-ENTRY-COUNT TO WS-MR-GL-COUNT
           MOVE ZEROS             TO WS-MR-VARIANCE

           WRITE MATCHED-OUTPUT FROM WS-MATCH-RESULT-REC
           .

      *================================================================*
      * 2120-AUTO-CORRECT: Rounding variance within tolerance.        *
      * Write as matched with auto-correction notation.                *
      *================================================================*
       2120-AUTO-CORRECT.
           INITIALIZE WS-MATCH-RESULT-REC
           MOVE 'A'                TO WS-MR-RESULT-CODE
           MOVE WS-TXN-KEY-CAT    TO WS-MR-ACCT-CATEGORY
           MOVE WS-TXN-KEY-TYPE   TO WS-MR-TYPE-CODE
           MOVE WS-GRP-DEBIT-TOTAL TO WS-MR-TXN-DEBIT
           MOVE WS-GRP-CREDIT-TOTAL TO WS-MR-TXN-CREDIT
           MOVE WS-GRP-NET-AMOUNT TO WS-MR-TXN-NET
           MOVE WS-GRP-ENTRY-COUNT TO WS-MR-TXN-COUNT
           MOVE WS-GL-DEBIT-TOTAL TO WS-MR-GL-DEBIT
           MOVE WS-GL-CREDIT-TOTAL TO WS-MR-GL-CREDIT
           MOVE WS-GL-NET-AMOUNT  TO WS-MR-GL-NET
           MOVE WS-GL-ENTRY-COUNT TO WS-MR-GL-COUNT
           MOVE WS-VAR-NET        TO WS-MR-VARIANCE

           WRITE MATCHED-OUTPUT FROM WS-MATCH-RESULT-REC

      *    Log auto-correction on exception report
           PERFORM 5100-PRINT-PAGE-HEADER-CHECK
           MOVE WS-TXN-KEY-CAT     TO WS-EXD-CAT
           MOVE WS-TXN-KEY-TYPE    TO WS-EXD-TYPE
           MOVE 'AUTO-CORR ' TO WS-EXD-STATUS
           MOVE WS-GRP-NET-AMOUNT  TO WS-EXD-TXN-AMT
           MOVE WS-GL-NET-AMOUNT   TO WS-EXD-GL-AMT
           MOVE WS-VAR-NET         TO WS-EXD-VARIANCE
           MOVE 'ADJUSTED  ' TO WS-EXD-ACTION
           WRITE EXCEPTION-RPT-REC FROM WS-EXC-DETAIL-LINE
           ADD 1 TO WS-RPT-LINE-COUNT
           .

      *================================================================*
      * 2130-WRITE-EXCEPTION: Variance exceeds tolerance. Write to   *
      * unmatched file and exception report. Determine action based   *
      * on severity.                                                   *
      *================================================================*
       2130-WRITE-EXCEPTION.
           INITIALIZE WS-MATCH-RESULT-REC
           MOVE 'T'                TO WS-MR-RESULT-CODE
           MOVE WS-TXN-KEY-CAT    TO WS-MR-ACCT-CATEGORY
           MOVE WS-TXN-KEY-TYPE   TO WS-MR-TYPE-CODE
           MOVE WS-GRP-DEBIT-TOTAL TO WS-MR-TXN-DEBIT
           MOVE WS-GRP-CREDIT-TOTAL TO WS-MR-TXN-CREDIT
           MOVE WS-GRP-NET-AMOUNT TO WS-MR-TXN-NET
           MOVE WS-GRP-ENTRY-COUNT TO WS-MR-TXN-COUNT
           MOVE WS-GL-DEBIT-TOTAL TO WS-MR-GL-DEBIT
           MOVE WS-GL-CREDIT-TOTAL TO WS-MR-GL-CREDIT
           MOVE WS-GL-NET-AMOUNT  TO WS-MR-GL-NET
           MOVE WS-GL-ENTRY-COUNT TO WS-MR-GL-COUNT
           MOVE WS-VAR-NET        TO WS-MR-VARIANCE

           WRITE UNMATCHED-OUTPUT FROM WS-MATCH-RESULT-REC

      *    Print exception with appropriate action
           PERFORM 5100-PRINT-PAGE-HEADER-CHECK

           MOVE WS-TXN-KEY-CAT     TO WS-EXD-CAT
           MOVE WS-TXN-KEY-TYPE    TO WS-EXD-TYPE
           MOVE 'VARIANCE  ' TO WS-EXD-STATUS
           MOVE WS-GRP-NET-AMOUNT  TO WS-EXD-TXN-AMT
           MOVE WS-GL-NET-AMOUNT   TO WS-EXD-GL-AMT
           MOVE WS-VAR-NET         TO WS-EXD-VARIANCE

      *    Determine action based on variance magnitude
           IF WS-ABS-VARIANCE > WS-SUPERVISOR-THRESHOLD
               MOVE 'SUPERVISOR' TO WS-EXD-ACTION
               ADD 1 TO WS-MANUAL-REVIEWS
           ELSE IF WS-ABS-VARIANCE > WS-REVIEW-THRESHOLD
               MOVE 'REVIEW    ' TO WS-EXD-ACTION
               ADD 1 TO WS-MANUAL-REVIEWS
           ELSE
               MOVE 'LOG ONLY  ' TO WS-EXD-ACTION
           END-IF

           WRITE EXCEPTION-RPT-REC FROM WS-EXC-DETAIL-LINE
           ADD 1 TO WS-RPT-LINE-COUNT

           MOVE 'Y' TO WS-OUT-OF-BALANCE
           .

      *================================================================*
      * 2200-TXN-NO-MATCH: Transaction group has no corresponding    *
      * GL entry. Write to unmatched file.                             *
      *================================================================*
       2200-TXN-NO-MATCH.
           ADD 1 TO WS-UNMATCHED-TXN
           ADD 1 TO WS-EXCEPTIONS

           INITIALIZE WS-MATCH-RESULT-REC
           MOVE 'T'                TO WS-MR-RESULT-CODE
           MOVE WS-TXN-KEY-CAT    TO WS-MR-ACCT-CATEGORY
           MOVE WS-TXN-KEY-TYPE   TO WS-MR-TYPE-CODE
           MOVE WS-GRP-DEBIT-TOTAL TO WS-MR-TXN-DEBIT
           MOVE WS-GRP-CREDIT-TOTAL TO WS-MR-TXN-CREDIT
           MOVE WS-GRP-NET-AMOUNT TO WS-MR-TXN-NET
           MOVE WS-GRP-ENTRY-COUNT TO WS-MR-TXN-COUNT
           MOVE ZEROS             TO WS-MR-GL-DEBIT
           MOVE ZEROS             TO WS-MR-GL-CREDIT
           MOVE ZEROS             TO WS-MR-GL-NET
           MOVE ZEROS             TO WS-MR-GL-COUNT
           MOVE WS-GRP-NET-AMOUNT TO WS-MR-VARIANCE

           WRITE UNMATCHED-OUTPUT FROM WS-MATCH-RESULT-REC

           ADD WS-GRP-NET-AMOUNT TO WS-GT-UNMATCHED-AMT

      *    Exception report
           PERFORM 5100-PRINT-PAGE-HEADER-CHECK
           MOVE WS-TXN-KEY-CAT    TO WS-EXD-CAT
           MOVE WS-TXN-KEY-TYPE   TO WS-EXD-TYPE
           MOVE 'NO GL ENT ' TO WS-EXD-STATUS
           MOVE WS-GRP-NET-AMOUNT TO WS-EXD-TXN-AMT
           MOVE ZEROS             TO WS-EXD-GL-AMT
           MOVE WS-GRP-NET-AMOUNT TO WS-EXD-VARIANCE
           MOVE 'SUPERVISOR' TO WS-EXD-ACTION
           ADD 1 TO WS-MANUAL-REVIEWS

           WRITE EXCEPTION-RPT-REC FROM WS-EXC-DETAIL-LINE
           ADD 1 TO WS-RPT-LINE-COUNT

           MOVE 'Y' TO WS-OUT-OF-BALANCE
           .

      *================================================================*
      * 2300-GL-NO-MATCH: GL entry has no corresponding transaction  *
      * detail. Write to unmatched file.                               *
      *================================================================*
       2300-GL-NO-MATCH.
           ADD 1 TO WS-UNMATCHED-GL
           ADD 1 TO WS-EXCEPTIONS

           INITIALIZE WS-MATCH-RESULT-REC
           MOVE 'G'                TO WS-MR-RESULT-CODE
           MOVE WS-GL-ACCT-CATEGORY TO WS-MR-ACCT-CATEGORY
           MOVE WS-GL-TYPE-CODE    TO WS-MR-TYPE-CODE
           MOVE ZEROS             TO WS-MR-TXN-DEBIT
           MOVE ZEROS             TO WS-MR-TXN-CREDIT
           MOVE ZEROS             TO WS-MR-TXN-NET
           MOVE ZEROS             TO WS-MR-TXN-COUNT
           MOVE WS-GL-DEBIT-TOTAL TO WS-MR-GL-DEBIT
           MOVE WS-GL-CREDIT-TOTAL TO WS-MR-GL-CREDIT
           MOVE WS-GL-NET-AMOUNT  TO WS-MR-GL-NET
           MOVE WS-GL-ENTRY-COUNT TO WS-MR-GL-COUNT
           COMPUTE WS-MR-VARIANCE =
               ZEROS - WS-GL-NET-AMOUNT

           WRITE UNMATCHED-OUTPUT FROM WS-MATCH-RESULT-REC

           COMPUTE WS-ABS-VARIANCE =
               WS-GL-NET-AMOUNT * -1
           IF WS-GL-NET-AMOUNT > ZEROS
               MOVE WS-GL-NET-AMOUNT TO WS-ABS-VARIANCE
           END-IF
           ADD WS-ABS-VARIANCE TO WS-GT-UNMATCHED-AMT

      *    Exception report
           PERFORM 5100-PRINT-PAGE-HEADER-CHECK
           MOVE WS-GL-ACCT-CATEGORY TO WS-EXD-CAT
           MOVE WS-GL-TYPE-CODE    TO WS-EXD-TYPE
           MOVE 'NO TXN DET' TO WS-EXD-STATUS
           MOVE ZEROS             TO WS-EXD-TXN-AMT
           MOVE WS-GL-NET-AMOUNT  TO WS-EXD-GL-AMT
           COMPUTE WS-EXD-VARIANCE =
               ZEROS - WS-GL-NET-AMOUNT
           MOVE 'SUPERVISOR' TO WS-EXD-ACTION
           ADD 1 TO WS-MANUAL-REVIEWS

           WRITE EXCEPTION-RPT-REC FROM WS-EXC-DETAIL-LINE
           ADD 1 TO WS-RPT-LINE-COUNT

           MOVE 'Y' TO WS-OUT-OF-BALANCE
           .

      *================================================================*
      * 3000-PROOF-OF-RECONCILIATION: Verify that matched plus       *
      * unmatched equals the original total. This is the auditor's    *
      * proof that the reconciliation is complete.                     *
      *================================================================*
       3000-PROOF-OF-RECONCILIATION.
           PERFORM 5100-PRINT-PAGE-HEADER-CHECK

           WRITE EXCEPTION-RPT-REC FROM WS-EXC-SEPARATOR

           INITIALIZE WS-EXC-DETAIL-LINE
           MOVE ' ' TO WS-EXC-DETAIL-LINE(1:1)
           MOVE 'PROOF OF RECONCILIATION'
               TO WS-EXC-DETAIL-LINE(4:30)
           WRITE EXCEPTION-RPT-REC FROM WS-EXC-DETAIL-LINE

           WRITE EXCEPTION-RPT-REC FROM WS-EXC-SEPARATOR

      *    TXN totals
           MOVE 'Total Transaction Debits:  '
               TO WS-EXT-LABEL
           MOVE WS-GT-TXN-DEBITS TO WS-EXT-VALUE
           WRITE EXCEPTION-RPT-REC FROM WS-EXC-TOTAL-LINE
           ADD 1 TO WS-RPT-LINE-COUNT

           MOVE 'Total Transaction Credits: '
               TO WS-EXT-LABEL
           MOVE WS-GT-TXN-CREDITS TO WS-EXT-VALUE
           WRITE EXCEPTION-RPT-REC FROM WS-EXC-TOTAL-LINE
           ADD 1 TO WS-RPT-LINE-COUNT

           MOVE 'Transaction Net:           '
               TO WS-EXT-LABEL
           MOVE WS-GT-TXN-NET TO WS-EXT-VALUE
           WRITE EXCEPTION-RPT-REC FROM WS-EXC-TOTAL-LINE
           ADD 1 TO WS-RPT-LINE-COUNT

           WRITE EXCEPTION-RPT-REC FROM WS-EXC-SEPARATOR

      *    GL totals
           MOVE 'Total GL Debits:           '
               TO WS-EXT-LABEL
           MOVE WS-GT-GL-DEBITS TO WS-EXT-VALUE
           WRITE EXCEPTION-RPT-REC FROM WS-EXC-TOTAL-LINE
           ADD 1 TO WS-RPT-LINE-COUNT

           MOVE 'Total GL Credits:          '
               TO WS-EXT-LABEL
           MOVE WS-GT-GL-CREDITS TO WS-EXT-VALUE
           WRITE EXCEPTION-RPT-REC FROM WS-EXC-TOTAL-LINE
           ADD 1 TO WS-RPT-LINE-COUNT

           MOVE 'GL Net:                    '
               TO WS-EXT-LABEL
           MOVE WS-GT-GL-NET TO WS-EXT-VALUE
           WRITE EXCEPTION-RPT-REC FROM WS-EXC-TOTAL-LINE
           ADD 1 TO WS-RPT-LINE-COUNT

           WRITE EXCEPTION-RPT-REC FROM WS-EXC-SEPARATOR

      *    Reconciliation proof
           MOVE 'Matched Amount:            '
               TO WS-EXT-LABEL
           MOVE WS-GT-MATCHED-AMT TO WS-EXT-VALUE
           WRITE EXCEPTION-RPT-REC FROM WS-EXC-TOTAL-LINE
           ADD 1 TO WS-RPT-LINE-COUNT

           MOVE 'Unmatched Amount:          '
               TO WS-EXT-LABEL
           MOVE WS-GT-UNMATCHED-AMT TO WS-EXT-VALUE
           WRITE EXCEPTION-RPT-REC FROM WS-EXC-TOTAL-LINE
           ADD 1 TO WS-RPT-LINE-COUNT

           WRITE EXCEPTION-RPT-REC FROM WS-EXC-SEPARATOR

      *    Overall balance check
           IF DAY-OUT-OF-BALANCE
               INITIALIZE WS-EXC-DETAIL-LINE
               MOVE '0' TO WS-EXC-DETAIL-LINE(1:1)
               MOVE '*** DAY IS OUT OF BALANCE ***'
                   TO WS-EXC-DETAIL-LINE(4:35)
               MOVE 'IMMEDIATE REVIEW REQUIRED'
                   TO WS-EXC-DETAIL-LINE(40:30)
               WRITE EXCEPTION-RPT-REC FROM WS-EXC-DETAIL-LINE
           ELSE
               INITIALIZE WS-EXC-DETAIL-LINE
               MOVE '0' TO WS-EXC-DETAIL-LINE(1:1)
               MOVE 'DAY IS IN BALANCE - RECONCILIATION COMPLETE'
                   TO WS-EXC-DETAIL-LINE(4:45)
               WRITE EXCEPTION-RPT-REC FROM WS-EXC-DETAIL-LINE
           END-IF
           .

      *================================================================*
      * 4000-PRINT-SUMMARY: Print processing statistics on the        *
      * exception report.                                              *
      *================================================================*
       4000-PRINT-SUMMARY.
           WRITE EXCEPTION-RPT-REC FROM WS-EXC-SEPARATOR

           INITIALIZE WS-EXC-DETAIL-LINE
           MOVE '0' TO WS-EXC-DETAIL-LINE(1:1)
           MOVE 'PROCESSING STATISTICS'
               TO WS-EXC-DETAIL-LINE(4:25)
           WRITE EXCEPTION-RPT-REC FROM WS-EXC-DETAIL-LINE

           INITIALIZE WS-EXC-DETAIL-LINE
           STRING '  TXN Records Read:    '
               WS-TXN-RECORDS-READ
               DELIMITED SIZE INTO WS-EXC-DETAIL-LINE(2:50)
           WRITE EXCEPTION-RPT-REC FROM WS-EXC-DETAIL-LINE

           INITIALIZE WS-EXC-DETAIL-LINE
           STRING '  GL Records Read:     '
               WS-GL-RECORDS-READ
               DELIMITED SIZE INTO WS-EXC-DETAIL-LINE(2:50)
           WRITE EXCEPTION-RPT-REC FROM WS-EXC-DETAIL-LINE

           INITIALIZE WS-EXC-DETAIL-LINE
           STRING '  Matched Groups:      '
               WS-MATCHED-GROUPS
               DELIMITED SIZE INTO WS-EXC-DETAIL-LINE(2:50)
           WRITE EXCEPTION-RPT-REC FROM WS-EXC-DETAIL-LINE

           INITIALIZE WS-EXC-DETAIL-LINE
           STRING '  Unmatched TXN Groups:'
               WS-UNMATCHED-TXN
               DELIMITED SIZE INTO WS-EXC-DETAIL-LINE(2:50)
           WRITE EXCEPTION-RPT-REC FROM WS-EXC-DETAIL-LINE

           INITIALIZE WS-EXC-DETAIL-LINE
           STRING '  Unmatched GL Entries:'
               WS-UNMATCHED-GL
               DELIMITED SIZE INTO WS-EXC-DETAIL-LINE(2:50)
           WRITE EXCEPTION-RPT-REC FROM WS-EXC-DETAIL-LINE

           INITIALIZE WS-EXC-DETAIL-LINE
           STRING '  Total Exceptions:    '
               WS-EXCEPTIONS
               DELIMITED SIZE INTO WS-EXC-DETAIL-LINE(2:50)
           WRITE EXCEPTION-RPT-REC FROM WS-EXC-DETAIL-LINE

           INITIALIZE WS-EXC-DETAIL-LINE
           STRING '  Auto-Corrections:    '
               WS-AUTO-CORRECTIONS
               DELIMITED SIZE INTO WS-EXC-DETAIL-LINE(2:50)
           WRITE EXCEPTION-RPT-REC FROM WS-EXC-DETAIL-LINE

           INITIALIZE WS-EXC-DETAIL-LINE
           STRING '  Manual Reviews:      '
               WS-MANUAL-REVIEWS
               DELIMITED SIZE INTO WS-EXC-DETAIL-LINE(2:50)
           WRITE EXCEPTION-RPT-REC FROM WS-EXC-DETAIL-LINE
           .

      *================================================================*
      * 5100-PRINT-PAGE-HEADER-CHECK: Print header if new page.      *
      *================================================================*
       5100-PRINT-PAGE-HEADER-CHECK.
           IF WS-RPT-LINE-COUNT >= WS-RPT-LINES-PER-PAGE
               ADD 1 TO WS-RPT-PAGE-COUNT
               MOVE WS-RPT-PAGE-COUNT TO WS-EXH-PAGE
               MOVE WS-REPORT-DATE    TO WS-EXH-DATE
               WRITE EXCEPTION-RPT-REC FROM WS-EXC-HEADER-1
               WRITE EXCEPTION-RPT-REC FROM WS-EXC-HEADER-2
               WRITE EXCEPTION-RPT-REC FROM WS-EXC-HEADER-3
               WRITE EXCEPTION-RPT-REC FROM WS-EXC-COL-HDR
               WRITE EXCEPTION-RPT-REC FROM WS-EXC-SEPARATOR
               MOVE 6 TO WS-RPT-LINE-COUNT
           END-IF
           .

      *================================================================*
      * 9000-WRAP-UP: Close files, set return code, display summary.  *
      *================================================================*
       9000-WRAP-UP.
           CLOSE TXN-DETAIL-FILE
           CLOSE GL-SUMMARY-FILE
           CLOSE MATCHED-FILE
           CLOSE UNMATCHED-FILE
           CLOSE EXCEPTION-RPT

           DISPLAY ' '
           DISPLAY '============================================='
           DISPLAY ' RECONMCH - RECONCILIATION COMPLETE'
           DISPLAY '   TXN Records:         '
               WS-TXN-RECORDS-READ
           DISPLAY '   GL Records:          '
               WS-GL-RECORDS-READ
           DISPLAY '   Matched Groups:      '
               WS-MATCHED-GROUPS
           DISPLAY '   Exceptions:          '
               WS-EXCEPTIONS
           DISPLAY '   Auto-Corrections:    '
               WS-AUTO-CORRECTIONS
           DISPLAY '   Manual Reviews:      '
               WS-MANUAL-REVIEWS

           IF DAY-OUT-OF-BALANCE
               DISPLAY '   *** OUT OF BALANCE ***'
               DISPLAY '============================================='
               MOVE 8 TO RETURN-CODE
           ELSE
               IF WS-EXCEPTIONS > ZEROS
                   DISPLAY '   In balance with exceptions.'
                   DISPLAY
                       '============================================='
                   MOVE 4 TO RETURN-CODE
               ELSE
                   DISPLAY '   In balance - clean reconciliation.'
                   DISPLAY
                       '============================================='
                   MOVE 0 TO RETURN-CODE
               END-IF
           END-IF
           .

Solution Walkthrough

The Merge-Match Algorithm

The reconciliation program uses a classic merge-match algorithm, the same pattern used in tape-era COBOL for matching two sorted files. The algorithm depends on both files being sorted by the same key (account category + transaction type).

The logic works as follows:

  1. Read one record from each file (priming reads).
  2. Compare the keys from the two files.
  3. If the keys are equal, the records potentially match -- accumulate the transaction detail group and compare totals.
  4. If the transaction key is less than the GL key, the transaction group has no corresponding GL entry (an exception).
  5. If the GL key is less than the transaction key, the GL entry has no corresponding transaction detail (an exception).
  6. Advance the file(s) as appropriate and repeat.

This algorithm makes a single pass through both files (O(n + m) complexity), making it highly efficient for large datasets. The key requirement is that both files must be sorted identically. If the sort order is wrong, the algorithm produces incorrect results without any obvious error.

Transaction Group Accumulation

A critical design element is that the transaction detail file contains individual transactions (one per record), while the GL summary file contains aggregated totals (one record per category/type combination). Before comparing, the program must accumulate all transaction records for a given category/type into group totals.

The accumulation loop in 2400-ACCUMULATE-TXN-GROUP reads forward through the transaction file until the key changes, summing debits and credits separately. This accumulated total is then compared against the single GL summary record for that key.

Exception Classification

The program classifies exceptions by severity, determining the appropriate workflow action:

Variance Amount Action Workflow
$0.00 None Exact match
$0.01 or less Auto-correct Logged, no human action
$0.02 - $99.99 Log only Documented, no escalation
$100.00 - $9,999.99 Review Next-day review by accounting
$10,000.00+ Supervisor Immediate supervisor notification
No GL entry for TXN Supervisor Always escalated
No TXN for GL entry Supervisor Always escalated

This tiered approach ensures that trivial discrepancies (common in systems with rounding differences across multiple applications) do not overwhelm the accounting team, while significant discrepancies receive prompt attention.

Proof of Reconciliation

The proof of reconciliation is the auditor's validation that the reconciliation is complete and accurate. It verifies the fundamental equation:

Matched Amount + Unmatched Amount = Total Transaction Amount

If this equation does not balance, the reconciliation program itself has a bug -- some transactions were lost, double-counted, or misclassified during the matching process. The proof section on the exception report allows auditors to verify this independently.

Return Code Strategy

The program uses a tiered return code strategy:

  • RC=0: Clean reconciliation, no exceptions.
  • RC=4: In balance overall, but exceptions exist that need review. This is the most common outcome in practice, as minor timing differences are normal.
  • RC=8: Out of balance. This triggers the NOTIFY step in the job stream to alert operations.
  • RC=16: File open error or other fatal condition. Not reached in normal operation.

The JCL uses COND=(4,LT,RCMATCH) for subsequent steps, which means they execute if RC is 0 or 4 (normal or warning) but not if RC is 8 or higher.

Automated vs. Manual Correction Workflow

The distinction between automated and manual corrections is essential to the bank's internal controls:

Automated corrections (rounding adjustments) are applied by the program itself. They are fully documented in the audit trail with the auto-correction flag. Internal audit reviews these periodically to ensure the auto-correction logic is not masking real problems.

Manual corrections are not applied by this program. Instead, the exception report identifies items requiring human review, and the accounting team investigates each one during the next business day. If a correction is needed, the accountant creates a journal entry through the bank's GL posting system, which will appear in the next day's reconciliation.

This separation of automated and manual processing is a fundamental internal control requirement. No batch program should have the authority to make arbitrary corrections to the general ledger. The auto-correction authority is strictly limited to the defined tolerance ($0.01).

Discussion Questions

  1. The merge-match algorithm requires both input files to be sorted by the same key. What would happen if the transaction file were sorted by account category ascending but the GL file were sorted by account category descending? Would the program detect this, or would it silently produce wrong results? How would you add sort-order validation?

  2. The auto-correction tolerance is set at $0.01. In a system processing millions of transactions daily, even a $0.01 rounding difference per transaction could accumulate into a significant amount. How would you monitor and control the cumulative auto-correction amount over time? At what point should auto-corrections trigger an investigation?

  3. The exception report is a print file (SYSOUT class H). In a modern banking environment, exception data might need to flow into a case management system for tracking and resolution. How would you redesign the exception output to support both a print report and a structured data feed to a downstream system?

  4. The program accumulates grand totals for the proof of reconciliation. If the transaction file contains billions of dollars in daily activity, the accumulator fields need to be large enough to hold the total. What is the maximum value that PIC S9(15)V99 can hold? At what point would this field overflow, and how should the program detect and handle accumulator overflow?

  5. Consider a scenario where a transaction was posted to the wrong account category. The transaction detail would show it in category A, but the GL entry would be in category B. How would this manifest in the reconciliation results? Category A would have an unmatched TXN group, and category B would have an unmatched GL entry. How would an investigator connect these two exceptions to identify the root cause?

  6. The program produces three separate output files (matched, unmatched, exception report). Argue for or against consolidating these into a single output file with a status indicator. What are the trade-offs in terms of downstream processing, storage efficiency, and operational usability?