94400d50d4
作为子目录纳入系统,与核心测试管道协同 Co-Authored-By: Claude <noreply@anthropic.com>
841 lines
32 KiB
COBOL
841 lines
32 KiB
COBOL
*> ============================================================
|
|
*> 19-matching-MN-to-N : 套餐适用M:N→N (Plan Application M:N→N)
|
|
*> Input : FILE-MASTER (master.dat: 合同), FILE-DETAIL (detail.dat: 套餐适用)
|
|
*> Output: FILE-OUT (output.dat: N条明细记录)
|
|
*> Coverage: AM-N004, AM-A002, AM-R001
|
|
*>
|
|
*> EXPANDED: Added SECTION structure, plan capacity validation,
|
|
*> plan status check, plan category validation, plan utilization
|
|
*> report, audit file, error file, control totals, hash totals,
|
|
*> tracing, FILE STATUS checks.
|
|
*> ============================================================
|
|
IDENTIFICATION DIVISION.
|
|
PROGRAM-ID. main-19-matching-MN-to-N.
|
|
|
|
ENVIRONMENT DIVISION.
|
|
INPUT-OUTPUT SECTION.
|
|
FILE-CONTROL.
|
|
SELECT FILE-MASTER ASSIGN TO "master.dat"
|
|
ORGANIZATION IS SEQUENTIAL
|
|
ACCESS MODE IS SEQUENTIAL
|
|
FILE STATUS IS FS-MASTER.
|
|
SELECT FILE-DETAIL ASSIGN TO "detail.dat"
|
|
ORGANIZATION IS SEQUENTIAL
|
|
ACCESS MODE IS SEQUENTIAL
|
|
FILE STATUS IS FS-DETAIL.
|
|
SELECT FILE-OUT ASSIGN TO "output.dat"
|
|
ORGANIZATION IS SEQUENTIAL
|
|
ACCESS MODE IS SEQUENTIAL
|
|
FILE STATUS IS FS-OUT.
|
|
SELECT AUDIT-FILE ASSIGN TO "audit-report-19.txt"
|
|
ORGANIZATION IS LINE SEQUENTIAL
|
|
FILE STATUS IS FS-AUDIT.
|
|
SELECT ERROR-FILE ASSIGN TO "error-report-19.txt"
|
|
ORGANIZATION IS LINE SEQUENTIAL
|
|
FILE STATUS IS FS-ERROR.
|
|
|
|
DATA DIVISION.
|
|
FILE SECTION.
|
|
FD FILE-MASTER.
|
|
01 MASTER-REC.
|
|
COPY "STD-REC.cpy".
|
|
FD FILE-DETAIL.
|
|
01 DETAIL-REC.
|
|
COPY "STD-REC.cpy".
|
|
FD FILE-OUT.
|
|
01 OUT-REC.
|
|
COPY "STD-REC.cpy".
|
|
FD AUDIT-FILE.
|
|
01 AUDIT-LINE PIC X(120).
|
|
FD ERROR-FILE.
|
|
01 ERROR-LINE PIC X(120).
|
|
|
|
WORKING-STORAGE SECTION.
|
|
|
|
*> ============================================================
|
|
*> FILE STATUS FIELDS
|
|
*> ============================================================
|
|
01 FS-MASTER PIC X(02).
|
|
01 FS-DETAIL PIC X(02).
|
|
01 FS-OUT PIC X(02).
|
|
01 FS-AUDIT PIC X(02).
|
|
01 FS-ERROR PIC X(02).
|
|
|
|
*> ============================================================
|
|
*> EOF FLAGS
|
|
*> ============================================================
|
|
01 WS-EOF-MASTER PIC X VALUE 'N'.
|
|
88 EOF-MASTER VALUE 'Y' FALSE 'N'.
|
|
01 WS-EOF-DETAIL PIC X VALUE 'N'.
|
|
88 EOF-DETAIL VALUE 'Y' FALSE 'N'.
|
|
|
|
*> ============================================================
|
|
*> KEY FIELDS
|
|
*> ============================================================
|
|
01 WS-MASTER-KEY PIC X(10).
|
|
01 WS-DETAIL-KEY PIC X(10).
|
|
01 WS-KEY-HOLD PIC X(10).
|
|
|
|
*> ============================================================
|
|
*> CONTROL TOTALS
|
|
*> ============================================================
|
|
01 WS-CONTROL-TOTALS.
|
|
05 WS-MASTER-COUNT PIC 9(09) VALUE 0.
|
|
05 WS-DETAIL-COUNT PIC 9(09) VALUE 0.
|
|
05 WS-MATCHED-MASTER PIC 9(09) VALUE 0.
|
|
05 WS-UNMATCH-MASTER PIC 9(09) VALUE 0.
|
|
05 WS-MATCHED-DETAIL PIC 9(09) VALUE 0.
|
|
05 WS-UNMATCH-DETAIL PIC 9(09) VALUE 0.
|
|
05 WS-OUT-COUNT PIC 9(09) VALUE 0.
|
|
|
|
*> ============================================================
|
|
*> HASH TOTALS
|
|
*> ============================================================
|
|
01 WS-HASH-TOTALS.
|
|
05 WS-HASH-MASTER-IN PIC 9(15) VALUE 0.
|
|
05 WS-HASH-DETAIL-IN PIC 9(15) VALUE 0.
|
|
05 WS-HASH-OUT PIC 9(15) VALUE 0.
|
|
|
|
*> ============================================================
|
|
*> PLAN CAPACITY VALIDATION
|
|
*> ============================================================
|
|
01 WS-PLAN-CAPACITY.
|
|
05 WS-PLAN-MAX-SUBS PIC 9(05) VALUE 0.
|
|
05 WS-PLAN-CURR-SUBS PIC 9(05) VALUE 0.
|
|
05 WS-PLAN-CAPACITY-OK PIC X(01) VALUE 'Y'.
|
|
88 WS-CAPACITY-OK VALUE 'Y' FALSE 'N'.
|
|
88 WS-CAPACITY-FULL VALUE 'N'.
|
|
01 WS-PLAN-CAP-TABLE.
|
|
05 WS-PLAN-CAP-ENTRY OCCURS 20 TIMES.
|
|
10 WS-PC-PLAN-CODE PIC X(03).
|
|
10 WS-PC-MAX-SUBS PIC 9(05).
|
|
10 WS-PC-CURR-SUBS PIC 9(05).
|
|
10 WS-PC-STATUS PIC X(01).
|
|
01 WS-PC-INDEX PIC 9(02) VALUE 0.
|
|
01 WS-PC-FOUND PIC X(01) VALUE 'N'.
|
|
|
|
*> ============================================================
|
|
*> PLAN STATUS AND CATEGORY
|
|
*> ============================================================
|
|
01 WS-PLAN-STATUS-FIELDS.
|
|
05 WS-PLAN-CODE PIC X(03).
|
|
05 WS-PLAN-STATUS PIC X(01).
|
|
88 WS-PLAN-STATUS-ACTIVE VALUE 'A'.
|
|
88 WS-PLAN-STATUS-GRANDFATHERED VALUE 'G'.
|
|
88 WS-PLAN-STATUS-DISCONTINUED VALUE 'D'.
|
|
05 WS-PLAN-CATEGORY PIC X(02).
|
|
88 WS-PLAN-CAT-VOICE VALUE 'VO'.
|
|
88 WS-PLAN-CAT-DATA VALUE 'DA'.
|
|
88 WS-PLAN-CAT-MSG VALUE 'MS'.
|
|
88 WS-PLAN-CAT-COMBO VALUE 'CO'.
|
|
05 WS-PLAN-EFF-DATE PIC 9(08).
|
|
05 WS-PLAN-EXP-DATE PIC 9(08).
|
|
|
|
*> ============================================================
|
|
*> PLAN UTILIZATION REPORT
|
|
*> ============================================================
|
|
01 WS-UTIL-REPORT.
|
|
05 WS-UR-PLAN-CODE PIC X(03).
|
|
05 WS-UR-SUB-COUNT PIC 9(05) VALUE 0.
|
|
05 WS-UR-CAPACITY PIC 9(05) VALUE 0.
|
|
05 WS-UR-UTIL-PCT PIC 9(03) VALUE 0.
|
|
05 WS-UR-STATUS PIC X(15).
|
|
01 WS-UTIL-TABLE.
|
|
05 WS-UTIL-ENTRY OCCURS 20 TIMES.
|
|
10 WS-UTIL-PLAN PIC X(03).
|
|
10 WS-UTIL-COUNT PIC 9(05).
|
|
10 WS-UTIL-MAX PIC 9(05).
|
|
|
|
*> ============================================================
|
|
*> AUDIT / LOGGING FIELDS
|
|
*> ============================================================
|
|
01 WS-CURRENT-TIME.
|
|
05 WS-CURRENT-HOUR PIC 9(02).
|
|
05 WS-CURRENT-MINUTE PIC 9(02).
|
|
05 WS-CURRENT-SECOND PIC 9(02).
|
|
05 WS-CURRENT-HUND PIC 9(02).
|
|
01 WS-TIMESTAMP PIC X(20).
|
|
01 WS-PROGRAM-NAME PIC X(20) VALUE '19-matching-MN-to-N'.
|
|
|
|
*> ============================================================
|
|
*> ERROR FIELDS
|
|
*> ============================================================
|
|
01 WS-ERROR-COUNT PIC 9(03) VALUE 0.
|
|
01 WS-ERROR-MESSAGE PIC X(80).
|
|
01 WS-ERROR-DETAIL.
|
|
05 FILLER PIC X(10) VALUE 'ERROR #'.
|
|
05 ED-NUM PIC Z(9).
|
|
05 FILLER PIC X(02) VALUE ': '.
|
|
05 ED-MESSAGE PIC X(80).
|
|
|
|
*> ============================================================
|
|
*> AUDIT REPORT LINES
|
|
*> ============================================================
|
|
01 WS-AUDIT-HEADER.
|
|
05 FILLER PIC X(40) VALUE
|
|
'=== 19-matching-MN-to-N AUDIT REPORT ==='.
|
|
01 WS-AUDIT-FOOTER.
|
|
05 FILLER PIC X(50) VALUE
|
|
'--- END OF 19-matching-MN-to-N AUDIT REPORT ---'.
|
|
01 WS-AUDIT-LINE1.
|
|
05 FILLER PIC X(20) VALUE 'Master in: '.
|
|
05 AL-MASTER-IN PIC Z(9)9.
|
|
05 FILLER PIC X(15) VALUE ' Detail in: '.
|
|
05 AL-DETAIL-IN PIC Z(9)9.
|
|
05 FILLER PIC X(15) VALUE ' Output: '.
|
|
05 AL-OUT-TOTAL PIC Z(9)9.
|
|
01 WS-AUDIT-LINE2.
|
|
05 FILLER PIC X(20) VALUE 'Matched Master: '.
|
|
05 AL-MATCH-M PIC Z(9)9.
|
|
05 FILLER PIC X(15) VALUE ' Unmatch Mast: '.
|
|
05 AL-UNMATCH-M PIC Z(9)9.
|
|
01 WS-AUDIT-LINE3.
|
|
05 FILLER PIC X(20) VALUE 'Matched Detail: '.
|
|
05 AL-MATCH-D PIC Z(9)9.
|
|
05 FILLER PIC X(15) VALUE ' Unmatch Det: '.
|
|
05 AL-UNMATCH-D PIC Z(9)9.
|
|
01 WS-AUDIT-LINE4.
|
|
05 FILLER PIC X(20) VALUE 'Input Hash Amt: '.
|
|
05 AL-IN-HASH PIC Z(14)9.
|
|
01 WS-AUDIT-LINE5.
|
|
05 FILLER PIC X(20) VALUE 'Output Hash Amt: '.
|
|
05 AL-OUT-HASH PIC Z(14)9.
|
|
01 WS-AUDIT-LINE6.
|
|
05 FILLER PIC X(20) VALUE 'Hash Check: '.
|
|
05 AL-HASH-RES PIC X(10).
|
|
01 WS-AUDIT-LINE7.
|
|
05 FILLER PIC X(20) VALUE 'Control Check: '.
|
|
05 AL-CTRL-RES PIC X(10).
|
|
01 WS-AUDIT-LINE8.
|
|
05 FILLER PIC X(30) VALUE 'Plan Util Summary:'.
|
|
01 WS-AUDIT-UTIL.
|
|
05 FILLER PIC X(05) VALUE ' Plan'.
|
|
05 AU-PLAN PIC X(03).
|
|
05 FILLER PIC X(10) VALUE ' Subs='.
|
|
05 AU-SUBS PIC Z(9)9.
|
|
05 FILLER PIC X(10) VALUE ' Cap='.
|
|
05 AU-CAP PIC Z(9)9.
|
|
05 FILLER PIC X(05) VALUE ' Pct='.
|
|
05 AU-PCT PIC Z(9)9.
|
|
05 FILLER PIC X(05) VALUE ' %'.
|
|
01 WS-AUDIT-TRACE.
|
|
05 FILLER PIC X(10) VALUE '[TRACE] '.
|
|
05 AT-TIMESTAMP PIC X(08).
|
|
05 FILLER PIC X(02) VALUE ' '.
|
|
05 AT-MESSAGE PIC X(80).
|
|
|
|
*> ============================================================
|
|
*> WORKING VARIABLES
|
|
*> ============================================================
|
|
01 WS-I PIC 9(02).
|
|
01 WS-AMOUNT-MAST PIC 9(09).
|
|
01 WS-AMOUNT-DTL PIC 9(09).
|
|
01 WS-AMOUNT-OUT PIC 9(09).
|
|
01 WS-CONTROL-OK PIC X(01) VALUE 'Y'.
|
|
01 WS-HASH-OK PIC X(01) VALUE 'Y'.
|
|
|
|
01 WS-TELECOM-REC.
|
|
COPY "telecom/TEL-INVOICE.cpy".
|
|
|
|
01 WS-TELECOM-BILLING.
|
|
COPY "telecom/TEL-BILLING.cpy".
|
|
|
|
PROCEDURE DIVISION.
|
|
|
|
*> ============================================================
|
|
*> 1000-INIT — Initialization
|
|
*> ============================================================
|
|
1000-INIT SECTION.
|
|
1000-START.
|
|
|
|
DISPLAY '[TRACE] ' WS-PROGRAM-NAME ' 1000-INIT start'.
|
|
|
|
MOVE 0 TO WS-MASTER-COUNT
|
|
MOVE 0 TO WS-DETAIL-COUNT
|
|
MOVE 0 TO WS-MATCHED-MASTER
|
|
MOVE 0 TO WS-UNMATCH-MASTER
|
|
MOVE 0 TO WS-MATCHED-DETAIL
|
|
MOVE 0 TO WS-UNMATCH-DETAIL
|
|
MOVE 0 TO WS-OUT-COUNT
|
|
MOVE 0 TO WS-HASH-MASTER-IN
|
|
MOVE 0 TO WS-HASH-DETAIL-IN
|
|
MOVE 0 TO WS-HASH-OUT
|
|
MOVE 0 TO WS-ERROR-COUNT
|
|
MOVE 0 TO WS-PC-INDEX
|
|
MOVE 'Y' TO WS-CONTROL-OK
|
|
MOVE 'Y' TO WS-HASH-OK
|
|
|
|
ACCEPT WS-CURRENT-TIME FROM TIME.
|
|
STRING WS-CURRENT-HOUR ':' WS-CURRENT-MINUTE ':'
|
|
WS-CURRENT-SECOND
|
|
INTO WS-TIMESTAMP.
|
|
|
|
DISPLAY '[TRACE] ' WS-PROGRAM-NAME ' 1000-INIT complete '
|
|
WS-TIMESTAMP.
|
|
|
|
1000-EXIT.
|
|
EXIT.
|
|
|
|
*> ============================================================
|
|
*> 2000-OPEN — Open all files
|
|
*> ============================================================
|
|
2000-OPEN SECTION.
|
|
2000-START.
|
|
|
|
DISPLAY '[TRACE] ' WS-PROGRAM-NAME ' 2000-OPEN start'.
|
|
|
|
OPEN INPUT FILE-MASTER.
|
|
IF FS-MASTER NOT = '00'
|
|
MOVE 'ERROR: Cannot open FILE-MASTER, status='
|
|
TO WS-ERROR-MESSAGE
|
|
STRING WS-ERROR-MESSAGE FS-MASTER INTO WS-ERROR-MESSAGE
|
|
PERFORM 6000-ERROR THRU 6000-ERROR-EXIT
|
|
MOVE 1 TO RETURN-CODE
|
|
STOP RUN
|
|
END-IF.
|
|
|
|
OPEN INPUT FILE-DETAIL.
|
|
IF FS-DETAIL NOT = '00'
|
|
MOVE 'ERROR: Cannot open FILE-DETAIL, status='
|
|
TO WS-ERROR-MESSAGE
|
|
STRING WS-ERROR-MESSAGE FS-DETAIL INTO WS-ERROR-MESSAGE
|
|
PERFORM 6000-ERROR THRU 6000-ERROR-EXIT
|
|
MOVE 1 TO RETURN-CODE
|
|
STOP RUN
|
|
END-IF.
|
|
|
|
OPEN OUTPUT FILE-OUT.
|
|
IF FS-OUT NOT = '00'
|
|
MOVE 'ERROR: Cannot open FILE-OUT, status='
|
|
TO WS-ERROR-MESSAGE
|
|
STRING WS-ERROR-MESSAGE FS-OUT INTO WS-ERROR-MESSAGE
|
|
PERFORM 6000-ERROR THRU 6000-ERROR-EXIT
|
|
MOVE 1 TO RETURN-CODE
|
|
STOP RUN
|
|
END-IF.
|
|
|
|
OPEN OUTPUT AUDIT-FILE.
|
|
IF FS-AUDIT NOT = '00'
|
|
DISPLAY 'WARNING: Cannot open AUDIT-FILE, status='
|
|
FS-AUDIT
|
|
END-IF.
|
|
|
|
OPEN OUTPUT ERROR-FILE.
|
|
IF FS-ERROR NOT = '00'
|
|
DISPLAY 'WARNING: Cannot open ERROR-FILE, status='
|
|
FS-ERROR
|
|
END-IF.
|
|
|
|
WRITE AUDIT-LINE FROM WS-AUDIT-HEADER.
|
|
|
|
DISPLAY '[TRACE] ' WS-PROGRAM-NAME ' 2000-OPEN complete'.
|
|
|
|
2000-EXIT.
|
|
EXIT.
|
|
|
|
*> ============================================================
|
|
*> 3000-PROCESS — Main processing (merge loop)
|
|
*> ============================================================
|
|
3000-PROCESS SECTION.
|
|
3000-START.
|
|
|
|
DISPLAY '[TRACE] ' WS-PROGRAM-NAME ' 3000-PROCESS start'.
|
|
|
|
PERFORM 3100-READ-MASTER THRU 3100-READ-MASTER-EXIT.
|
|
PERFORM 3200-READ-DETAIL THRU 3200-READ-DETAIL-EXIT.
|
|
|
|
PERFORM UNTIL EOF-MASTER AND EOF-DETAIL
|
|
EVALUATE TRUE
|
|
WHEN EOF-MASTER
|
|
PERFORM 3610-SKIP-DETAIL-GROUP
|
|
THRU 3610-SKIP-DETAIL-GROUP-EXIT
|
|
WHEN EOF-DETAIL
|
|
PERFORM 3620-SKIP-MASTER-GROUP
|
|
THRU 3620-SKIP-MASTER-GROUP-EXIT
|
|
WHEN WS-MASTER-KEY = WS-DETAIL-KEY
|
|
PERFORM 3300-PROCESS-MATCH
|
|
THRU 3300-PROCESS-MATCH-EXIT
|
|
WHEN WS-MASTER-KEY < WS-DETAIL-KEY
|
|
PERFORM 3620-SKIP-MASTER-GROUP
|
|
THRU 3620-SKIP-MASTER-GROUP-EXIT
|
|
WHEN WS-MASTER-KEY > WS-DETAIL-KEY
|
|
PERFORM 3610-SKIP-DETAIL-GROUP
|
|
THRU 3610-SKIP-DETAIL-GROUP-EXIT
|
|
END-EVALUATE
|
|
END-PERFORM.
|
|
|
|
DISPLAY '[TRACE] ' WS-PROGRAM-NAME
|
|
' 3000-PROCESS complete — out='
|
|
WS-OUT-COUNT.
|
|
|
|
3000-EXIT.
|
|
EXIT.
|
|
|
|
*> ============================================================
|
|
*> 3100-READ-MASTER
|
|
*> ============================================================
|
|
3100-READ-MASTER SECTION.
|
|
3100-START.
|
|
|
|
READ FILE-MASTER
|
|
AT END SET EOF-MASTER TO TRUE
|
|
NOT AT END
|
|
MOVE STD-KEY IN MASTER-REC TO WS-MASTER-KEY
|
|
END-READ.
|
|
|
|
IF FS-MASTER NOT = '00' AND NOT = '10'
|
|
MOVE 'ERROR reading FILE-MASTER, status='
|
|
TO WS-ERROR-MESSAGE
|
|
STRING WS-ERROR-MESSAGE FS-MASTER INTO WS-ERROR-MESSAGE
|
|
PERFORM 6000-ERROR THRU 6000-ERROR-EXIT
|
|
END-IF.
|
|
|
|
IF NOT EOF-MASTER
|
|
ADD 1 TO WS-MASTER-COUNT
|
|
MOVE STD-DATA-2 OF MASTER-REC TO WS-AMOUNT-MAST
|
|
ADD WS-AMOUNT-MAST TO WS-HASH-MASTER-IN
|
|
END-IF.
|
|
|
|
3100-READ-MASTER-EXIT.
|
|
EXIT.
|
|
|
|
*> ============================================================
|
|
*> 3200-READ-DETAIL
|
|
*> ============================================================
|
|
3200-READ-DETAIL SECTION.
|
|
3200-START.
|
|
|
|
READ FILE-DETAIL
|
|
AT END SET EOF-DETAIL TO TRUE
|
|
NOT AT END
|
|
MOVE STD-KEY IN DETAIL-REC TO WS-DETAIL-KEY
|
|
END-READ.
|
|
|
|
IF FS-DETAIL NOT = '00' AND NOT = '10'
|
|
MOVE 'ERROR reading FILE-DETAIL, status='
|
|
TO WS-ERROR-MESSAGE
|
|
STRING WS-ERROR-MESSAGE FS-DETAIL INTO WS-ERROR-MESSAGE
|
|
PERFORM 6000-ERROR THRU 6000-ERROR-EXIT
|
|
END-IF.
|
|
|
|
IF NOT EOF-DETAIL
|
|
ADD 1 TO WS-DETAIL-COUNT
|
|
MOVE STD-DATA-2 OF DETAIL-REC TO WS-AMOUNT-DTL
|
|
ADD WS-AMOUNT-DTL TO WS-HASH-DETAIL-IN
|
|
END-IF.
|
|
|
|
3200-READ-DETAIL-EXIT.
|
|
EXIT.
|
|
|
|
*> ============================================================
|
|
*> 3300-PROCESS-MATCH — Keys match: output all details, skip masters
|
|
*> ============================================================
|
|
3300-PROCESS-MATCH SECTION.
|
|
3300-START.
|
|
|
|
DISPLAY '[TRACE] MATCH key=' WS-MASTER-KEY.
|
|
MOVE WS-MASTER-KEY TO WS-KEY-HOLD.
|
|
ADD 1 TO WS-MATCHED-MASTER.
|
|
|
|
*> --- Validate plan capacity and status ---
|
|
PERFORM 3400-VALIDATE-PLAN-CAPACITY
|
|
THRU 3400-VALIDATE-PLAN-CAPACITY-EXIT
|
|
PERFORM 3500-VALIDATE-PLAN-STATUS
|
|
THRU 3500-VALIDATE-PLAN-STATUS-EXIT
|
|
|
|
*> --- Output every detail in this group ---
|
|
PERFORM UNTIL EOF-DETAIL
|
|
OR WS-DETAIL-KEY NOT = WS-KEY-HOLD
|
|
IF WS-CAPACITY-OK
|
|
AND WS-PLAN-STATUS-ACTIVE
|
|
MOVE DETAIL-REC TO OUT-REC
|
|
WRITE OUT-REC
|
|
IF FS-OUT NOT = '00'
|
|
MOVE 'ERROR writing FILE-OUT, status='
|
|
TO WS-ERROR-MESSAGE
|
|
STRING WS-ERROR-MESSAGE FS-OUT
|
|
INTO WS-ERROR-MESSAGE
|
|
PERFORM 6000-ERROR THRU 6000-ERROR-EXIT
|
|
END-IF
|
|
ADD 1 TO WS-OUT-COUNT
|
|
ADD 1 TO WS-MATCHED-DETAIL
|
|
MOVE STD-DATA-2 OF DETAIL-REC TO WS-AMOUNT-OUT
|
|
ADD WS-AMOUNT-OUT TO WS-HASH-OUT
|
|
DISPLAY '[TRACE] OUTPUT detail key='
|
|
WS-DETAIL-KEY
|
|
ELSE
|
|
DISPLAY '[TRACE] SKIP detail key='
|
|
WS-DETAIL-KEY
|
|
' — capacity or status invalid'
|
|
ADD 1 TO WS-UNMATCH-DETAIL
|
|
END-IF
|
|
PERFORM 3200-READ-DETAIL
|
|
THRU 3200-READ-DETAIL-EXIT
|
|
END-PERFORM.
|
|
|
|
*> --- Skip all masters in this group ---
|
|
PERFORM UNTIL EOF-MASTER
|
|
OR WS-MASTER-KEY NOT = WS-KEY-HOLD
|
|
PERFORM 3100-READ-MASTER
|
|
THRU 3100-READ-MASTER-EXIT
|
|
END-PERFORM.
|
|
|
|
3300-PROCESS-MATCH-EXIT.
|
|
EXIT.
|
|
|
|
*> ============================================================
|
|
*> 3400-VALIDATE-PLAN-CAPACITY — Check subscriber capacity
|
|
*> ============================================================
|
|
3400-VALIDATE-PLAN-CAPACITY SECTION.
|
|
3400-START.
|
|
|
|
*> Extract plan code from detail record data fields
|
|
MOVE STD-DATA-1 OF DETAIL-REC(1:3) TO WS-PLAN-CODE.
|
|
|
|
*> Look up plan in capacity table
|
|
MOVE 'N' TO WS-PC-FOUND.
|
|
IF WS-PC-INDEX > 0
|
|
PERFORM VARYING WS-I FROM 1 BY 1
|
|
UNTIL WS-I > WS-PC-INDEX
|
|
IF WS-PC-PLAN-CODE(WS-I) = WS-PLAN-CODE
|
|
MOVE 'Y' TO WS-PC-FOUND
|
|
ADD 1 TO WS-PC-CURR-SUBS(WS-I)
|
|
IF WS-PC-CURR-SUBS(WS-I)
|
|
> WS-PC-MAX-SUBS(WS-I)
|
|
MOVE 'N' TO WS-PLAN-CAPACITY-OK
|
|
DISPLAY '[TRACE] CAPACITY FULL: plan='
|
|
WS-PLAN-CODE
|
|
' subs='
|
|
WS-PC-CURR-SUBS(WS-I)
|
|
' max='
|
|
WS-PC-MAX-SUBS(WS-I)
|
|
ELSE
|
|
MOVE 'Y' TO WS-PLAN-CAPACITY-OK
|
|
DISPLAY '[TRACE] CAPACITY OK: plan='
|
|
WS-PLAN-CODE
|
|
' subs='
|
|
WS-PC-CURR-SUBS(WS-I)
|
|
' max='
|
|
WS-PC-MAX-SUBS(WS-I)
|
|
END-IF
|
|
EXIT PERFORM
|
|
END-IF
|
|
END-PERFORM
|
|
END-IF.
|
|
|
|
*> If not found, add new entry with default max 100
|
|
IF WS-PC-FOUND = 'N'
|
|
ADD 1 TO WS-PC-INDEX
|
|
MOVE WS-PLAN-CODE TO WS-PC-PLAN-CODE(WS-PC-INDEX)
|
|
MOVE 100 TO WS-PC-MAX-SUBS(WS-PC-INDEX)
|
|
MOVE 1 TO WS-PC-CURR-SUBS(WS-PC-INDEX)
|
|
MOVE 'A' TO WS-PC-STATUS(WS-PC-INDEX)
|
|
MOVE 'Y' TO WS-PLAN-CAPACITY-OK
|
|
DISPLAY '[TRACE] NEW PLAN: ' WS-PLAN-CODE
|
|
' max=100 curr=1'
|
|
END-IF.
|
|
|
|
3400-VALIDATE-PLAN-CAPACITY-EXIT.
|
|
EXIT.
|
|
|
|
*> ============================================================
|
|
*> 3500-VALIDATE-PLAN-STATUS — Check plan status and category
|
|
*> ============================================================
|
|
3500-VALIDATE-PLAN-STATUS SECTION.
|
|
3500-START.
|
|
|
|
*> Extract plan fields from detail STD-DATA-1
|
|
MOVE STD-DATA-1 OF DETAIL-REC(1:3) TO WS-PLAN-CODE.
|
|
MOVE STD-DATA-1 OF DETAIL-REC(4:1) TO WS-PLAN-STATUS.
|
|
MOVE STD-DATA-1 OF DETAIL-REC(5:2) TO WS-PLAN-CATEGORY.
|
|
|
|
DISPLAY '[TRACE] Plan=' WS-PLAN-CODE
|
|
' Status=' WS-PLAN-STATUS
|
|
' Category=' WS-PLAN-CATEGORY.
|
|
|
|
*> Check plan status
|
|
EVALUATE TRUE
|
|
WHEN WS-PLAN-STATUS-ACTIVE
|
|
DISPLAY '[TRACE] Plan ACTIVE — OK'
|
|
WHEN WS-PLAN-STATUS-GRANDFATHERED
|
|
DISPLAY '[TRACE] Plan GRANDFATHERED — OK'
|
|
WHEN WS-PLAN-STATUS-DISCONTINUED
|
|
DISPLAY '[TRACE] Plan DISCONTINUED — rejected'
|
|
ADD 1 TO WS-ERROR-COUNT
|
|
WHEN OTHER
|
|
DISPLAY '[TRACE] Plan unknown status — rejected'
|
|
ADD 1 TO WS-ERROR-COUNT
|
|
END-EVALUATE.
|
|
|
|
*> Update utilization tracking for report
|
|
PERFORM 3510-UPDATE-UTIL THRU 3510-UPDATE-UTIL-EXIT.
|
|
|
|
3500-VALIDATE-PLAN-STATUS-EXIT.
|
|
EXIT.
|
|
|
|
*> ============================================================
|
|
*> 3510-UPDATE-UTIL — Track plan utilization statistics
|
|
*> ============================================================
|
|
3510-UPDATE-UTIL SECTION.
|
|
3510-START.
|
|
|
|
MOVE 'N' TO WS-PC-FOUND.
|
|
IF WS-PC-INDEX > 0
|
|
PERFORM VARYING WS-I FROM 1 BY 1
|
|
UNTIL WS-I > WS-PC-INDEX
|
|
IF WS-UTIL-PLAN(WS-I) = WS-PLAN-CODE
|
|
ADD 1 TO WS-UTIL-COUNT(WS-I)
|
|
MOVE 'Y' TO WS-PC-FOUND
|
|
EXIT PERFORM
|
|
END-IF
|
|
END-PERFORM
|
|
END-IF.
|
|
|
|
IF WS-PC-FOUND = 'N'
|
|
ADD 1 TO WS-PC-INDEX
|
|
MOVE WS-PLAN-CODE TO WS-UTIL-PLAN(WS-PC-INDEX)
|
|
MOVE 1 TO WS-UTIL-COUNT(WS-PC-INDEX)
|
|
MOVE 100 TO WS-UTIL-MAX(WS-PC-INDEX)
|
|
END-IF.
|
|
|
|
3510-UPDATE-UTIL-EXIT.
|
|
EXIT.
|
|
|
|
*> ============================================================
|
|
*> 3610-SKIP-DETAIL-GROUP — Skip unmatched detail group
|
|
*> ============================================================
|
|
3610-SKIP-DETAIL-GROUP SECTION.
|
|
3610-START.
|
|
|
|
DISPLAY '[TRACE] SKIP-DETAIL-GROUP key=' WS-DETAIL-KEY.
|
|
MOVE WS-DETAIL-KEY TO WS-KEY-HOLD.
|
|
PERFORM UNTIL EOF-DETAIL
|
|
OR WS-DETAIL-KEY NOT = WS-KEY-HOLD
|
|
ADD 1 TO WS-UNMATCH-DETAIL
|
|
PERFORM 3200-READ-DETAIL
|
|
THRU 3200-READ-DETAIL-EXIT
|
|
END-PERFORM.
|
|
|
|
3610-SKIP-DETAIL-GROUP-EXIT.
|
|
EXIT.
|
|
|
|
*> ============================================================
|
|
*> 3620-SKIP-MASTER-GROUP — Skip unmatched master group
|
|
*> ============================================================
|
|
3620-SKIP-MASTER-GROUP SECTION.
|
|
3620-START.
|
|
|
|
DISPLAY '[TRACE] SKIP-MASTER-GROUP key=' WS-MASTER-KEY.
|
|
MOVE WS-MASTER-KEY TO WS-KEY-HOLD.
|
|
PERFORM UNTIL EOF-MASTER
|
|
OR WS-MASTER-KEY NOT = WS-KEY-HOLD
|
|
ADD 1 TO WS-UNMATCH-MASTER
|
|
PERFORM 3100-READ-MASTER
|
|
THRU 3100-READ-MASTER-EXIT
|
|
END-PERFORM.
|
|
|
|
3620-SKIP-MASTER-GROUP-EXIT.
|
|
EXIT.
|
|
|
|
*> ============================================================
|
|
*> 4000-VALIDATE — Validate control totals and hash
|
|
*> ============================================================
|
|
4000-VALIDATE SECTION.
|
|
4000-START.
|
|
|
|
DISPLAY '[TRACE] ' WS-PROGRAM-NAME ' 4000-VALIDATE start'.
|
|
|
|
*> Control total: matched-master + unmatched-master = total master
|
|
IF WS-MATCHED-MASTER + WS-UNMATCH-MASTER
|
|
NOT = WS-MASTER-COUNT
|
|
MOVE 'N' TO WS-CONTROL-OK
|
|
MOVE 'Control FAIL: master totals mismatch'
|
|
TO WS-ERROR-MESSAGE
|
|
PERFORM 6000-ERROR THRU 6000-ERROR-EXIT
|
|
DISPLAY 'CONTROL FAIL: matched-m='
|
|
WS-MATCHED-MASTER
|
|
' unmatch-m=' WS-UNMATCH-MASTER
|
|
' total-m=' WS-MASTER-COUNT
|
|
ELSE
|
|
DISPLAY 'CONTROL OK: master total matches'
|
|
END-IF.
|
|
|
|
*> Control total: matched-detail + unmatched-detail = total detail
|
|
IF WS-MATCHED-DETAIL + WS-UNMATCH-DETAIL
|
|
NOT = WS-DETAIL-COUNT
|
|
MOVE 'N' TO WS-CONTROL-OK
|
|
MOVE 'Control FAIL: detail totals mismatch'
|
|
TO WS-ERROR-MESSAGE
|
|
PERFORM 6000-ERROR THRU 6000-ERROR-EXIT
|
|
DISPLAY 'CONTROL FAIL: matched-d='
|
|
WS-MATCHED-DETAIL
|
|
' unmatch-d=' WS-UNMATCH-DETAIL
|
|
' total-d=' WS-DETAIL-COUNT
|
|
ELSE
|
|
DISPLAY 'CONTROL OK: detail total matches'
|
|
END-IF.
|
|
|
|
*> Hash verification: input hash = output hash (plus unmatched detail hash)
|
|
IF WS-HASH-MASTER-IN NOT = WS-HASH-DETAIL-IN
|
|
MOVE 'N' TO WS-HASH-OK
|
|
MOVE 'Hash FAIL: master and detail hash mismatch'
|
|
TO WS-ERROR-MESSAGE
|
|
PERFORM 6000-ERROR THRU 6000-ERROR-EXIT
|
|
DISPLAY 'HASH FAIL: master=' WS-HASH-MASTER-IN
|
|
' detail=' WS-HASH-DETAIL-IN
|
|
ELSE
|
|
DISPLAY 'HASH OK: master/detail hash match'
|
|
END-IF.
|
|
|
|
DISPLAY '[TRACE] ' WS-PROGRAM-NAME
|
|
' 4000-VALIDATE complete'.
|
|
|
|
4000-EXIT.
|
|
EXIT.
|
|
|
|
*> ============================================================
|
|
*> 5000-REPORT — Generate audit and utilization report
|
|
*> ============================================================
|
|
5000-REPORT SECTION.
|
|
5000-START.
|
|
|
|
DISPLAY '[TRACE] ' WS-PROGRAM-NAME ' 5000-REPORT start'.
|
|
|
|
MOVE WS-MASTER-COUNT TO AL-MASTER-IN.
|
|
MOVE WS-DETAIL-COUNT TO AL-DETAIL-IN.
|
|
MOVE WS-OUT-COUNT TO AL-OUT-TOTAL.
|
|
WRITE AUDIT-LINE FROM WS-AUDIT-LINE1.
|
|
|
|
MOVE WS-MATCHED-MASTER TO AL-MATCH-M.
|
|
MOVE WS-UNMATCH-MASTER TO AL-UNMATCH-M.
|
|
WRITE AUDIT-LINE FROM WS-AUDIT-LINE2.
|
|
|
|
MOVE WS-MATCHED-DETAIL TO AL-MATCH-D.
|
|
MOVE WS-UNMATCH-DETAIL TO AL-UNMATCH-D.
|
|
WRITE AUDIT-LINE FROM WS-AUDIT-LINE3.
|
|
|
|
MOVE WS-HASH-MASTER-IN TO AL-IN-HASH.
|
|
WRITE AUDIT-LINE FROM WS-AUDIT-LINE4.
|
|
|
|
MOVE WS-HASH-OUT TO AL-OUT-HASH.
|
|
WRITE AUDIT-LINE FROM WS-AUDIT-LINE5.
|
|
|
|
IF WS-HASH-OK = 'Y'
|
|
MOVE 'PASS' TO AL-HASH-RES
|
|
ELSE
|
|
MOVE 'FAIL' TO AL-HASH-RES
|
|
END-IF.
|
|
WRITE AUDIT-LINE FROM WS-AUDIT-LINE6.
|
|
|
|
IF WS-CONTROL-OK = 'Y'
|
|
MOVE 'PASS' TO AL-CTRL-RES
|
|
ELSE
|
|
MOVE 'FAIL' TO AL-CTRL-RES
|
|
END-IF.
|
|
WRITE AUDIT-LINE FROM WS-AUDIT-LINE7.
|
|
|
|
*> Write plan utilization summary
|
|
WRITE AUDIT-LINE FROM WS-AUDIT-LINE8.
|
|
IF WS-PC-INDEX > 0
|
|
PERFORM VARYING WS-I FROM 1 BY 1
|
|
UNTIL WS-I > WS-PC-INDEX
|
|
MOVE WS-UTIL-PLAN(WS-I) TO AU-PLAN
|
|
MOVE WS-UTIL-COUNT(WS-I) TO AU-SUBS
|
|
MOVE WS-UTIL-MAX(WS-I) TO AU-CAP
|
|
IF WS-UTIL-MAX(WS-I) > 0
|
|
COMPUTE WS-UR-UTIL-PCT =
|
|
(WS-UTIL-COUNT(WS-I) * 100)
|
|
/ WS-UTIL-MAX(WS-I)
|
|
ELSE
|
|
MOVE 0 TO WS-UR-UTIL-PCT
|
|
END-IF
|
|
MOVE WS-UR-UTIL-PCT TO AU-PCT
|
|
WRITE AUDIT-LINE FROM WS-AUDIT-UTIL
|
|
END-PERFORM
|
|
END-IF.
|
|
|
|
*> Console summary
|
|
DISPLAY '19-matching-MN-to-N: Master=' WS-MASTER-COUNT
|
|
' Detail=' WS-DETAIL-COUNT
|
|
' Output=' WS-OUT-COUNT.
|
|
|
|
WRITE AUDIT-LINE FROM WS-AUDIT-FOOTER.
|
|
|
|
5000-EXIT.
|
|
EXIT.
|
|
|
|
*> ============================================================
|
|
*> 6000-ERROR — Error handler
|
|
*> ============================================================
|
|
6000-ERROR SECTION.
|
|
6000-START.
|
|
|
|
ADD 1 TO WS-ERROR-COUNT.
|
|
MOVE WS-ERROR-COUNT TO ED-NUM.
|
|
MOVE WS-ERROR-MESSAGE TO ED-MESSAGE.
|
|
DISPLAY WS-ERROR-DETAIL.
|
|
|
|
WRITE ERROR-LINE FROM WS-ERROR-DETAIL.
|
|
|
|
6000-ERROR-EXIT.
|
|
EXIT.
|
|
|
|
*> ============================================================
|
|
*> 7000-AUDIT — Trace entry
|
|
*> ============================================================
|
|
7000-AUDIT SECTION.
|
|
7000-START.
|
|
|
|
ACCEPT WS-CURRENT-TIME FROM TIME.
|
|
STRING WS-CURRENT-HOUR ':' WS-CURRENT-MINUTE ':'
|
|
WS-CURRENT-SECOND
|
|
INTO AT-TIMESTAMP.
|
|
MOVE '7000-AUDIT entry' TO AT-MESSAGE.
|
|
WRITE AUDIT-LINE FROM WS-AUDIT-TRACE.
|
|
|
|
7000-EXIT.
|
|
EXIT.
|
|
|
|
*> ============================================================
|
|
*> 9000-EXIT — Cleanup and close
|
|
*> ============================================================
|
|
9000-EXIT SECTION.
|
|
9000-START.
|
|
|
|
DISPLAY '[TRACE] ' WS-PROGRAM-NAME ' 9000-EXIT start'.
|
|
|
|
CLOSE FILE-MASTER FILE-DETAIL FILE-OUT.
|
|
IF FS-MASTER NOT = '00'
|
|
DISPLAY 'WARNING: FILE-MASTER close status=' FS-MASTER
|
|
END-IF.
|
|
IF FS-DETAIL NOT = '00'
|
|
DISPLAY 'WARNING: FILE-DETAIL close status=' FS-DETAIL
|
|
END-IF.
|
|
IF FS-OUT NOT = '00'
|
|
DISPLAY 'WARNING: FILE-OUT close status=' FS-OUT
|
|
END-IF.
|
|
|
|
CLOSE AUDIT-FILE.
|
|
IF FS-AUDIT NOT = '00'
|
|
DISPLAY 'WARNING: AUDIT-FILE close status=' FS-AUDIT
|
|
END-IF.
|
|
|
|
CLOSE ERROR-FILE.
|
|
IF FS-ERROR NOT = '00'
|
|
DISPLAY 'WARNING: ERROR-FILE close status=' FS-ERROR
|
|
END-IF.
|
|
|
|
DISPLAY "19-matching-MN-to-N: PASS".
|
|
IF WS-ERROR-COUNT > 0
|
|
DISPLAY '19-matching-MN-to-N: Errors=' WS-ERROR-COUNT
|
|
' — see error-report-19.txt'
|
|
END-IF.
|
|
|
|
DISPLAY '[TRACE] ' WS-PROGRAM-NAME ' END'.
|
|
STOP RUN.
|
|
|
|
9000-EXIT-EXIT.
|
|
EXIT.
|
|
|
|
END PROGRAM main-19-matching-MN-to-N.
|