*> ============================================================ *> 08-keybreak-aggregate : 套餐统计 (Plan Statistics) *> Input : FILE-IN.DAT (KEY PIC X(10), VALUE PIC 9(10), PLAN X(3)) *> Output: FILE-OUT.DAT (KEY组别统计: 件数,最小值,最大值,合计) *> Report: REPORT-OUT.TXT (formatted 2-level key break report) *> Audit: AUDIT-OUT.TXT (group-level audit trail) *> Coverage: KB-N002, KB-N004~N006, KB-R001 *> 2-level key break: customer (IN-KEY) + plan (BILL-PLAN-CODE) *> Statistics: count, min, max, total, avg, variance, std-dev *> Hash totals for data integrity verification *> ============================================================ IDENTIFICATION DIVISION. PROGRAM-ID. KeyBreakAgg. 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 REPORT-OUT ASSIGN TO "REPORT-OUT.TXT" ORGANIZATION IS LINE SEQUENTIAL FILE STATUS IS WS-REPORT-STATUS. SELECT AUDIT-OUT ASSIGN TO "AUDIT-OUT.TXT" ORGANIZATION IS LINE SEQUENTIAL FILE STATUS IS WS-AUDIT-STATUS. DATA DIVISION. FILE SECTION. FD FILE-IN. 01 FILE-IN-REC. 05 IN-KEY PIC X(10). 05 IN-VALUE PIC 9(10). 05 BILL-PLAN-CODE PIC X(03). 05 FILLER PIC X(22). FD FILE-OUT. 01 FILE-OUT-REC. 05 OUT-KEY PIC X(10). 05 FILLER PIC X VALUE SPACE. 05 OUT-COUNT PIC Z(05)9. 05 FILLER PIC X VALUE SPACE. 05 OUT-MIN PIC Z(09)9. 05 FILLER PIC X VALUE SPACE. 05 OUT-MAX PIC Z(09)9. 05 FILLER PIC X VALUE SPACE. 05 OUT-TOTAL PIC Z(09)9. FD REPORT-OUT. 01 REPORT-OUT-REC PIC X(80). FD AUDIT-OUT. 01 AUDIT-OUT-REC PIC X(80). WORKING-STORAGE SECTION. 01 WS-TELECOM-REC. COPY "telecom/TEL-BILLING.cpy". *> Status flags 01 WS-STATUS. 05 WS-EOF-FLAG PIC X VALUE 'N'. 88 WS-EOF VALUE 'Y' FALSE 'N'. 05 WS-FIRST-REC PIC X VALUE 'Y'. 88 WS-FIRST VALUE 'Y' FALSE 'N'. *> Key break fields 01 WS-PREV-KEY PIC X(10). 01 WS-CURRENT-KEY PIC X(10). 01 WS-PREV-PLAN PIC X(03). 01 WS-CURRENT-PLAN PIC X(03). *> Customer-level accumulators (original augmented) 01 WS-ACCUMULATORS. 05 WS-GROUP-COUNT PIC 9(05) VALUE 0. 05 WS-GROUP-MIN PIC 9(10) VALUE 9999999999. 05 WS-GROUP-MAX PIC 9(10) VALUE 0. 05 WS-GROUP-TOTAL PIC 9(10) VALUE 0. 05 WS-GROUP-AVG PIC 9(10)V9(05) VALUE 0. 05 WS-SUM-SQUARES PIC 9(20) VALUE 0. 05 WS-GROUP-VAR PIC 9(10)V9(05) VALUE 0. 05 WS-GROUP-STDDEV PIC 9(10)V9(05) VALUE 0. *> Plan-level accumulators 01 WS-PLAN-ACCUMULATORS. 05 WS-PLAN-COUNT PIC 9(05) VALUE 0. 05 WS-PLAN-MIN PIC 9(10) VALUE 9999999999. 05 WS-PLAN-MAX PIC 9(10) VALUE 0. 05 WS-PLAN-TOTAL PIC 9(10) VALUE 0. 05 WS-PLAN-AVG PIC 9(10)V9(05) VALUE 0. 05 WS-PLAN-SUM-SQUARES PIC 9(20) VALUE 0. 05 WS-PLAN-VAR PIC 9(10)V9(05) VALUE 0. 05 WS-PLAN-STDDEV PIC 9(10)V9(05) VALUE 0. *> Overflow handling 01 WS-MAX-TOTAL PIC 9(10) VALUE 9999999999. *> Report control 01 WS-LINE-COUNT PIC 9(02) VALUE 99. 01 WS-PAGE-LENGTH PIC 9(02) VALUE 60. 01 WS-PAGE-NUM PIC 9(03) VALUE 0. *> Hash totals (data integrity) 01 WS-HASH-TOTAL-IN PIC 9(18) VALUE 0. 01 WS-HASH-TOTAL-OUT PIC 9(18) VALUE 0. *> Batch counters 01 WS-GROUPS-WRITTEN PIC 9(05) VALUE 0. 01 WS-RECORDS-READ PIC 9(05) VALUE 0. 01 WS-VALUE-NUM PIC 9(10). 01 WS-HASH-VERIFIED PIC X(07) VALUE 'PASSED'. *> File status fields 01 WS-FILE-IN-STATUS PIC X(02). 01 WS-FILE-OUT-STATUS PIC X(02). 01 WS-REPORT-STATUS PIC X(02). 01 WS-AUDIT-STATUS PIC X(02). *> Error handling 01 WS-ERROR-MESSAGE PIC X(60). 01 WS-ERROR-SEVERITY PIC X(07). 88 WS-SEVERITY-WARNING VALUE 'WARNING'. 88 WS-SEVERITY-ERROR VALUE 'ERROR '. 88 WS-SEVERITY-FATAL VALUE 'FATAL '. *> Overflow flag 01 WS-OVERFLOW-FLAG PIC X VALUE 'N'. 88 WS-OVERFLOW VALUE 'Y' FALSE 'N'. *> Timestamp 01 WS-TIMESTAMP PIC X(19). 01 WS-CURRENT-DATE-DATA. 05 WS-CD-DATE PIC X(08). 05 WS-CD-TIME PIC X(06). 05 FILLER PIC X(09). *> Report structures 01 WS-REPORT-HEADER. 05 FILLER PIC X(30) 05 FILLER PIC X(25) VALUE SPACES. 05 FILLER PIC X(06) VALUE 'PAGE: '. 05 WS-HDR-PAGE PIC Z(03)9. 05 FILLER PIC X(15) VALUE SPACES. 01 WS-DETAIL-LINE. 05 FILLER PIC X(05) VALUE SPACES. 05 WS-DL-KEY PIC X(10). 05 FILLER PIC X(03) VALUE SPACES. 05 FILLER PIC X(05) VALUE 'PLAN:'. 05 WS-DL-PLAN PIC X(03). 05 FILLER PIC X(03) VALUE SPACES. 05 FILLER PIC X(06) VALUE 'VALUE:'. 05 WS-DL-VALUE PIC Z(09)9. 05 FILLER PIC X(04) VALUE SPACES. 05 FILLER PIC X(06) VALUE 'CUMUL:'. 05 WS-DL-CUMUL PIC Z(09)9. 05 FILLER PIC X(24) VALUE SPACES. 01 WS-CUST-FOOTER. 05 FILLER PIC X(16) VALUE ' CUSTOMER TOTAL'. 05 FILLER PIC X(05) VALUE ': CNT='. 05 WS-CF-COUNT PIC Z(05)9. 05 FILLER PIC X(03) VALUE ' | '. 05 FILLER PIC X(05) VALUE 'MIN: '. 05 WS-CF-MIN PIC Z(09)9. 05 FILLER PIC X(03) VALUE ' | '. 05 FILLER PIC X(05) VALUE 'MAX: '. 05 WS-CF-MAX PIC Z(09)9. 05 FILLER PIC X(03) VALUE ' | '. 05 FILLER PIC X(06) VALUE 'TOTAL:'. 05 WS-CF-TOTAL PIC Z(09)9. 05 FILLER PIC X(03) VALUE ' | '. 05 FILLER PIC X(05) VALUE 'AVG: '. 05 WS-CF-AVG PIC Z(09)9. 05 FILLER PIC X(20) VALUE SPACES. 01 WS-PLAN-FOOTER. 05 FILLER PIC X(14) VALUE ' PLAN-'. 05 WS-PF-PLAN PIC X(03). 05 FILLER PIC X(05) VALUE ': CNT='. 05 WS-PF-COUNT PIC Z(05)9. 05 FILLER PIC X(03) VALUE ' | '. 05 FILLER PIC X(05) VALUE 'MIN: '. 05 WS-PF-MIN PIC Z(09)9. 05 FILLER PIC X(03) VALUE ' | '. 05 FILLER PIC X(05) VALUE 'MAX: '. 05 WS-PF-MAX PIC Z(09)9. 05 FILLER PIC X(03) VALUE ' | '. 05 FILLER PIC X(06) VALUE 'TOTAL:'. 05 WS-PF-TOTAL PIC Z(09)9. 05 FILLER PIC X(03) VALUE ' | '. 05 FILLER PIC X(05) VALUE 'AVG: '. 05 WS-PF-AVG PIC Z(09)9. 05 FILLER PIC X(03) VALUE ' | '. 05 FILLER PIC X(05) VALUE 'VAR: '. 05 WS-PF-VAR PIC Z(09)9. 05 FILLER PIC X(03) VALUE ' | '. 05 FILLER PIC X(05) VALUE 'STDEV:'. 05 WS-PF-STDDEV PIC Z(09)9. 05 FILLER PIC X(08) VALUE SPACES. 01 WS-GRAND-TOTAL-HEADER. 05 FILLER PIC X(25) VALUE '=== GRAND TOTAL SUMMARY ==='. 05 FILLER PIC X(55) VALUE SPACES. 01 WS-GRAND-TOTAL-LINE. 05 FILLER PIC X(20) VALUE ' Records read: '. 05 WS-GT-RECORDS PIC Z(05)9. 05 FILLER PIC X(53) VALUE SPACES. 01 WS-GT-HASH-LINE. 05 FILLER PIC X(20) VALUE ' Hash IN: '. 05 WS-GT-HASH-IN PIC Z(17)9. 05 FILLER PIC X(43) VALUE SPACES. 01 WS-GT-HASH-LINE-OUT. 05 FILLER PIC X(20) VALUE ' Hash OUT: '. 05 WS-GT-HASH-OUT PIC Z(17)9. 05 FILLER PIC X(43) VALUE SPACES. 01 WS-GT-VERIFY-LINE. 05 FILLER PIC X(20) VALUE ' Verification: '. 05 WS-GT-VERIFY PIC X(07). 05 FILLER PIC X(53) VALUE SPACES. *> Audit record structure 01 WS-AUDIT-LINE. 05 WS-AUDIT-TS PIC X(19). 05 FILLER PIC X VALUE SPACE. 05 WS-AUDIT-TYPE PIC X(08). 05 FILLER PIC X VALUE SPACE. 05 WS-AUDIT-DESC PIC X(51). PROCEDURE DIVISION. MAIN SECTION. MAIN-PROCEDURE. PERFORM 1000-INIT-SECTION PERFORM 2000-OPEN-FILES-SECTION PERFORM 3000-PROCESS-SECTION PERFORM 4000-REPORT-SECTION PERFORM 5000-AUDIT-SECTION PERFORM 9000-EXIT-SECTION STOP RUN. *> 1000-INIT-SECTION 1000-INIT-SECTION. PERFORM GET-TIMESTAMP DISPLAY "[" WS-TIMESTAMP "] KeyBreakAgg START" MOVE SPACES TO WS-PREV-PLAN MOVE 0 TO WS-GROUPS-WRITTEN WS-RECORDS-READ MOVE 0 TO WS-HASH-TOTAL-IN WS-HASH-TOTAL-OUT MOVE 'N' TO WS-OVERFLOW-FLAG MOVE 99 TO WS-LINE-COUNT DISPLAY "Page length: " WS-PAGE-LENGTH . *> 2000-OPEN-FILES-SECTION 2000-OPEN-FILES-SECTION. OPEN INPUT FILE-IN IF WS-FILE-IN-STATUS NOT = '00' STRING 'FILE-IN OPEN FAILED STATUS=' WS-FILE-IN-STATUS INTO WS-ERROR-MESSAGE END-STRING MOVE 'FATAL ' TO WS-ERROR-SEVERITY PERFORM 6000-ERROR-HANDLE-SECTION END-IF DISPLAY "FILE-IN opened status=" WS-FILE-IN-STATUS OPEN OUTPUT FILE-OUT IF WS-FILE-OUT-STATUS NOT = '00' STRING 'FILE-OUT OPEN FAILED STATUS=' WS-FILE-OUT-STATUS INTO WS-ERROR-MESSAGE END-STRING MOVE 'FATAL ' TO WS-ERROR-SEVERITY PERFORM 6000-ERROR-HANDLE-SECTION END-IF DISPLAY "FILE-OUT opened status=" WS-FILE-OUT-STATUS OPEN OUTPUT REPORT-OUT IF WS-REPORT-STATUS NOT = '00' STRING 'REPORT-OUT OPEN FAILED STATUS=' WS-REPORT-STATUS INTO WS-ERROR-MESSAGE END-STRING MOVE 'FATAL ' TO WS-ERROR-SEVERITY PERFORM 6000-ERROR-HANDLE-SECTION END-IF DISPLAY "REPORT-OUT opened status=" WS-REPORT-STATUS OPEN OUTPUT AUDIT-OUT IF WS-AUDIT-STATUS NOT = '00' STRING 'AUDIT-OUT OPEN FAILED STATUS=' WS-AUDIT-STATUS INTO WS-ERROR-MESSAGE END-STRING MOVE 'FATAL ' TO WS-ERROR-SEVERITY PERFORM 6000-ERROR-HANDLE-SECTION END-IF DISPLAY "AUDIT-OUT opened status=" WS-AUDIT-STATUS . *> 3000-PROCESS-SECTION 3000-PROCESS-SECTION. PERFORM 3100-READ-INPUT-SECTION PERFORM UNTIL WS-EOF PERFORM 3200-VALIDATE-SECTION PERFORM 3300-APPLY-RULES-SECTION PERFORM 3400-WRITE-OUTPUT-SECTION PERFORM 3100-READ-INPUT-SECTION END-PERFORM IF WS-RECORDS-READ > 0 PERFORM WRITE-PLAN-AGGREGATE PERFORM WRITE-GROUP-AGGREGATE END-IF . *> 3100-READ-INPUT-SECTION 3100-READ-INPUT-SECTION. READ FILE-IN INTO FILE-IN-REC IF WS-FILE-IN-STATUS = '10' SET WS-EOF TO TRUE DISPLAY "FILE-IN EOF status=" WS-FILE-IN-STATUS ELSE IF WS-FILE-IN-STATUS = '00' ADD 1 TO WS-RECORDS-READ MOVE IN-VALUE TO WS-VALUE-NUM MOVE IN-KEY TO WS-CURRENT-KEY MOVE BILL-PLAN-CODE OF FILE-IN-REC TO WS-CURRENT-PLAN ADD WS-VALUE-NUM TO WS-HASH-TOTAL-IN ELSE STRING 'FILE-IN READ ERROR STATUS=' WS-FILE-IN-STATUS INTO WS-ERROR-MESSAGE END-STRING MOVE 'FATAL ' TO WS-ERROR-SEVERITY PERFORM 6000-ERROR-HANDLE-SECTION END-IF . *> 3200-VALIDATE-SECTION 3200-VALIDATE-SECTION. IF WS-VALUE-NUM = 0 STRING 'Zero value encountered key=' WS-CURRENT-KEY INTO WS-ERROR-MESSAGE END-STRING MOVE 'WARNING' TO WS-ERROR-SEVERITY PERFORM 6000-ERROR-HANDLE-SECTION END-IF IF WS-GROUP-TOTAL > WS-MAX-TOTAL MOVE 'Y' TO WS-OVERFLOW-FLAG STRING 'CUSTOMER TOTAL OVERFLOW key=' WS-CURRENT-KEY INTO WS-ERROR-MESSAGE END-STRING MOVE 'ERROR ' TO WS-ERROR-SEVERITY PERFORM 6000-ERROR-HANDLE-SECTION END-IF IF WS-GROUP-TOTAL + WS-VALUE-NUM > WS-MAX-TOTAL STRING 'Would exceed MAX-TOTAL key=' WS-CURRENT-KEY INTO WS-ERROR-MESSAGE END-STRING MOVE 'WARNING' TO WS-ERROR-SEVERITY PERFORM 6000-ERROR-HANDLE-SECTION END-IF . *> 3300-APPLY-RULES-SECTION 3300-APPLY-RULES-SECTION. IF WS-FIRST MOVE WS-CURRENT-KEY TO WS-PREV-KEY MOVE WS-CURRENT-PLAN TO WS-PREV-PLAN MOVE WS-VALUE-NUM TO WS-GROUP-MIN MOVE WS-VALUE-NUM TO WS-GROUP-MAX MOVE WS-VALUE-NUM TO WS-PLAN-MIN MOVE WS-VALUE-NUM TO WS-PLAN-MAX MOVE 'N' TO WS-FIRST-REC DISPLAY "First record key=" WS-CURRENT-KEY " plan=" WS-CURRENT-PLAN ELSE IF WS-CURRENT-KEY NOT = WS-PREV-KEY IF WS-PREV-PLAN NOT = SPACES DISPLAY "CUST BREAK: " WS-PREV-KEY " -> " WS-CURRENT-KEY PERFORM WRITE-PLAN-AGGREGATE END-IF PERFORM WRITE-GROUP-AGGREGATE MOVE WS-CURRENT-KEY TO WS-PREV-KEY MOVE WS-CURRENT-PLAN TO WS-PREV-PLAN MOVE 9999999999 TO WS-GROUP-MIN MOVE 0 TO WS-GROUP-MAX MOVE 0 TO WS-GROUP-COUNT MOVE 0 TO WS-GROUP-TOTAL MOVE 0 TO WS-GROUP-AVG MOVE 0 TO WS-SUM-SQUARES MOVE 0 TO WS-GROUP-VAR MOVE 0 TO WS-GROUP-STDDEV MOVE 9999999999 TO WS-PLAN-MIN MOVE 0 TO WS-PLAN-MAX MOVE 0 TO WS-PLAN-COUNT MOVE 0 TO WS-PLAN-TOTAL MOVE 0 TO WS-PLAN-AVG MOVE 0 TO WS-PLAN-SUM-SQUARES MOVE 0 TO WS-PLAN-VAR MOVE 0 TO WS-PLAN-STDDEV ELSE IF WS-CURRENT-PLAN NOT = WS-PREV-PLAN DISPLAY "PLAN BREAK: " WS-PREV-PLAN " -> " WS-CURRENT-PLAN PERFORM WRITE-PLAN-AGGREGATE MOVE WS-CURRENT-PLAN TO WS-PREV-PLAN MOVE 9999999999 TO WS-PLAN-MIN MOVE 0 TO WS-PLAN-MAX MOVE 0 TO WS-PLAN-COUNT MOVE 0 TO WS-PLAN-TOTAL MOVE 0 TO WS-PLAN-AVG MOVE 0 TO WS-PLAN-SUM-SQUARES MOVE 0 TO WS-PLAN-VAR MOVE 0 TO WS-PLAN-STDDEV END-IF END-IF END-IF *> Customer-level accumulation (original logic preserved) ADD 1 TO WS-GROUP-COUNT ADD WS-VALUE-NUM TO WS-GROUP-TOTAL COMPUTE WS-SUM-SQUARES = WS-SUM-SQUARES + (WS-VALUE-NUM * WS-VALUE-NUM) IF WS-VALUE-NUM < WS-GROUP-MIN MOVE WS-VALUE-NUM TO WS-GROUP-MIN END-IF IF WS-VALUE-NUM > WS-GROUP-MAX MOVE WS-VALUE-NUM TO WS-GROUP-MAX END-IF *> Plan-level accumulation ADD 1 TO WS-PLAN-COUNT ADD WS-VALUE-NUM TO WS-PLAN-TOTAL COMPUTE WS-PLAN-SUM-SQUARES = WS-PLAN-SUM-SQUARES + (WS-VALUE-NUM * WS-VALUE-NUM) IF WS-VALUE-NUM < WS-PLAN-MIN MOVE WS-VALUE-NUM TO WS-PLAN-MIN END-IF IF WS-VALUE-NUM > WS-PLAN-MAX MOVE WS-VALUE-NUM TO WS-PLAN-MAX END-IF . *> 3400-WRITE-OUTPUT-SECTION 3400-WRITE-OUTPUT-SECTION. MOVE IN-KEY TO WS-DL-KEY MOVE BILL-PLAN-CODE OF FILE-IN-REC TO WS-DL-PLAN MOVE IN-VALUE TO WS-DL-VALUE MOVE WS-GROUP-TOTAL TO WS-DL-CUMUL PERFORM WRITE-DETAIL-LINE . *> 4000-REPORT-SECTION 4000-REPORT-SECTION. PERFORM WRITE-GRAND-TOTAL . *> 5000-AUDIT-SECTION 5000-AUDIT-SECTION. PERFORM GET-TIMESTAMP MOVE WS-TIMESTAMP TO WS-AUDIT-TS MOVE 'SUMMARY' TO WS-AUDIT-TYPE MOVE 'Batch processing complete' TO WS-AUDIT-DESC WRITE AUDIT-OUT-REC FROM WS-AUDIT-LINE IF WS-AUDIT-STATUS NOT = '00' MOVE 'AUDIT-OUT WRITE ERROR' TO WS-ERROR-MESSAGE MOVE 'WARNING' TO WS-ERROR-SEVERITY PERFORM 6000-ERROR-HANDLE-SECTION END-IF STRING 'Records read:' WS-RECORDS-READ ' Groups:' WS-GROUPS-WRITTEN INTO WS-AUDIT-DESC END-STRING WRITE AUDIT-OUT-REC FROM WS-AUDIT-LINE STRING 'Hash IN:' WS-HASH-TOTAL-IN ' OUT:' WS-HASH-TOTAL-OUT ' Verify:' WS-HASH-VERIFIED INTO WS-AUDIT-DESC END-STRING WRITE AUDIT-OUT-REC FROM WS-AUDIT-LINE IF WS-OVERFLOW MOVE 'Overflow was set during processing' TO WS-AUDIT-DESC WRITE AUDIT-OUT-REC FROM WS-AUDIT-LINE END-IF MOVE 'END-OF-JOB' TO WS-AUDIT-DESC WRITE AUDIT-OUT-REC FROM WS-AUDIT-LINE . *> 6000-ERROR-HANDLE-SECTION 6000-ERROR-HANDLE-SECTION. DISPLAY "[" WS-ERROR-SEVERITY "] " WS-ERROR-MESSAGE IF WS-SEVERITY-FATAL PERFORM 9000-EXIT-SECTION STOP RUN END-IF . *> 9000-EXIT-SECTION 9000-EXIT-SECTION. CLOSE FILE-IN IF WS-FILE-IN-STATUS NOT = '00' DISPLAY "FILE-IN CLOSE status=" WS-FILE-IN-STATUS END-IF CLOSE FILE-OUT IF WS-FILE-OUT-STATUS NOT = '00' DISPLAY "FILE-OUT CLOSE status=" WS-FILE-OUT-STATUS END-IF CLOSE REPORT-OUT IF WS-REPORT-STATUS NOT = '00' DISPLAY "REPORT-OUT CLOSE status=" WS-REPORT-STATUS END-IF CLOSE AUDIT-OUT IF WS-AUDIT-STATUS NOT = '00' DISPLAY "AUDIT-OUT CLOSE status=" WS-AUDIT-STATUS END-IF PERFORM GET-TIMESTAMP DISPLAY "[" WS-TIMESTAMP "] === FINAL SUMMARY ===" DISPLAY "Records read: " WS-RECORDS-READ DISPLAY "Groups written: " WS-GROUPS-WRITTEN DISPLAY "Hash total IN: " WS-HASH-TOTAL-IN DISPLAY "Hash total OUT: " WS-HASH-TOTAL-OUT DISPLAY "Hash verification: " WS-HASH-VERIFIED DISPLAY "Overflow occurred: " WS-OVERFLOW-FLAG DISPLAY "[" WS-TIMESTAMP "] KeyBreakAgg END" . *> SUPPORTING PARAGRAPHS *> ------------------------------------------------------------ *> GET-TIMESTAMP : Populate WS-TIMESTAMP from system clock *> ------------------------------------------------------------ GET-TIMESTAMP SECTION. GET-TIMESTAMP-PROC. MOVE FUNCTION CURRENT-DATE TO WS-CURRENT-DATE-DATA STRING WS-CD-DATE(1:4) '-' WS-CD-DATE(5:2) '-' WS-CD-DATE(7:2) ' ' WS-CD-TIME(1:2) ':' WS-CD-TIME(3:2) ':' WS-CD-TIME(5:2) INTO WS-TIMESTAMP END-STRING . *> ------------------------------------------------------------ *> WRITE-GROUP-AGGREGATE — Original aggregate output (kept intact) *> ------------------------------------------------------------ WRITE-GROUP-AGGREGATE SECTION. WRITE-GROUP-AGGREGATE-PROC. IF WS-GROUP-COUNT > 0 COMPUTE WS-GROUP-AVG = WS-GROUP-TOTAL / WS-GROUP-COUNT COMPUTE WS-GROUP-VAR = (WS-SUM-SQUARES - (WS-GROUP-TOTAL * WS-GROUP-TOTAL / WS-GROUP-COUNT)) / WS-GROUP-COUNT COMPUTE WS-GROUP-STDDEV = FUNCTION SQRT(WS-GROUP-VAR) ELSE MOVE 0 TO WS-GROUP-AVG WS-GROUP-VAR WS-GROUP-STDDEV END-IF MOVE WS-PREV-KEY TO OUT-KEY MOVE WS-GROUP-COUNT TO OUT-COUNT MOVE WS-GROUP-MIN TO OUT-MIN MOVE WS-GROUP-MAX TO OUT-MAX MOVE WS-GROUP-TOTAL TO OUT-TOTAL WRITE FILE-OUT-REC IF WS-FILE-OUT-STATUS NOT = '00' STRING 'FILE-OUT WRITE ERROR STATUS=' WS-FILE-OUT-STATUS INTO WS-ERROR-MESSAGE END-STRING MOVE 'ERROR ' TO WS-ERROR-SEVERITY PERFORM 6000-ERROR-HANDLE-SECTION END-IF ADD 1 TO WS-GROUPS-WRITTEN ADD WS-GROUP-TOTAL TO WS-HASH-TOTAL-OUT DISPLAY " Group " WS-PREV-KEY ": count=" WS-GROUP-COUNT ", min=" WS-GROUP-MIN ", max=" WS-GROUP-MAX ", total=" WS-GROUP-TOTAL *> Write customer footer to report MOVE WS-GROUP-COUNT TO WS-CF-COUNT MOVE WS-GROUP-MIN TO WS-CF-MIN MOVE WS-GROUP-MAX TO WS-CF-MAX MOVE WS-GROUP-TOTAL TO WS-CF-TOTAL MOVE WS-GROUP-AVG TO WS-CF-AVG MOVE WS-CUST-FOOTER TO REPORT-OUT-REC PERFORM WRITE-REPORT-LINE *> Write audit for customer group PERFORM GET-TIMESTAMP MOVE WS-TIMESTAMP TO WS-AUDIT-TS MOVE 'CUST GRP' TO WS-AUDIT-TYPE STRING 'Key ' WS-PREV-KEY ' count=' WS-GROUP-COUNT ' total=' WS-GROUP-TOTAL INTO WS-AUDIT-DESC END-STRING WRITE AUDIT-OUT-REC FROM WS-AUDIT-LINE . *> ------------------------------------------------------------ *> WRITE-PLAN-AGGREGATE — Plan-level aggregate output *> ------------------------------------------------------------ WRITE-PLAN-AGGREGATE SECTION. WRITE-PLAN-AGGREGATE-PROC. IF WS-PLAN-COUNT = 0 EXIT SECTION END-IF COMPUTE WS-PLAN-AVG = WS-PLAN-TOTAL / WS-PLAN-COUNT COMPUTE WS-PLAN-VAR = (WS-PLAN-SUM-SQUARES - (WS-PLAN-TOTAL * WS-PLAN-TOTAL / WS-PLAN-COUNT)) / WS-PLAN-COUNT COMPUTE WS-PLAN-STDDEV = FUNCTION SQRT(WS-PLAN-VAR) *> Write plan footer to report MOVE WS-PREV-PLAN TO WS-PF-PLAN MOVE WS-PLAN-COUNT TO WS-PF-COUNT MOVE WS-PLAN-MIN TO WS-PF-MIN MOVE WS-PLAN-MAX TO WS-PF-MAX MOVE WS-PLAN-TOTAL TO WS-PF-TOTAL MOVE WS-PLAN-AVG TO WS-PF-AVG MOVE WS-PLAN-VAR TO WS-PF-VAR MOVE WS-PLAN-STDDEV TO WS-PF-STDDEV MOVE WS-PLAN-FOOTER TO REPORT-OUT-REC PERFORM WRITE-REPORT-LINE DISPLAY " Plan " WS-PREV-PLAN ": count=" WS-PLAN-COUNT ", total=" WS-PLAN-TOTAL *> Write audit for plan group PERFORM GET-TIMESTAMP MOVE WS-TIMESTAMP TO WS-AUDIT-TS MOVE 'PLAN GRP' TO WS-AUDIT-TYPE STRING 'Plan ' WS-PREV-PLAN ' for key ' WS-PREV-KEY ' count=' WS-PLAN-COUNT ' total=' WS-PLAN-TOTAL INTO WS-AUDIT-DESC END-STRING WRITE AUDIT-OUT-REC FROM WS-AUDIT-LINE . *> ------------------------------------------------------------ *> WRITE-REPORT-LINE : Write report line with page break control *> ------------------------------------------------------------ WRITE-REPORT-LINE SECTION. WRITE-REPORT-LINE-PROC. IF WS-LINE-COUNT >= WS-PAGE-LENGTH ADD 1 TO WS-PAGE-NUM MOVE WS-PAGE-NUM TO WS-HDR-PAGE MOVE WS-REPORT-HEADER TO REPORT-OUT-REC WRITE REPORT-OUT-REC MOVE 2 TO WS-LINE-COUNT END-IF WRITE REPORT-OUT-REC ADD 1 TO WS-LINE-COUNT . *> ------------------------------------------------------------ *> WRITE-DETAIL-LINE : Write one detail record to report *> ------------------------------------------------------------ WRITE-DETAIL-LINE SECTION. WRITE-DETAIL-LINE-PROC. MOVE WS-DETAIL-LINE TO REPORT-OUT-REC PERFORM WRITE-REPORT-LINE . *> ------------------------------------------------------------ *> WRITE-GRAND-TOTAL : Grand total summary to report *> ------------------------------------------------------------ WRITE-GRAND-TOTAL SECTION. WRITE-GRAND-TOTAL-PROC. IF WS-HASH-TOTAL-IN = WS-HASH-TOTAL-OUT MOVE 'PASSED' TO WS-HASH-VERIFIED ELSE MOVE 'FAILED' TO WS-HASH-VERIFIED END-IF MOVE WS-RECORDS-READ TO WS-GT-RECORDS MOVE WS-HASH-TOTAL-IN TO WS-GT-HASH-IN MOVE WS-HASH-TOTAL-OUT TO WS-GT-HASH-OUT MOVE WS-HASH-VERIFIED TO WS-GT-VERIFY MOVE WS-GRAND-TOTAL-HEADER TO REPORT-OUT-REC PERFORM WRITE-REPORT-LINE MOVE SPACES TO REPORT-OUT-REC PERFORM WRITE-REPORT-LINE MOVE WS-GRAND-TOTAL-LINE TO REPORT-OUT-REC PERFORM WRITE-REPORT-LINE MOVE WS-GT-HASH-LINE TO REPORT-OUT-REC PERFORM WRITE-REPORT-LINE MOVE WS-GT-HASH-LINE-OUT TO REPORT-OUT-REC PERFORM WRITE-REPORT-LINE MOVE WS-GT-VERIFY-LINE TO REPORT-OUT-REC PERFORM WRITE-REPORT-LINE DISPLAY "Grand total: records=" WS-RECORDS-READ " groups=" WS-GROUPS-WRITTEN DISPLAY "Hash IN=" WS-HASH-TOTAL-IN " OUT=" WS-HASH-TOTAL-OUT " " WS-HASH-VERIFIED .