feat: add benchmark-programs — 58 telecom COBOL test programs

作为子目录纳入系统,与核心测试管道协同

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
NB-076
2026-06-25 09:53:21 +08:00
parent 50f9f0f52f
commit 94400d50d4
278 changed files with 44125 additions and 0 deletions
@@ -0,0 +1,888 @@
*> ============================================================
*> 33-mix-1N-diffkeybreak : 线路+类型切替 (Line+Type Change)
*> Input : FILE-MAST (diff-master.dat: 线路), FILE-DETL (diff-detail.dat: 类型)
*> Output: FILE-OUT (diff-match-output.txt: 切替检测结果)
*> AUDIT-OUT (audit-33.log: 审计跟踪)
*> Coverage: AM-N007, MT-R001
*> Version : 2.0 — Expanded with audit, hash totals, FILE STATUS
*> ============================================================
IDENTIFICATION DIVISION.
PROGRAM-ID. Main33Mix1NDiffKeyBreak.
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT FILE-MAST ASSIGN TO "diff-master.dat"
ORGANIZATION IS LINE SEQUENTIAL
FILE STATUS IS FS-MAST.
SELECT FILE-DETL ASSIGN TO "diff-detail.dat"
ORGANIZATION IS LINE SEQUENTIAL
FILE STATUS IS FS-DETL.
SELECT FILE-OUT ASSIGN TO "diff-match-output.txt"
ORGANIZATION IS LINE SEQUENTIAL
FILE STATUS IS FS-OUT.
SELECT AUDIT-OUT ASSIGN TO "audit-33.log"
ORGANIZATION IS LINE SEQUENTIAL
FILE STATUS IS FS-AUDIT.
DATA DIVISION.
FILE SECTION.
FD FILE-MAST.
01 MAST-REC.
05 MAST-ID PIC X(05).
05 MAST-NAME PIC X(20).
05 MAST-TYPE PIC X(05).
05 MAST-AMOUNT PIC 9(07).
FD FILE-DETL.
01 DETL-REC.
05 DETL-MAST-ID PIC X(05).
05 DETL-TRAN-ID PIC X(10).
05 DETL-AMOUNT PIC 9(07).
FD FILE-OUT.
01 OUT-REC.
05 OUT-LINE PIC X(80).
FD AUDIT-OUT.
01 AUDIT-REC.
05 AUDIT-LINE PIC X(120).
WORKING-STORAGE SECTION.
01 WS-TELECOM-REC.
COPY "telecom/TEL-BILLING.cpy".
*> ============================================================
*> FILE STATUS fields
*> ============================================================
01 FS-MAST PIC X(02) VALUE "00".
01 FS-DETL PIC X(02) VALUE "00".
01 FS-OUT PIC X(02) VALUE "00".
01 FS-AUDIT PIC X(02) VALUE "00".
*> ============================================================
*> End-of-file flags
*> ============================================================
01 WS-EOF-MAST PIC X(01) VALUE "N".
88 MAST-EOF VALUE "Y".
01 WS-EOF-DETL PIC X(01) VALUE "N".
88 DETL-EOF VALUE "Y".
*> ============================================================
*> Key break fields (diff-key: master ID vs detail master ID)
*> ============================================================
01 WS-PREV-MAST-ID PIC X(05).
01 WS-CURR-MAST-ID PIC X(05).
01 WS-MASTER-FOUND PIC X(01) VALUE "N".
*> ============================================================
*> Core counters
*> ============================================================
01 WS-MATCH-COUNT PIC 9(05) VALUE 0.
01 WS-BREAK-COUNT PIC 9(05) VALUE 0.
01 WS-DETAIL-COUNT PIC 9(05) VALUE 0.
01 WS-BREAK-TOTAL PIC 9(09) VALUE 0.
01 WS-GRAND-TOTAL PIC 9(09) VALUE 0.
*> ============================================================
*> Expanded counters: match path, unmatched path, break path
*> ============================================================
01 WS-MATCH-PATH-CNT PIC 9(05) VALUE 0.
01 WS-UNMATCH-CNT PIC 9(05) VALUE 0.
01 WS-BREAK-PATH-CNT PIC 9(05) VALUE 0.
01 WS-VALID-COUNT PIC 9(05) VALUE 0.
01 WS-INVALID-COUNT PIC 9(05) VALUE 0.
01 WS-TOTAL-RECORDS PIC 9(05) VALUE 0.
*> ============================================================
*> Hash totals per category
*> ============================================================
01 WS-HASH-MATCHED PIC 9(11) VALUE 0.
01 WS-HASH-UNMATCHED PIC 9(11) VALUE 0.
01 WS-HASH-BREAK PIC 9(11) VALUE 0.
01 WS-HASH-GRAND PIC 9(11) VALUE 0.
*> ============================================================
*> Master fields from lookup
*> ============================================================
01 WS-MASTER-NAME PIC X(20).
01 WS-MASTER-TYPE PIC X(05).
01 WS-MASTER-AMT PIC 9(07).
*> ============================================================
*> Master table loaded into memory
*> ============================================================
01 MASTER-TABLE.
05 MASTER-ENTRY OCCURS 8 TIMES.
10 ME-ID PIC X(05).
10 ME-NAME PIC X(20).
10 ME-TYPE PIC X(05).
10 ME-AMT PIC 9(07).
01 IDX PIC 9(02).
01 MAST-IDX PIC 9(02).
01 WS-MAST-COUNT PIC 9(02).
*> ============================================================
*> Timestamp and batch control
*> ============================================================
01 WS-TIMESTAMP.
05 WS-TS-DATE PIC X(08).
05 FILLER PIC X(01) VALUE SPACE.
05 WS-TS-TIME PIC X(08).
01 WS-BATCH-ID PIC X(08) VALUE "BATCH033".
01 WS-BATCH-START PIC X(16).
01 WS-BATCH-END PIC X(16).
01 WS-PROGRAM-NAME PIC X(30) VALUE
"Main33Mix1NDiffKeyBreak".
*> ============================================================
*> Error severity levels
*> ============================================================
01 WS-ERROR-SEVERITY.
05 WS-ERR-LEVEL PIC X(01).
88 ERR-INFO VALUE "I".
88 ERR-WARN VALUE "W".
88 ERR-ERROR VALUE "E".
88 ERR-CRITICAL VALUE "C".
01 WS-ERROR-MESSAGE PIC X(80).
01 WS-ERR-COUNT-INFO PIC 9(03) VALUE 0.
01 WS-ERR-COUNT-WARN PIC 9(03) VALUE 0.
01 WS-ERR-COUNT-ERROR PIC 9(03) VALUE 0.
01 WS-ERR-COUNT-CRIT PIC 9(03) VALUE 0.
*> ============================================================
*> FILE STATUS trace buffer
*> ============================================================
01 WS-FS-TRACE PIC X(40).
01 WS-FS-EXPECTED PIC X(02) VALUE "00".
*> ============================================================
*> Audit line templates
*> ============================================================
01 WS-AUDIT-HEADER.
05 FILLER PIC X(08) VALUE "AUDIT ".
05 FILLER PIC X(01) VALUE SPACE.
05 AH-PGM PIC X(30).
05 FILLER PIC X(01) VALUE SPACE.
05 AH-BATCH PIC X(08).
05 FILLER PIC X(01) VALUE SPACE.
05 AH-TIMESTAMP PIC X(17).
01 WS-AUDIT-ENTRY.
05 FILLER PIC X(08) VALUE " ENTRY ".
05 AE-TEXT PIC X(72).
01 WS-AUDIT-STATS.
05 FILLER PIC X(08) VALUE " STATS ".
05 AS-TEXT PIC X(72).
01 WS-AUDIT-ERROR.
05 FILLER PIC X(08) VALUE " ERROR ".
05 AE-LEVEL PIC X(01).
05 FILLER PIC X(01) VALUE SPACE.
05 AE-MSG PIC X(70).
*> ============================================================
*> Hybrid processing trace fields
*> ============================================================
01 WS-HYBRID-TRACE.
05 HT-EVENT PIC X(20).
05 HT-MAST-ID PIC X(05).
05 HT-DETL-ID PIC X(10).
05 HT-AMOUNT PIC 9(07).
05 HT-RESULT PIC X(10).
01 WS-TRACE-LINE.
05 FILLER PIC X(03) VALUE "[TR]".
05 TL-EVENT PIC X(20).
05 FILLER PIC X(01) VALUE SPACE.
05 TL-MAST-ID PIC X(05).
05 FILLER PIC X(01) VALUE SPACE.
05 TL-DETL-ID PIC X(10).
05 FILLER PIC X(01) VALUE SPACE.
05 TL-AMOUNT PIC Z(9)9.
05 FILLER PIC X(01) VALUE SPACE.
05 TL-RESULT PIC X(10).
*> ============================================================
*> Output line templates (preserved from original)
*> ============================================================
01 WS-HEADER1.
05 FILLER PIC X(40) VALUE
"MasterID Name ".
05 FILLER PIC X(40) VALUE
"Trans ID Amount".
01 WS-MATCH-LINE.
05 FILLER PIC X(02) VALUE " ".
05 ML-MAST-ID PIC X(05).
05 FILLER PIC X(02) VALUE SPACES.
05 ML-NAME PIC X(20).
05 FILLER PIC X(02) VALUE SPACES.
05 ML-TRAN-ID PIC X(10).
05 FILLER PIC X(02) VALUE SPACES.
05 ML-AMOUNT PIC Z(9)9.
01 WS-BREAK-LINE.
05 FILLER PIC X(10) VALUE ">> BREAK: ".
05 BL-MAST-ID PIC X(05).
05 FILLER PIC X(10) VALUE " -> ".
05 BL-DETL-ID PIC X(05).
05 FILLER PIC X(10) VALUE " Count: ".
05 BL-COUNT PIC Z(9).
05 FILLER PIC X(10) VALUE " Total: ".
05 BL-TOTAL PIC Z(9)9.
01 WS-UNMATCHED-LINE.
05 FILLER PIC X(20) VALUE " UNMATCHED master ".
05 UL-MAST-ID PIC X(05).
*> ============================================================
*> Report totals template
*> ============================================================
01 WS-REPORT-LINE.
05 FILLER PIC X(02) VALUE SPACES.
05 RL-LABEL PIC X(30).
05 FILLER PIC X(02) VALUE SPACES.
05 RL-VALUE PIC Z(9)9.
01 WS-HASH-LINE.
05 FILLER PIC X(02) VALUE SPACES.
05 HL-LABEL PIC X(30).
05 FILLER PIC X(02) VALUE SPACES.
05 HL-VALUE PIC Z(10)9.
*> ============================================================
*> Temporary work fields
*> ============================================================
01 WS-TEMP-AMOUNT PIC 9(09).
01 WS-TEMP-COUNT PIC 9(05).
01 WS-TEMP-HASH PIC 9(11).
PROCEDURE DIVISION.
MAIN-PROCEDURE.
PERFORM 1000-INIT.
PERFORM 2000-OPEN-FILES.
PERFORM 3000-PROCESS.
PERFORM 4000-REPORT.
PERFORM 5000-AUDIT.
PERFORM 9000-EXIT.
STOP RUN.
*> ============================================================
*> 1000-INIT : Initialise batch, timestamp, counters
*> ============================================================
1000-INIT.
MOVE FUNCTION CURRENT-DATE (1:8) TO WS-TS-DATE.
MOVE FUNCTION CURRENT-DATE (9:8) TO WS-TS-TIME.
MOVE WS-TS-DATE TO WS-BATCH-START(1:8).
MOVE WS-TS-TIME TO WS-BATCH-START(9:8).
MOVE 0 TO WS-MATCH-COUNT.
MOVE 0 TO WS-MATCH-PATH-CNT.
MOVE 0 TO WS-UNMATCH-CNT.
MOVE 0 TO WS-BREAK-PATH-CNT.
MOVE 0 TO WS-BREAK-COUNT.
MOVE 0 TO WS-VALID-COUNT.
MOVE 0 TO WS-INVALID-COUNT.
MOVE 0 TO WS-TOTAL-RECORDS.
MOVE 0 TO WS-GRAND-TOTAL.
MOVE 0 TO WS-HASH-MATCHED.
MOVE 0 TO WS-HASH-UNMATCHED.
MOVE 0 TO WS-HASH-BREAK.
MOVE 0 TO WS-HASH-GRAND.
MOVE 0 TO WS-ERR-COUNT-INFO.
MOVE 0 TO WS-ERR-COUNT-WARN.
MOVE 0 TO WS-ERR-COUNT-ERROR.
MOVE 0 TO WS-ERR-COUNT-CRIT.
DISPLAY "[" WS-TS-DATE " " WS-TS-TIME "] "
WS-PROGRAM-NAME " starting, batch="
WS-BATCH-ID.
*> ============================================================
*> 2000-OPEN-FILES : Open all files with FILE STATUS checks
*> ============================================================
2000-OPEN-FILES.
OPEN OUTPUT FILE-OUT.
MOVE FS-OUT TO WS-FS-TRACE.
IF FS-OUT NOT = "00"
MOVE "E" TO WS-ERR-LEVEL
STRING "FILE-OUT open failed FS=" FS-OUT
INTO WS-ERROR-MESSAGE
PERFORM 6000-ERROR-HANDLE
END-IF.
OPEN OUTPUT AUDIT-OUT.
MOVE FS-AUDIT TO WS-FS-TRACE.
IF FS-AUDIT NOT = "00"
MOVE "E" TO WS-ERR-LEVEL
STRING "AUDIT-OUT open failed FS=" FS-AUDIT
INTO WS-ERROR-MESSAGE
PERFORM 6000-ERROR-HANDLE
END-IF.
MOVE SPACES TO WS-AUDIT-HEADER.
MOVE WS-PROGRAM-NAME TO AH-PGM.
MOVE WS-BATCH-ID TO AH-BATCH.
STRING WS-TS-DATE " " WS-TS-TIME
DELIMITED BY SIZE INTO AH-TIMESTAMP.
MOVE WS-AUDIT-HEADER TO AUDIT-REC.
WRITE AUDIT-REC.
MOVE FS-AUDIT TO WS-FS-TRACE.
IF FS-AUDIT NOT = "00"
DISPLAY "Warning: AUDIT write failed FS=" FS-AUDIT
END-IF.
*> Load master table into memory
PERFORM LOAD-MASTER-TABLE.
MOVE "1:N Match with Different-Key Break" TO OUT-REC.
WRITE OUT-REC.
MOVE SPACES TO OUT-REC.
WRITE OUT-REC.
MOVE WS-HEADER1 TO OUT-REC.
WRITE OUT-REC.
MOVE SPACES TO OUT-REC.
WRITE OUT-REC.
MOVE SPACES TO WS-AUDIT-ENTRY.
STRING "Header written, master table size=" WS-MAST-COUNT
DELIMITED BY SIZE INTO AE-TEXT.
MOVE WS-AUDIT-ENTRY TO AUDIT-REC.
WRITE AUDIT-REC.
*> ============================================================
*> 3000-PROCESS : Main processing loop
*> ============================================================
3000-PROCESS.
*> Process details - master and detail keys may differ
OPEN INPUT FILE-DETL.
IF FS-DETL NOT = "00"
MOVE "E" TO WS-ERR-LEVEL
STRING "FILE-DETL open failed FS=" FS-DETL
INTO WS-ERROR-MESSAGE
PERFORM 6000-ERROR-HANDLE
END-IF.
MOVE 'N' TO WS-EOF-DETL.
MOVE 0 TO WS-MATCH-COUNT.
MOVE 0 TO WS-BREAK-COUNT.
MOVE 0 TO WS-GRAND-TOTAL.
MOVE SPACES TO WS-PREV-MAST-ID.
MOVE "I" TO WS-ERR-LEVEL.
MOVE "Detail processing started (diff-key)" TO
WS-ERROR-MESSAGE.
PERFORM 6000-ERROR-HANDLE.
PERFORM UNTIL DETL-EOF
READ FILE-DETL INTO DETL-REC
AT END
SET DETL-EOF TO TRUE
PERFORM HANDLE-FINAL-BREAK
NOT AT END
PERFORM PROCESS-DETAIL
END-READ
MOVE FS-DETL TO WS-FS-TRACE
IF NOT DETL-EOF AND FS-DETL NOT = "00"
MOVE "E" TO WS-ERR-LEVEL
STRING "FILE-DETL read failed FS=" FS-DETL
INTO WS-ERROR-MESSAGE
PERFORM 6000-ERROR-HANDLE
END-IF
END-PERFORM.
CLOSE FILE-DETL.
IF FS-DETL NOT = "00"
MOVE "W" TO WS-ERR-LEVEL
STRING "FILE-DETL close FS=" FS-DETL
INTO WS-ERROR-MESSAGE
PERFORM 6000-ERROR-HANDLE
END-IF.
*> ============================================================
*> 3100-VALIDATE : Validate detail record fields
*> ============================================================
3100-VALIDATE.
ADD 1 TO WS-TOTAL-RECORDS.
*> Validate master-ID not empty
IF DETL-MAST-ID = SPACES OR ZERO
ADD 1 TO WS-INVALID-COUNT
MOVE "W" TO WS-ERR-LEVEL
STRING "Empty master-id at record "
WS-TOTAL-RECORDS INTO WS-ERROR-MESSAGE
PERFORM 6000-ERROR-HANDLE
EXIT PARAGRAPH
END-IF.
*> Validate trans-ID not empty
IF DETL-TRAN-ID = SPACES OR ZERO
ADD 1 TO WS-INVALID-COUNT
MOVE "W" TO WS-ERR-LEVEL
STRING "Empty trans-id for master "
DETL-MAST-ID INTO WS-ERROR-MESSAGE
PERFORM 6000-ERROR-HANDLE
EXIT PARAGRAPH
END-IF.
*> Validate amount within range
IF DETL-AMOUNT = 0
ADD 1 TO WS-INVALID-COUNT
MOVE "I" TO WS-ERR-LEVEL
STRING "Zero amount for master " DETL-MAST-ID
INTO WS-ERROR-MESSAGE
PERFORM 6000-ERROR-HANDLE
END-IF.
*> Validate amount not exceeding threshold
IF DETL-AMOUNT > 9999999
ADD 1 TO WS-INVALID-COUNT
MOVE "W" TO WS-ERR-LEVEL
STRING "Large amount " DETL-AMOUNT
" for master " DETL-MAST-ID
INTO WS-ERROR-MESSAGE
PERFORM 6000-ERROR-HANDLE
END-IF.
*> Cross-check: master ID length
IF DETL-MAST-ID (1:1) = SPACE
ADD 1 TO WS-INVALID-COUNT
MOVE "W" TO WS-ERR-LEVEL
STRING "Short master-ID " DETL-MAST-ID
INTO WS-ERROR-MESSAGE
PERFORM 6000-ERROR-HANDLE
EXIT PARAGRAPH
END-IF.
ADD 1 TO WS-VALID-COUNT.
*> ============================================================
*> 3200-CALCULATE : Accumulate hash totals per category
*> ============================================================
3200-CALCULATE.
IF WS-MASTER-FOUND = "Y"
ADD DETL-AMOUNT TO WS-HASH-MATCHED
ELSE
ADD DETL-AMOUNT TO WS-HASH-UNMATCHED
END-IF.
ADD DETL-AMOUNT TO WS-HASH-GRAND.
*> Cross-check hash consistency
COMPUTE WS-TEMP-HASH =
WS-HASH-MATCHED + WS-HASH-UNMATCHED.
IF WS-TEMP-HASH NOT = WS-HASH-GRAND
MOVE "W" TO WS-ERR-LEVEL
STRING "Hash mismatch: "
WS-HASH-GRAND " vs " WS-TEMP-HASH
INTO WS-ERROR-MESSAGE
PERFORM 6000-ERROR-HANDLE
END-IF.
*> ============================================================
*> 3300-FORMAT-OUTPUT : Format output with hybrid trace
*> ============================================================
3300-FORMAT-OUTPUT.
MOVE SPACES TO WS-AUDIT-ENTRY.
IF WS-MASTER-FOUND = "Y"
STRING "MATCH mid=" WS-CURR-MAST-ID
" tran=" DETL-TRAN-ID
" amt=" DETL-AMOUNT
DELIMITED BY SIZE INTO AE-TEXT
ELSE
STRING "UNMATCH mid=" WS-CURR-MAST-ID
" tran=" DETL-TRAN-ID
" amt=" DETL-AMOUNT
DELIMITED BY SIZE INTO AE-TEXT
END-IF.
MOVE WS-AUDIT-ENTRY TO AUDIT-REC.
WRITE AUDIT-REC.
*> ============================================================
*> 3400-WRITE-OUTPUT : Write record + FILE STATUS check
*> ============================================================
3400-WRITE-OUTPUT.
MOVE FS-OUT TO WS-FS-TRACE.
IF FS-OUT NOT = "00"
MOVE "E" TO WS-ERR-LEVEL
STRING "FILE-OUT write failed FS=" FS-OUT
INTO WS-ERROR-MESSAGE
PERFORM 6000-ERROR-HANDLE
END-IF.
*> ============================================================
*> 4000-REPORT : Write summary report to output and audit
*> ============================================================
4000-REPORT.
MOVE SPACES TO OUT-REC.
WRITE OUT-REC.
PERFORM 3400-WRITE-OUTPUT.
MOVE SPACES TO WS-REPORT-LINE.
MOVE "Total matches:" TO RL-LABEL.
MOVE WS-MATCH-COUNT TO RL-VALUE.
MOVE WS-REPORT-LINE TO OUT-REC.
WRITE OUT-REC.
PERFORM 3400-WRITE-OUTPUT.
MOVE SPACES TO WS-REPORT-LINE.
MOVE "Total unmatched:" TO RL-LABEL.
MOVE WS-UNMATCH-CNT TO RL-VALUE.
MOVE WS-REPORT-LINE TO OUT-REC.
WRITE OUT-REC.
PERFORM 3400-WRITE-OUTPUT.
MOVE SPACES TO WS-REPORT-LINE.
MOVE "Total breaks:" TO RL-LABEL.
MOVE WS-BREAK-COUNT TO RL-VALUE.
MOVE WS-REPORT-LINE TO OUT-REC.
WRITE OUT-REC.
PERFORM 3400-WRITE-OUTPUT.
MOVE SPACES TO WS-REPORT-LINE.
MOVE "Valid records:" TO RL-LABEL.
MOVE WS-VALID-COUNT TO RL-VALUE.
MOVE WS-REPORT-LINE TO OUT-REC.
WRITE OUT-REC.
PERFORM 3400-WRITE-OUTPUT.
MOVE SPACES TO WS-REPORT-LINE.
MOVE "Invalid records:" TO RL-LABEL.
MOVE WS-INVALID-COUNT TO RL-VALUE.
MOVE WS-REPORT-LINE TO OUT-REC.
WRITE OUT-REC.
PERFORM 3400-WRITE-OUTPUT.
MOVE SPACES TO WS-HASH-LINE.
MOVE "Hash total (matched):" TO HL-LABEL.
MOVE WS-HASH-MATCHED TO HL-VALUE.
MOVE WS-HASH-LINE TO OUT-REC.
WRITE OUT-REC.
PERFORM 3400-WRITE-OUTPUT.
MOVE SPACES TO WS-HASH-LINE.
MOVE "Hash total (unmatched):" TO HL-LABEL.
MOVE WS-HASH-UNMATCHED TO HL-VALUE.
MOVE WS-HASH-LINE TO OUT-REC.
WRITE OUT-REC.
PERFORM 3400-WRITE-OUTPUT.
MOVE SPACES TO WS-HASH-LINE.
MOVE "Hash total (grand):" TO HL-LABEL.
MOVE WS-HASH-GRAND TO HL-VALUE.
MOVE WS-HASH-LINE TO OUT-REC.
WRITE OUT-REC.
PERFORM 3400-WRITE-OUTPUT.
STRING "Total matches: " WS-MATCH-COUNT
" Breaks: " WS-BREAK-COUNT
" Grand total: " WS-GRAND-TOTAL
DELIMITED BY SIZE INTO OUT-REC.
WRITE OUT-REC.
PERFORM 3400-WRITE-OUTPUT.
MOVE SPACES TO WS-AUDIT-ENTRY.
STRING "REPORT: match=" WS-MATCH-COUNT
" unmatched=" WS-UNMATCH-CNT
" break=" WS-BREAK-COUNT
" valid=" WS-VALID-COUNT
" invalid=" WS-INVALID-COUNT
" grand=" WS-GRAND-TOTAL
" hashG=" WS-HASH-GRAND
DELIMITED BY SIZE INTO AE-TEXT.
MOVE WS-AUDIT-ENTRY TO AUDIT-REC.
WRITE AUDIT-REC.
MOVE SPACES TO WS-AUDIT-ENTRY.
STRING "ERRORS: info=" WS-ERR-COUNT-INFO
" warn=" WS-ERR-COUNT-WARN
" error=" WS-ERR-COUNT-ERROR
" crit=" WS-ERR-COUNT-CRIT
DELIMITED BY SIZE INTO AE-TEXT.
MOVE WS-AUDIT-ENTRY TO AUDIT-REC.
WRITE AUDIT-REC.
*> ============================================================
*> 5000-AUDIT : Write final audit summary, close audit file
*> ============================================================
5000-AUDIT.
MOVE FUNCTION CURRENT-DATE (1:8) TO WS-TS-DATE.
MOVE FUNCTION CURRENT-DATE (9:8) TO WS-TS-TIME.
MOVE WS-TS-DATE TO WS-BATCH-END(1:8).
MOVE WS-TS-TIME TO WS-BATCH-END(9:8).
MOVE SPACES TO WS-AUDIT-STATS.
STRING "Batch " WS-BATCH-ID
" ended " WS-BATCH-END
DELIMITED BY SIZE INTO AS-TEXT.
MOVE WS-AUDIT-STATS TO AUDIT-REC.
WRITE AUDIT-REC.
MOVE SPACES TO WS-AUDIT-STATS.
STRING "Records total=" WS-TOTAL-RECORDS
" match=" WS-MATCH-PATH-CNT
" break=" WS-BREAK-PATH-CNT
DELIMITED BY SIZE INTO AS-TEXT.
MOVE WS-AUDIT-STATS TO AUDIT-REC.
WRITE AUDIT-REC.
MOVE SPACES TO WS-AUDIT-STATS.
STRING "Hash matched=" WS-HASH-MATCHED
" unmatched=" WS-HASH-UNMATCHED
" grand=" WS-HASH-GRAND
DELIMITED BY SIZE INTO AS-TEXT.
MOVE WS-AUDIT-STATS TO AUDIT-REC.
WRITE AUDIT-REC.
CLOSE AUDIT-OUT.
IF FS-AUDIT NOT = "00"
DISPLAY "Warning: AUDIT close FS=" FS-AUDIT
END-IF.
*> ============================================================
*> LOAD-MASTER-TABLE (original logic preserved, expanded)
*> ============================================================
LOAD-MASTER-TABLE.
OPEN INPUT FILE-MAST.
IF FS-MAST NOT = "00"
MOVE "E" TO WS-ERR-LEVEL
STRING "FILE-MAST open failed FS=" FS-MAST
INTO WS-ERROR-MESSAGE
PERFORM 6000-ERROR-HANDLE
END-IF.
MOVE 0 TO WS-MAST-COUNT.
PERFORM VARYING IDX FROM 1 BY 1 UNTIL IDX > 8
READ FILE-MAST INTO MAST-REC
AT END EXIT PERFORM
END-READ
MOVE FS-MAST TO WS-FS-TRACE
IF FS-MAST NOT = "00" AND FS-MAST NOT = "10"
MOVE "W" TO WS-ERR-LEVEL
STRING "FILE-MAST read idx=" IDX
" FS=" FS-MAST INTO WS-ERROR-MESSAGE
PERFORM 6000-ERROR-HANDLE
END-IF
MOVE MAST-ID TO ME-ID(IDX)
MOVE MAST-NAME TO ME-NAME(IDX)
MOVE MAST-TYPE TO ME-TYPE(IDX)
MOVE MAST-AMOUNT TO ME-AMT(IDX)
ADD 1 TO WS-MAST-COUNT
END-PERFORM.
CLOSE FILE-MAST.
MOVE FS-MAST TO WS-FS-TRACE.
IF FS-MAST NOT = "00"
MOVE "W" TO WS-ERR-LEVEL
STRING "FILE-MAST close FS=" FS-MAST
INTO WS-ERROR-MESSAGE
PERFORM 6000-ERROR-HANDLE
END-IF.
DISPLAY "Master table loaded: " WS-MAST-COUNT " entries".
MOVE SPACES TO WS-AUDIT-ENTRY.
STRING "LOAD-MASTER: " WS-MAST-COUNT " entries loaded"
DELIMITED BY SIZE INTO AE-TEXT.
MOVE WS-AUDIT-ENTRY TO AUDIT-REC.
WRITE AUDIT-REC.
*> ============================================================
*> PROCESS-DETAIL (original logic preserved, expanded)
*> ============================================================
PROCESS-DETAIL.
*> Run validation
PERFORM 3100-VALIDATE.
*> Record the current master ID from detail
MOVE DETL-MAST-ID TO WS-CURR-MAST-ID.
*> Check for key break (master ID changes)
IF WS-CURR-MAST-ID NOT = WS-PREV-MAST-ID
IF WS-PREV-MAST-ID NOT = SPACES
ADD 1 TO WS-BREAK-PATH-CNT
PERFORM HANDLE-KEY-BREAK
END-IF
MOVE WS-CURR-MAST-ID TO WS-PREV-MAST-ID
MOVE 0 TO WS-DETAIL-COUNT
MOVE 0 TO WS-BREAK-TOTAL
MOVE SPACES TO WS-AUDIT-ENTRY
STRING "KEYBREAK: prev=" WS-PREV-MAST-ID
" curr=" WS-CURR-MAST-ID
DELIMITED BY SIZE INTO AE-TEXT
MOVE WS-AUDIT-ENTRY TO AUDIT-REC
WRITE AUDIT-REC
END-IF.
*> Hybrid processing trace: record event
MOVE SPACES TO WS-TRACE-LINE.
MOVE "LOOKUP" TO TL-EVENT.
MOVE WS-CURR-MAST-ID TO TL-MAST-ID.
MOVE DETL-TRAN-ID TO TL-DETL-ID.
MOVE DETL-AMOUNT TO TL-AMOUNT.
*> Find matching master
MOVE "N" TO WS-MASTER-FOUND.
PERFORM VARYING MAST-IDX FROM 1 BY 1
UNTIL MAST-IDX > WS-MAST-COUNT
IF ME-ID(MAST-IDX) = WS-CURR-MAST-ID
MOVE "Y" TO WS-MASTER-FOUND
MOVE ME-NAME(MAST-IDX) TO WS-MASTER-NAME
MOVE ME-TYPE(MAST-IDX) TO WS-MASTER-TYPE
MOVE ME-AMT(MAST-IDX) TO WS-MASTER-AMT
END-IF
END-PERFORM.
*> Perform hash accumulation (3200)
PERFORM 3200-CALCULATE.
*> Hybrid processing trace: record match result
IF WS-MASTER-FOUND = "Y"
MOVE "MATCH" TO TL-RESULT
DISPLAY "[TR] LOOKUP " WS-CURR-MAST-ID " "
DETL-TRAN-ID " " DETL-AMOUNT " MATCH"
ELSE
MOVE "UNMATCH" TO TL-RESULT
DISPLAY "[TR] LOOKUP " WS-CURR-MAST-ID " "
DETL-TRAN-ID " " DETL-AMOUNT " UNMATCH"
END-IF.
IF WS-MASTER-FOUND = "Y"
ADD 1 TO WS-MATCH-COUNT
ADD 1 TO WS-MATCH-PATH-CNT
ADD 1 TO WS-DETAIL-COUNT
ADD DETL-AMOUNT TO WS-BREAK-TOTAL
ADD DETL-AMOUNT TO WS-GRAND-TOTAL
MOVE WS-CURR-MAST-ID TO ML-MAST-ID
MOVE WS-MASTER-NAME TO ML-NAME
MOVE DETL-TRAN-ID TO ML-TRAN-ID
MOVE DETL-AMOUNT TO ML-AMOUNT
DISPLAY " " WS-MATCH-LINE
MOVE WS-MATCH-LINE TO OUT-REC
WRITE OUT-REC
PERFORM 3400-WRITE-OUTPUT
ELSE
ADD 1 TO WS-UNMATCH-CNT
MOVE WS-CURR-MAST-ID TO UL-MAST-ID
DISPLAY " " WS-UNMATCHED-LINE
MOVE WS-UNMATCHED-LINE TO OUT-REC
WRITE OUT-REC
PERFORM 3400-WRITE-OUTPUT
END-IF.
*> Audit trace for this detail
PERFORM 3300-FORMAT-OUTPUT.
*> ============================================================
*> HANDLE-KEY-BREAK (original logic preserved, expanded)
*> ============================================================
HANDLE-KEY-BREAK.
ADD 1 TO WS-BREAK-COUNT.
MOVE WS-PREV-MAST-ID TO BL-MAST-ID.
MOVE WS-CURR-MAST-ID TO BL-DETL-ID.
MOVE WS-DETAIL-COUNT TO BL-COUNT.
MOVE WS-BREAK-TOTAL TO BL-TOTAL.
ADD WS-BREAK-TOTAL TO WS-HASH-BREAK.
DISPLAY " " WS-BREAK-LINE.
MOVE WS-BREAK-LINE TO OUT-REC.
WRITE OUT-REC.
PERFORM 3400-WRITE-OUTPUT.
*> Hybrid processing trace for break
DISPLAY "[TR] BREAK " WS-PREV-MAST-ID " -> "
WS-CURR-MAST-ID " count=" WS-DETAIL-COUNT
" total=" WS-BREAK-TOTAL.
MOVE SPACES TO WS-AUDIT-ENTRY.
STRING "BREAK: prev=" WS-PREV-MAST-ID
" curr=" WS-CURR-MAST-ID
" count=" WS-DETAIL-COUNT
" total=" WS-BREAK-TOTAL
DELIMITED BY SIZE INTO AE-TEXT.
MOVE WS-AUDIT-ENTRY TO AUDIT-REC.
WRITE AUDIT-REC.
*> ============================================================
*> HANDLE-FINAL-BREAK (original logic preserved, expanded)
*> ============================================================
HANDLE-FINAL-BREAK.
IF WS-PREV-MAST-ID NOT = SPACES
ADD 1 TO WS-BREAK-PATH-CNT
PERFORM HANDLE-KEY-BREAK
END-IF.
MOVE SPACES TO WS-AUDIT-ENTRY.
STRING "FINAL-BREAK: total count=" WS-BREAK-COUNT
DELIMITED BY SIZE INTO AE-TEXT.
MOVE WS-AUDIT-ENTRY TO AUDIT-REC.
WRITE AUDIT-REC.
*> ============================================================
*> 6000-ERROR-HANDLE : Centralized error handling by severity
*> ============================================================
6000-ERROR-HANDLE.
EVALUATE WS-ERR-LEVEL
WHEN "I"
ADD 1 TO WS-ERR-COUNT-INFO
DISPLAY "INFO: " WS-ERROR-MESSAGE
WHEN "W"
ADD 1 TO WS-ERR-COUNT-WARN
DISPLAY "WARN: " WS-ERROR-MESSAGE
WHEN "E"
ADD 1 TO WS-ERR-COUNT-ERROR
DISPLAY "ERROR: " WS-ERROR-MESSAGE
WHEN "C"
ADD 1 TO WS-ERR-COUNT-CRIT
DISPLAY "CRITICAL: " WS-ERROR-MESSAGE
MOVE WS-ERROR-MESSAGE TO OUT-REC
WRITE OUT-REC
MOVE SPACES TO WS-AUDIT-ERROR
MOVE "C" TO AE-LEVEL
STRING "ABORT: " WS-ERROR-MESSAGE
DELIMITED BY SIZE INTO AE-MSG
MOVE WS-AUDIT-ERROR TO AUDIT-REC
WRITE AUDIT-REC
CLOSE FILE-OUT
CLOSE AUDIT-OUT
STOP RUN
WHEN OTHER
DISPLAY "UNKNOWN: " WS-ERROR-MESSAGE
END-EVALUATE.
*> Write error to audit log
MOVE SPACES TO WS-AUDIT-ERROR.
MOVE WS-ERR-LEVEL TO AE-LEVEL.
MOVE WS-ERROR-MESSAGE TO AE-MSG.
MOVE WS-AUDIT-ERROR TO AUDIT-REC.
WRITE AUDIT-REC.
*> ============================================================
*> 9000-EXIT : Close files and terminate
*> ============================================================
9000-EXIT.
MOVE FUNCTION CURRENT-DATE (1:8) TO WS-TS-DATE.
MOVE FUNCTION CURRENT-DATE (9:8) TO WS-TS-TIME.
MOVE WS-TS-DATE TO WS-BATCH-END(1:8).
MOVE WS-TS-TIME TO WS-BATCH-END(9:8).
DISPLAY "[" WS-TS-DATE " " WS-TS-TIME "] "
WS-PROGRAM-NAME " ending, batch=" WS-BATCH-ID.
CLOSE FILE-OUT.
IF FS-OUT NOT = "00"
DISPLAY "Warning: FILE-OUT close FS=" FS-OUT
END-IF.
DISPLAY "Output written to diff-match-output.txt".
DISPLAY "Audit written to audit-33.log".