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,872 @@
*> ============================================================
*> main-07-keybreak-summary.cbl : 加入者月汇总 (EXPANDED)
*> Input : FILE-IN.DAT (按客户ID/套餐排序的用量记录)
*> Output: FILE-OUT.DAT (客户别月汇总: 金额合计,件数)
*> REPORT-OUT.DAT (格式化报告)
*> AUDIT-RPT.DAT (审计追踪)
*> Coverage: KB-N001, KB-N004~N006, KB-A001, KB-R001
*> Expanded features:
*> 2-level key break (customer + plan)
*> Accumulator overflow handling
*> Statistics per group (min, max, avg, variance)
*> Page break control, formatted report output
*> Audit trail, hash totals, batch controls
*> FILE STATUS checks, error severity levels
*> ============================================================
IDENTIFICATION DIVISION.
PROGRAM-ID. KeyBreakSum.
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT FILE-IN
ASSIGN TO "FILE-IN.DAT"
ORGANIZATION IS LINE SEQUENTIAL
FILE STATUS IS WS-FILE-IN-STATUS.
SELECT FILE-OUT
ASSIGN TO "FILE-OUT.DAT"
ORGANIZATION IS LINE SEQUENTIAL
FILE STATUS IS WS-FILE-OUT-STATUS.
SELECT AUDIT-REPORT
ASSIGN TO "AUDIT-RPT.DAT"
ORGANIZATION IS LINE SEQUENTIAL
FILE STATUS IS WS-AUDIT-STATUS.
SELECT REPORT-FILE
ASSIGN TO "REPORT-OUT.DAT"
ORGANIZATION IS LINE SEQUENTIAL
FILE STATUS IS WS-REPORT-STATUS.
DATA DIVISION.
FILE SECTION.
FD FILE-IN.
*> Expanded FD to match telecom copybook (45 bytes total)
*> Original IN-KEY and IN-AMOUNT preserved at same names
01 FILE-IN-REC.
05 IN-KEY PIC X(10).
05 IN-CUST-ID PIC X(10).
05 IN-PLAN-CODE PIC X(03).
05 IN-AMOUNT PIC 9(09).
05 IN-STATUS-FLAG PIC X(01).
05 IN-RESERVED PIC X(12).
FD FILE-OUT.
01 FILE-OUT-REC.
05 OUT-KEY PIC X(10).
05 FILLER PIC X VALUE SPACE.
05 OUT-COUNT PIC Z(9)9.
05 FILLER PIC X(03) VALUE SPACE.
05 OUT-TOTAL PIC Z(9)9.
FD AUDIT-REPORT.
01 AUDIT-REC PIC X(80).
FD REPORT-FILE.
01 REPORT-REC PIC X(80).
WORKING-STORAGE SECTION.
*> File status fields
01 WS-FILE-STATUS.
05 WS-FILE-IN-STATUS PIC X(02).
05 WS-FILE-OUT-STATUS PIC X(02).
05 WS-AUDIT-STATUS PIC X(02).
05 WS-REPORT-STATUS PIC X(02).
*> Timestamp from FUNCTION CURRENT-DATE (21 chars)
01 WS-TIMESTAMP-STR PIC X(21).
01 WS-TS-FIELDS REDEFINES WS-TIMESTAMP-STR.
05 WS-TS-YEAR PIC 9(4).
05 WS-TS-MONTH PIC 9(2).
05 WS-TS-DAY PIC 9(2).
05 WS-TS-HOUR PIC 9(2).
05 WS-TS-MINUTE PIC 9(2).
05 WS-TS-SECOND PIC 9(2).
05 WS-TS-HUND PIC 9(2).
05 WS-TS-OFFSET PIC X(5).
01 WS-TELECOM-REC.
COPY "telecom/TEL-BILLING.cpy".
*> Program status flags
01 WS-STATUS.
05 WS-EOF-FLAG PIC X VALUE 'N'.
88 WS-EOF VALUE 'Y'.
05 WS-FIRST-REC PIC X VALUE 'Y'.
88 WS-FIRST VALUE 'Y'.
*> Key fields for 2-level key break
01 WS-KEY-FIELDS.
05 WS-PREV-KEY PIC X(10).
05 WS-CURRENT-KEY PIC X(10).
05 WS-PREV-PLAN PIC X(03).
05 WS-CURRENT-PLAN PIC X(03).
*> Customer-level accumulators
01 WS-ACCUMULATORS.
05 WS-GROUP-COUNT PIC 9(5) VALUE 0.
05 WS-GROUP-TOTAL PIC 9(10) VALUE 0.
05 WS-GROUP-MIN PIC 9(10) VALUE 9999999999.
05 WS-GROUP-MAX PIC 9(10) VALUE 0.
05 WS-GROUP-AVG PIC 9(10)V99 VALUE 0.
05 WS-GROUP-VAR PIC 9(10)V99 VALUE 0.
05 WS-SUM-SQUARES PIC 9(20) VALUE 0.
*> Plan-level accumulators
01 WS-PLAN-ACCUMULATORS.
05 WS-PLAN-COUNT PIC 9(5) VALUE 0.
05 WS-PLAN-TOTAL PIC 9(10) VALUE 0.
05 WS-PLAN-MIN PIC 9(10) VALUE 9999999999.
05 WS-PLAN-MAX PIC 9(10) VALUE 0.
*> Page and overflow control
01 WS-CONTROL-FIELDS.
05 WS-MAX-TOTAL PIC 9(10) VALUE 9999999999.
05 WS-OVERFLOW-FLAG PIC X VALUE 'N'.
88 WS-OVERFLOW VALUE 'Y'.
05 WS-LINE-COUNT PIC 9(02) VALUE 0.
05 WS-PAGE-LENGTH PIC 9(02) VALUE 60.
05 WS-PAGE-NUM PIC 9(03) VALUE 1.
*> Running totals
01 WS-TOTALS.
05 WS-GRAND-TOTAL PIC 9(10) VALUE 0.
05 WS-GRAND-VERIFY PIC 9(10) VALUE 0.
05 WS-GROUPS-WRITTEN PIC 9(5) VALUE 0.
05 WS-RECORDS-READ PIC 9(5) VALUE 0.
05 WS-RECORDS-WRITTEN PIC 9(5) VALUE 0.
05 WS-ERROR-COUNT PIC 9(03) VALUE 0.
05 WS-WARNING-COUNT PIC 9(03) VALUE 0.
*> Hash totals for data integrity
01 WS-HASH-TOTALS.
05 WS-HASH-TOTAL-IN PIC 9(18) VALUE 0.
05 WS-HASH-TOTAL-OUT PIC 9(18) VALUE 0.
*> Batch control totals
01 WS-BATCH-CONTROL.
05 WS-BATCH-REC-EXP PIC 9(5) VALUE 0.
05 WS-BATCH-AMT-EXP PIC 9(10) VALUE 0.
05 WS-BATCH-STATUS PIC X(10) VALUE SPACES.
*> Report header line (first page header)
01 WS-HEADER-LINE.
05 FILLER PIC X(10) VALUE SPACES.
05 HL-TEXT PIC X(43) VALUE
"TELECOM BILLING - CUSTOMER SUMMARY REPORT".
05 FILLER PIC X(27) VALUE SPACES.
*> Page header (repeated each new page)
01 WS-PAGE-HEADER.
05 FILLER PIC X(05) VALUE "PAGE ".
05 PH-PAGE-NUM PIC Z(9)9.
05 FILLER PIC X(03) VALUE SPACES.
05 PH-DATE PIC X(10).
05 FILLER PIC X(62) VALUE SPACES.
*> Customer-level group header
01 WS-CUSTOMER-HEADER.
05 FILLER PIC X(03) VALUE SPACES.
05 CH-TEXT PIC X(10) VALUE "CUSTOMER: ".
05 CH-KEY PIC X(10).
05 FILLER PIC X(05) VALUE SPACES.
05 CH-PLAN-TEXT PIC X(06) VALUE "PLAN: ".
05 CH-PLAN PIC X(03).
05 FILLER PIC X(43) VALUE SPACES.
*> Plan-level footer
01 WS-PLAN-FOOTER.
05 FILLER PIC X(05) VALUE SPACES.
05 PF-TEXT PIC X(12) VALUE "Plan Total: ".
05 PF-PLAN PIC X(03).
05 FILLER PIC X(03) VALUE SPACES.
05 PF-COUNT PIC Z(9)9.
05 FILLER PIC X(03) VALUE " / ".
05 PF-TOTAL PIC Z(9)9.
05 FILLER PIC X(38) VALUE SPACES.
*> Customer-level group footer with statistics
01 WS-GROUP-FOOTER.
05 FILLER PIC X(03) VALUE SPACES.
05 GF-TEXT PIC X(16) VALUE "** CUSTOMER SUM **".
05 FILLER PIC X(02) VALUE SPACES.
05 GF-COUNT-TEXT PIC X(05) VALUE "CNT: ".
05 GF-COUNT PIC Z(9)9.
05 FILLER PIC X(02) VALUE SPACES.
05 GF-TOTAL-TEXT PIC X(05) VALUE "TOT: ".
05 GF-TOTAL PIC Z(9)9.
05 FILLER PIC X(02) VALUE SPACES.
05 GF-MIN-TEXT PIC X(04) VALUE "MIN:".
05 GF-MIN PIC Z(9)9.
05 FILLER PIC X(02) VALUE SPACES.
05 GF-MAX-TEXT PIC X(04) VALUE "MAX:".
05 GF-MAX PIC Z(9)9.
05 FILLER PIC X(02) VALUE SPACES.
05 GF-AVG-TEXT PIC X(04) VALUE "AVG:".
05 GF-AVG PIC Z(9)9.99.
05 FILLER PIC X(06) VALUE SPACES.
*> Grand total verification line
01 WS-GRAND-TOTAL-LINE.
05 FILLER PIC X(03) VALUE SPACES.
05 GT-TEXT PIC X(14) VALUE "GRAND TOTAL: ".
05 GT-VALUE PIC Z(9)9.
05 FILLER PIC X(05) VALUE SPACES.
05 GT-VERIFY-TEXT PIC X(08) VALUE "VERIFY: ".
05 GT-VERIFY PIC Z(9)9.
05 FILLER PIC X(05) VALUE SPACES.
05 GT-STATUS-TEXT PIC X(08) VALUE "STATUS: ".
05 GT-STATUS PIC X(10).
*> Detail line for each input record
01 WS-DETAIL-LINE.
05 FILLER PIC X(05) VALUE SPACES.
05 DL-KEY PIC X(10).
05 FILLER PIC X(03) VALUE SPACES.
05 DL-PLAN PIC X(03).
05 FILLER PIC X(03) VALUE SPACES.
05 DL-AMOUNT PIC Z(9)9.
05 FILLER PIC X(46) VALUE SPACES.
*> Audit record structure
01 WS-AUDIT-REC.
05 AR-TIMESTAMP PIC X(08).
05 FILLER PIC X(01) VALUE SPACE.
05 AR-TEXT PIC X(60).
05 FILLER PIC X(11) VALUE SPACES.
*> Error message structure with severity levels
01 WS-ERROR-MESSAGE.
05 FILLER PIC X(08) VALUE "ERROR: ".
05 EM-SEVERITY PIC X(08).
05 FILLER PIC X(03) VALUE " - ".
05 EM-TEXT PIC X(50).
05 FILLER PIC X(11) VALUE SPACES.
PROCEDURE DIVISION.
MAIN SECTION.
MAIN-PROCEDURE.
PERFORM 1000-INIT-SECTION
PERFORM 2000-OPEN-FILES-SECTION
PERFORM 3000-PROCESS-SECTION
PERFORM 5000-AUDIT-SECTION
PERFORM 9000-EXIT-SECTION
STOP RUN.
*> ============================================================
*> 1000-INIT-SECTION
*> Initialize all accumulators, display program banner
*> ============================================================
1000-INIT-SECTION SECTION.
1000-INIT-PROC.
DISPLAY " "
DISPLAY "=========================================="
DISPLAY " KeyBreakSummary - Telecom Billing"
DISPLAY " Phase: Monthly Aggregation"
DISPLAY "=========================================="
DISPLAY " "
MOVE FUNCTION CURRENT-DATE TO WS-TIMESTAMP-STR
MOVE 'N' TO WS-EOF-FLAG
MOVE 'Y' TO WS-FIRST-REC
MOVE 0 TO WS-GROUP-COUNT
MOVE 0 TO WS-GROUP-TOTAL
MOVE 9999999999 TO WS-GROUP-MIN
MOVE 0 TO WS-GROUP-MAX
MOVE 0 TO WS-GROUP-AVG
MOVE 0 TO WS-GROUP-VAR
MOVE 0 TO WS-SUM-SQUARES
MOVE 0 TO WS-PLAN-COUNT
MOVE 0 TO WS-PLAN-TOTAL
MOVE 9999999999 TO WS-PLAN-MIN
MOVE 0 TO WS-PLAN-MAX
MOVE 9999999999 TO WS-MAX-TOTAL
MOVE 'N' TO WS-OVERFLOW-FLAG
MOVE 0 TO WS-LINE-COUNT
MOVE 60 TO WS-PAGE-LENGTH
MOVE 1 TO WS-PAGE-NUM
MOVE 0 TO WS-GRAND-TOTAL
MOVE 0 TO WS-GRAND-VERIFY
MOVE 0 TO WS-GROUPS-WRITTEN
MOVE 0 TO WS-RECORDS-READ
MOVE 0 TO WS-RECORDS-WRITTEN
MOVE 0 TO WS-ERROR-COUNT
MOVE 0 TO WS-WARNING-COUNT
MOVE 0 TO WS-HASH-TOTAL-IN
MOVE 0 TO WS-HASH-TOTAL-OUT
MOVE 0 TO WS-BATCH-REC-EXP
MOVE 0 TO WS-BATCH-AMT-EXP
MOVE SPACES TO WS-BATCH-STATUS
DISPLAY "INIT: " WS-TS-YEAR "-" WS-TS-MONTH "-"
WS-TS-DAY " " WS-TS-HOUR ":" WS-TS-MINUTE ":"
WS-TS-SECOND
DISPLAY "INIT: Page length = " WS-PAGE-LENGTH
DISPLAY " "
.
1000-EXIT.
EXIT.
*> ============================================================
*> 2000-OPEN-FILES-SECTION
*> Open all four files with FILE STATUS checks
*> ============================================================
2000-OPEN-FILES-SECTION SECTION.
2000-OPEN-FILES-PROC.
OPEN INPUT FILE-IN
IF WS-FILE-IN-STATUS NOT = '00'
MOVE "FATAL" TO EM-SEVERITY
MOVE "UNABLE TO OPEN FILE-IN.DAT" TO EM-TEXT
PERFORM 6000-ERROR-HANDLE-SECTION
STOP RUN
END-IF
OPEN OUTPUT FILE-OUT
IF WS-FILE-OUT-STATUS NOT = '00'
MOVE "FATAL" TO EM-SEVERITY
MOVE "UNABLE TO OPEN FILE-OUT.DAT" TO EM-TEXT
PERFORM 6000-ERROR-HANDLE-SECTION
STOP RUN
END-IF
OPEN OUTPUT AUDIT-REPORT
IF WS-AUDIT-STATUS NOT = '00'
MOVE "WARNING" TO EM-SEVERITY
MOVE "UNABLE TO OPEN AUDIT-RPT.DAT, CONTINUING"
TO EM-TEXT
PERFORM 6000-ERROR-HANDLE-SECTION
END-IF
OPEN OUTPUT REPORT-FILE
IF WS-REPORT-STATUS NOT = '00'
MOVE "WARNING" TO EM-SEVERITY
MOVE "UNABLE TO OPEN REPORT-OUT.DAT, CONTINUING"
TO EM-TEXT
PERFORM 6000-ERROR-HANDLE-SECTION
END-IF
MOVE FUNCTION CURRENT-DATE TO WS-TIMESTAMP-STR
DISPLAY "OPEN: " WS-TS-HOUR ":" WS-TS-MINUTE ":"
WS-TS-SECOND " Files opened"
MOVE "PROGRAM STARTED - FILES OPENED" TO AR-TEXT
PERFORM 5000-WRITE-AUDIT
.
2000-EXIT.
EXIT.
*> ============================================================
*> 3000-PROCESS-SECTION
*> Main processing loop: read, validate, apply rules
*> ============================================================
3000-PROCESS-SECTION SECTION.
3000-PROCESS-PROC.
MOVE FUNCTION CURRENT-DATE TO WS-TIMESTAMP-STR
DISPLAY "PROC: " WS-TS-HOUR ":" WS-TS-MINUTE ":"
WS-TS-SECOND " Starting main loop"
MOVE "PROCESSING STARTED" TO AR-TEXT
PERFORM 5000-WRITE-AUDIT
PERFORM 3100-READ-INPUT-SECTION
PERFORM UNTIL WS-EOF
PERFORM 3200-VALIDATE-SECTION
PERFORM 3300-APPLY-RULES-SECTION
PERFORM 3100-READ-INPUT-SECTION
END-PERFORM
MOVE FUNCTION CURRENT-DATE TO WS-TIMESTAMP-STR
DISPLAY "PROC: " WS-TS-HOUR ":" WS-TS-MINUTE ":"
WS-TS-SECOND " EOF reached"
*> Close remaining plan group for last customer
IF WS-PLAN-COUNT > 0
PERFORM WRITE-PLAN-FOOTER
END-IF
*> Write final group summary (preserved original behavior)
IF WS-GROUP-COUNT > 0
PERFORM WRITE-GROUP-SUMMARY
END-IF
*> Write final formatted report
PERFORM 4000-REPORT-SECTION
MOVE FUNCTION CURRENT-DATE TO WS-TIMESTAMP-STR
DISPLAY "PROC: " WS-TS-HOUR ":" WS-TS-MINUTE ":"
WS-TS-SECOND " Main loop complete"
.
3000-EXIT.
EXIT.
*> ============================================================
*> 3100-READ-INPUT-SECTION
*> Read one record from FILE-IN, update keys, check status
*> ============================================================
3100-READ-INPUT-SECTION SECTION.
3100-READ-INPUT-PROC.
READ FILE-IN INTO WS-TELECOM-REC
AT END
SET WS-EOF TO TRUE
MOVE FUNCTION CURRENT-DATE TO WS-TIMESTAMP-STR
DISPLAY "READ: " WS-TS-HOUR ":" WS-TS-MINUTE ":"
WS-TS-SECOND " EOF after "
WS-RECORDS-READ " records"
NOT AT END
ADD 1 TO WS-RECORDS-READ
MOVE BILL-KEY TO WS-CURRENT-KEY
MOVE BILL-PLAN-CODE TO WS-CURRENT-PLAN
END-READ
*> FILE STATUS check for read errors (status '10' = AT END)
IF WS-FILE-IN-STATUS NOT = '00'
AND WS-FILE-IN-STATUS NOT = '10'
MOVE "ERROR" TO EM-SEVERITY
STRING "FILE-IN READ ERROR, STATUS="
WS-FILE-IN-STATUS
INTO EM-TEXT
PERFORM 6000-ERROR-HANDLE-SECTION
END-IF
.
3100-EXIT.
EXIT.
*> ============================================================
*> 3200-VALIDATE-SECTION
*> Validate record content, filter invalid records
*> ============================================================
3200-VALIDATE-SECTION SECTION.
3200-VALIDATE-PROC.
*> Check for error/exclude status flags
IF BILL-STATUS = 'E' OR 'X'
ADD 1 TO WS-ERROR-COUNT
MOVE "WARNING" TO EM-SEVERITY
STRING "SKIP RECORD KEY=" BILL-KEY
" STATUS=" BILL-STATUS
INTO EM-TEXT
PERFORM 6000-ERROR-HANDLE-SECTION
EXIT PARAGRAPH
END-IF
*> Warn on zero amount (still processed)
IF BILL-AMOUNT = 0
ADD 1 TO WS-WARNING-COUNT
MOVE "WARNING" TO EM-SEVERITY
STRING "ZERO AMOUNT KEY=" BILL-KEY
INTO EM-TEXT
PERFORM 6000-ERROR-HANDLE-SECTION
END-IF
*> Reject amount exceeding PIC 9(09) capacity
IF BILL-AMOUNT > 999999999
ADD 1 TO WS-ERROR-COUNT
MOVE "ERROR" TO EM-SEVERITY
STRING "AMOUNT OVERFLOW KEY=" BILL-KEY
INTO EM-TEXT
PERFORM 6000-ERROR-HANDLE-SECTION
EXIT PARAGRAPH
END-IF
MOVE "RECORD VALIDATED" TO AR-TEXT
PERFORM 5000-WRITE-AUDIT
.
3200-EXIT.
EXIT.
*> ============================================================
*> 3300-APPLY-RULES-SECTION
*> Key-break detection (2-level), accumulation, statistics
*> PRESERVED ORIGINAL LOGIC: key-break + accumulation
*> ============================================================
3300-APPLY-RULES-SECTION SECTION.
3300-APPLY-RULES-PROC.
MOVE BILL-KEY TO WS-CURRENT-KEY
*> --- PRESERVED ORIGINAL KEY-BREAK LOGIC ---
IF WS-FIRST
MOVE WS-CURRENT-KEY TO WS-PREV-KEY
MOVE BILL-PLAN-CODE TO WS-PREV-PLAN
MOVE 'N' TO WS-FIRST-REC
PERFORM WRITE-CUSTOMER-HEADER
PERFORM WRITE-PLAN-HEADER
ELSE
IF WS-CURRENT-KEY NOT = WS-PREV-KEY
*> Customer break: plan footer first, then group summary
IF WS-PLAN-COUNT > 0
PERFORM WRITE-PLAN-FOOTER
END-IF
PERFORM WRITE-GROUP-SUMMARY
MOVE WS-CURRENT-KEY TO WS-PREV-KEY
MOVE BILL-PLAN-CODE TO WS-PREV-PLAN
PERFORM WRITE-CUSTOMER-HEADER
PERFORM WRITE-PLAN-HEADER
ELSE
*> Same customer: check plan-level break
IF BILL-PLAN-CODE NOT = WS-PREV-PLAN
IF WS-PLAN-COUNT > 0
PERFORM WRITE-PLAN-FOOTER
END-IF
MOVE BILL-PLAN-CODE TO WS-PREV-PLAN
PERFORM WRITE-PLAN-HEADER
END-IF
END-IF
END-IF
*> --- PRESERVED ORIGINAL ACCUMULATION LOGIC ---
ADD BILL-AMOUNT TO WS-GROUP-TOTAL
ADD 1 TO WS-GROUP-COUNT
*> --- EXPANDED: plan-level accumulation ---
ADD BILL-AMOUNT TO WS-PLAN-TOTAL
ADD 1 TO WS-PLAN-COUNT
*> --- EXPANDED: hash total for data integrity ---
ADD BILL-AMOUNT TO WS-HASH-TOTAL-IN
*> --- EXPANDED: minimum and maximum per group ---
IF BILL-AMOUNT < WS-GROUP-MIN
MOVE BILL-AMOUNT TO WS-GROUP-MIN
END-IF
IF BILL-AMOUNT > WS-GROUP-MAX
MOVE BILL-AMOUNT TO WS-GROUP-MAX
END-IF
IF BILL-AMOUNT < WS-PLAN-MIN
MOVE BILL-AMOUNT TO WS-PLAN-MIN
END-IF
IF BILL-AMOUNT > WS-PLAN-MAX
MOVE BILL-AMOUNT TO WS-PLAN-MAX
END-IF
*> --- EXPANDED: sum of squares for variance ---
COMPUTE WS-SUM-SQUARES = WS-SUM-SQUARES
+ (BILL-AMOUNT * BILL-AMOUNT)
*> --- EXPANDED: accumulator overflow check ---
IF WS-GROUP-TOTAL > WS-MAX-TOTAL
SET WS-OVERFLOW TO TRUE
MOVE "ERROR" TO EM-SEVERITY
STRING "GROUP TOTAL OVERFLOW KEY=" WS-PREV-KEY
INTO EM-TEXT
PERFORM 6000-ERROR-HANDLE-SECTION
END-IF
*> --- EXPANDED: batch control totals ---
ADD 1 TO WS-BATCH-REC-EXP
ADD BILL-AMOUNT TO WS-BATCH-AMT-EXP
*> --- EXPANDED: detail line to report file ---
MOVE BILL-KEY TO DL-KEY
MOVE BILL-PLAN-CODE TO DL-PLAN
MOVE BILL-AMOUNT TO DL-AMOUNT
PERFORM WRITE-REPORT-LINE
.
3300-EXIT.
EXIT.
*> ============================================================
*> 3400-WRITE-OUTPUT-SECTION
*> Write group summary record to FILE-OUT
*> Called from WRITE-GROUP-SUMMARY
*> ============================================================
3400-WRITE-OUTPUT-SECTION SECTION.
3400-WRITE-OUTPUT-PROC.
*> --- PRESERVED ORIGINAL OUTPUT LOGIC ---
MOVE WS-PREV-KEY TO OUT-KEY
MOVE WS-GROUP-COUNT TO OUT-COUNT
MOVE WS-GROUP-TOTAL TO OUT-TOTAL
WRITE FILE-OUT-REC
ADD 1 TO WS-GROUPS-WRITTEN
ADD 1 TO WS-RECORDS-WRITTEN
*> Accumulate grand total and hash (original behavior)
ADD WS-GROUP-TOTAL TO WS-GRAND-TOTAL
ADD WS-GROUP-TOTAL TO WS-HASH-TOTAL-OUT
*> Display group summary (preserved original display)
DISPLAY " Group " WS-PREV-KEY ": count="
WS-GROUP-COUNT ", total=" WS-GROUP-TOTAL
*> --- EXPANDED: compute average and variance ---
IF WS-GROUP-COUNT > 0
COMPUTE WS-GROUP-AVG = WS-GROUP-TOTAL
/ WS-GROUP-COUNT
COMPUTE WS-GROUP-VAR =
(WS-SUM-SQUARES / WS-GROUP-COUNT)
- (WS-GROUP-AVG * WS-GROUP-AVG)
ELSE
MOVE 0 TO WS-GROUP-AVG
MOVE 0 TO WS-GROUP-VAR
END-IF
*> Display extended statistics
DISPLAY " Stats " WS-PREV-KEY ": min=" WS-GROUP-MIN
" max=" WS-GROUP-MAX " avg=" WS-GROUP-AVG
*> Write formatted group footer to report file
MOVE WS-GROUP-COUNT TO GF-COUNT
MOVE WS-GROUP-TOTAL TO GF-TOTAL
MOVE WS-GROUP-MIN TO GF-MIN
MOVE WS-GROUP-MAX TO GF-MAX
MOVE WS-GROUP-AVG TO GF-AVG
MOVE WS-GROUP-FOOTER TO REPORT-REC
WRITE REPORT-REC
ADD 1 TO WS-LINE-COUNT
*> FILE STATUS check after WRITE
IF WS-REPORT-STATUS NOT = '00'
MOVE "WARNING" TO EM-SEVERITY
STRING "REPORT WRITE ERROR STATUS="
WS-REPORT-STATUS
INTO EM-TEXT
PERFORM 6000-ERROR-HANDLE-SECTION
END-IF
*> Reset group accumulators for next group
MOVE 0 TO WS-GROUP-COUNT
MOVE 0 TO WS-GROUP-TOTAL
MOVE 9999999999 TO WS-GROUP-MIN
MOVE 0 TO WS-GROUP-MAX
MOVE 0 TO WS-GROUP-AVG
MOVE 0 TO WS-GROUP-VAR
MOVE 0 TO WS-SUM-SQUARES
MOVE 'N' TO WS-OVERFLOW-FLAG
MOVE "GROUP SUMMARY WRITTEN" TO AR-TEXT
PERFORM 5000-WRITE-AUDIT
.
3400-EXIT.
EXIT.
*> ============================================================
*> 4000-REPORT-SECTION
*> Final summary report with grand total verification
*> ============================================================
4000-REPORT-SECTION SECTION.
4000-REPORT-PROC.
DISPLAY "RPT: Generating final summary report"
MOVE "FINAL REPORT GENERATED" TO AR-TEXT
PERFORM 5000-WRITE-AUDIT
*> Grand total verification line
MOVE WS-GRAND-TOTAL TO GT-VALUE
MOVE WS-GRAND-VERIFY TO GT-VERIFY
IF WS-GRAND-TOTAL = WS-GRAND-VERIFY
MOVE "VERIFIED" TO GT-STATUS
ELSE
MOVE "MISMATCH!!" TO GT-STATUS
END-IF
MOVE WS-GRAND-TOTAL-LINE TO REPORT-REC
WRITE REPORT-REC
ADD 1 TO WS-LINE-COUNT
*> Hash total verification
MOVE SPACES TO WS-AUDIT-REC
STRING "HASH IN=" WS-HASH-TOTAL-IN
" OUT=" WS-HASH-TOTAL-OUT
INTO AR-TEXT
MOVE AR-TEXT TO REPORT-REC
WRITE REPORT-REC
*> Batch control totals
MOVE SPACES TO WS-AUDIT-REC
STRING "BATCH RECS=" WS-BATCH-REC-EXP
" AMT=" WS-BATCH-AMT-EXP
INTO AR-TEXT
MOVE AR-TEXT TO REPORT-REC
WRITE REPORT-REC
*> Error and warning summary
MOVE SPACES TO WS-AUDIT-REC
STRING "ERRORS=" WS-ERROR-COUNT
" WARNINGS=" WS-WARNING-COUNT
INTO AR-TEXT
MOVE AR-TEXT TO REPORT-REC
WRITE REPORT-REC
DISPLAY "RPT: Report generated"
.
4000-EXIT.
EXIT.
*> ============================================================
*> 5000-AUDIT-SECTION
*> Write audit trail records to AUDIT-RPT.DAT
*> ============================================================
5000-AUDIT-SECTION SECTION.
5000-WRITE-AUDIT.
STRING WS-TS-HOUR DELIMITED BY SIZE
":" DELIMITED BY SIZE
WS-TS-MINUTE DELIMITED BY SIZE
":" DELIMITED BY SIZE
WS-TS-SECOND DELIMITED BY SIZE
INTO AR-TIMESTAMP
END-STRING
WRITE AUDIT-REC FROM WS-AUDIT-REC
IF WS-AUDIT-STATUS NOT = '00'
MOVE "WARNING" TO EM-SEVERITY
STRING "AUDIT WRITE ERROR, STATUS="
WS-AUDIT-STATUS
INTO EM-TEXT
END-STRING
PERFORM 6000-ERROR-HANDLE-SECTION
END-IF
.
5000-EXIT.
EXIT.
*> ============================================================
*> 6000-ERROR-HANDLE-SECTION
*> Handle errors by severity level
*> WARNING - display and continue
*> ERROR - increment count and continue
*> FATAL - abort program
*> ============================================================
6000-ERROR-HANDLE-SECTION SECTION.
6000-ERROR-HANDLE-PROC.
MOVE FUNCTION CURRENT-DATE TO WS-TIMESTAMP-STR
DISPLAY " " WS-TS-HOUR ":" WS-TS-MINUTE ":"
WS-TS-SECOND " " EM-SEVERITY ": " EM-TEXT
IF EM-SEVERITY = "FATAL"
MOVE "FATAL ERROR - PROGRAM ABORTED" TO AR-TEXT
PERFORM 5000-WRITE-AUDIT
PERFORM 9000-EXIT-SECTION
STOP RUN
END-IF
.
6000-EXIT.
EXIT.
*> ============================================================
*> 9000-EXIT-SECTION
*> Close all files, display final statistics
*> ============================================================
9000-EXIT-SECTION SECTION.
9000-EXIT-PROC.
MOVE FUNCTION CURRENT-DATE TO WS-TIMESTAMP-STR
DISPLAY " "
DISPLAY "=== FINAL SUMMARY ==="
DISPLAY "Timestamp: " WS-TS-YEAR "-" WS-TS-MONTH "-"
WS-TS-DAY " " WS-TS-HOUR ":" WS-TS-MINUTE ":"
WS-TS-SECOND
DISPLAY "Records read: " WS-RECORDS-READ
DISPLAY "Records written: " WS-RECORDS-WRITTEN
DISPLAY "Groups written: " WS-GROUPS-WRITTEN
DISPLAY "Grand total: " WS-GRAND-TOTAL
DISPLAY "Hash total in: " WS-HASH-TOTAL-IN
DISPLAY "Hash total out: " WS-HASH-TOTAL-OUT
DISPLAY "Warnings counted: " WS-WARNING-COUNT
DISPLAY "Errors counted: " WS-ERROR-COUNT
IF WS-GRAND-TOTAL = WS-GRAND-VERIFY
DISPLAY "Grand total VERIFIED OK"
ELSE
DISPLAY "Grand total VERIFY MISMATCH!"
END-IF
MOVE "PROGRAM COMPLETED NORMALLY" TO AR-TEXT
PERFORM 5000-WRITE-AUDIT
CLOSE FILE-IN
CLOSE FILE-OUT
CLOSE AUDIT-REPORT
CLOSE REPORT-FILE
DISPLAY " "
MOVE FUNCTION CURRENT-DATE TO WS-TIMESTAMP-STR
DISPLAY "EXIT: " WS-TS-HOUR ":" WS-TS-MINUTE ":"
WS-TS-SECOND " Program ended"
.
9000-EXIT.
EXIT.
*> ============================================================
*> WRITE-GROUP-SUMMARY -- PRESERVED ORIGINAL SECTION
*> Original group summary writer (now delegates to 3400)
*> ============================================================
WRITE-GROUP-SUMMARY SECTION.
WRITE-GROUP-SUMMARY-PROC.
PERFORM 3400-WRITE-OUTPUT-SECTION
.
*> ============================================================
*> WRITE-CUSTOMER-HEADER
*> Write formatted customer header to report file
*> ============================================================
WRITE-CUSTOMER-HEADER SECTION.
WRITE-CUSTOMER-HEADER-PROC.
MOVE WS-PREV-KEY TO CH-KEY
MOVE WS-PREV-PLAN TO CH-PLAN
MOVE WS-CUSTOMER-HEADER TO REPORT-REC
WRITE REPORT-REC
ADD 1 TO WS-LINE-COUNT
MOVE "CUSTOMER HEADER WRITTEN" TO AR-TEXT
PERFORM 5000-WRITE-AUDIT
.
*> ============================================================
*> WRITE-PLAN-HEADER
*> Write plan header line to report
*> ============================================================
WRITE-PLAN-HEADER SECTION.
WRITE-PLAN-HEADER-PROC.
MOVE WS-PREV-KEY TO CH-KEY
MOVE WS-PREV-PLAN TO CH-PLAN
MOVE WS-CUSTOMER-HEADER TO REPORT-REC
WRITE REPORT-REC
ADD 1 TO WS-LINE-COUNT
MOVE "PLAN HEADER WRITTEN" TO AR-TEXT
PERFORM 5000-WRITE-AUDIT
.
*> ============================================================
*> WRITE-PLAN-FOOTER
*> Write plan footer, output plan totals, reset accumulators
*> ============================================================
WRITE-PLAN-FOOTER SECTION.
WRITE-PLAN-FOOTER-PROC.
MOVE WS-PREV-PLAN TO PF-PLAN
MOVE WS-PLAN-COUNT TO PF-COUNT
MOVE WS-PLAN-TOTAL TO PF-TOTAL
MOVE WS-PLAN-FOOTER TO REPORT-REC
WRITE REPORT-REC
ADD 1 TO WS-LINE-COUNT
DISPLAY " Plan " WS-PREV-PLAN ": count="
WS-PLAN-COUNT ", total=" WS-PLAN-TOTAL
*> Add plan total to grand total verification
ADD WS-PLAN-TOTAL TO WS-GRAND-VERIFY
*> Reset plan accumulators
MOVE 0 TO WS-PLAN-COUNT
MOVE 0 TO WS-PLAN-TOTAL
MOVE 9999999999 TO WS-PLAN-MIN
MOVE 0 TO WS-PLAN-MAX
MOVE "PLAN FOOTER WRITTEN" TO AR-TEXT
PERFORM 5000-WRITE-AUDIT
.
*> ============================================================
*> WRITE-REPORT-LINE
*> Write detail line to report with page break control
*> ============================================================
WRITE-REPORT-LINE SECTION.
WRITE-REPORT-LINE-PROC.
*> Page break: check line count against page length
IF WS-LINE-COUNT >= WS-PAGE-LENGTH
ADD 1 TO WS-PAGE-NUM
MOVE WS-PAGE-NUM TO PH-PAGE-NUM
MOVE WS-TS-YEAR TO PH-DATE(1:4)
MOVE "-" TO PH-DATE(5:1)
MOVE WS-TS-MONTH TO PH-DATE(6:2)
MOVE "-" TO PH-DATE(8:1)
MOVE WS-TS-DAY TO PH-DATE(9:2)
MOVE WS-PAGE-HEADER TO REPORT-REC
WRITE REPORT-REC
MOVE 0 TO WS-LINE-COUNT
END-IF
MOVE WS-DETAIL-LINE TO REPORT-REC
WRITE REPORT-REC
ADD 1 TO WS-LINE-COUNT
.