*> ============================================================ *> 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 .