94400d50d4
作为子目录纳入系统,与核心测试管道协同 Co-Authored-By: Claude <noreply@anthropic.com>
893 lines
34 KiB
COBOL
893 lines
34 KiB
COBOL
*> ============================================================
|
||
*> 20-matching-MN-to-MxN : CDR详细清单 (CDR Detail M:N→M×N)
|
||
*> Input : FILE-MASTER (master.dat: 合同), FILE-DETAIL (detail.dat: CDR)
|
||
*> Output: FILE-OUT (output.dat: M×N笛卡尔积明细)
|
||
*> Coverage: AM-N005, AM-R001
|
||
*>
|
||
*> EXPANDED: Added SECTION structure, CDR-to-plan mapping validation,
|
||
*> call type against plan allowance, excess usage tracking, detailed
|
||
*> charge line generation, audit file, error file, control totals,
|
||
*> hash totals, tracing, FILE STATUS checks.
|
||
*> ============================================================
|
||
>>SOURCE FORMAT IS FREE
|
||
IDENTIFICATION DIVISION.
|
||
PROGRAM-ID. main-20-matching-MN-to-MxN.
|
||
|
||
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-20.txt"
|
||
ORGANIZATION IS LINE SEQUENTIAL
|
||
FILE STATUS IS FS-AUDIT.
|
||
SELECT ERROR-FILE ASSIGN TO "error-report-20.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
|
||
*> ============================================================
|
||
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).
|
||
|
||
*> ============================================================
|
||
*> TABLE COUNTS
|
||
*> ============================================================
|
||
01 WS-MASTER-COUNT PIC 9(02) VALUE 0.
|
||
01 WS-DETAIL-COUNT PIC 9(02) VALUE 0.
|
||
01 WS-I PIC 9(02).
|
||
01 WS-J PIC 9(02).
|
||
|
||
*> ============================================================
|
||
*> CONTROL TOTALS
|
||
*> ============================================================
|
||
01 WS-CONTROL-TOTALS.
|
||
05 WS-TOTAL-MASTERS PIC 9(09) VALUE 0.
|
||
05 WS-TOTAL-DETAILS PIC 9(09) VALUE 0.
|
||
05 WS-OUT-COUNT PIC 9(09) VALUE 0.
|
||
05 WS-MASTER-GROUPS PIC 9(09) VALUE 0.
|
||
05 WS-DETAIL-GROUPS PIC 9(09) VALUE 0.
|
||
05 WS-UNMATCH-MASTER PIC 9(09) VALUE 0.
|
||
05 WS-UNMATCH-DETAIL 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.
|
||
|
||
*> ============================================================
|
||
*> MASTER TABLE
|
||
*> ============================================================
|
||
01 WS-MASTER-TABLE.
|
||
05 WS-MASTER-ENTRY OCCURS 10 TIMES.
|
||
10 WS-MST-KEY PIC X(10).
|
||
10 WS-MST-DATA1 PIC X(20).
|
||
10 WS-MST-DATA2 PIC 9(10).
|
||
10 WS-MST-DATA3 PIC S9(7)V99 COMP-3.
|
||
|
||
*> ============================================================
|
||
*> DETAIL TABLE
|
||
*> ============================================================
|
||
01 WS-DETAIL-TABLE.
|
||
05 WS-DETAIL-ENTRY OCCURS 10 TIMES.
|
||
10 WS-DTL-KEY PIC X(10).
|
||
10 WS-DTL-DATA1 PIC X(20).
|
||
10 WS-DTL-DATA2 PIC 9(10).
|
||
10 WS-DTL-DATA3 PIC S9(7)V99 COMP-3.
|
||
|
||
*> ============================================================
|
||
*> CDR-TO-PLAN MAPPING VALIDATION
|
||
*> ============================================================
|
||
01 WS-CDR-MAPPING.
|
||
05 WS-CDR-CALL-TYPE PIC X(02).
|
||
88 WS-CDR-VOICE-CALL VALUE 'VO'.
|
||
88 WS-CDR-DATA-CALL VALUE 'DA'.
|
||
88 WS-CDR-MESSAGE-CALL VALUE 'MS'.
|
||
88 WS-CDR-VIDEO-CALL VALUE 'VI'.
|
||
88 WS-CDR-ROAMING-CALL VALUE 'RO'.
|
||
05 WS-CDR-DURATION PIC 9(05).
|
||
05 WS-CDR-DATA-VOLUME PIC 9(09).
|
||
05 WS-CDR-TIMESTAMP PIC X(14).
|
||
05 WS-CDR-STATUS PIC X(01).
|
||
88 WS-CDR-VALID VALUE 'V'.
|
||
88 WS-CDR-INVALID VALUE 'I'.
|
||
88 WS-CDR-PENDING VALUE 'P'.
|
||
|
||
*> ============================================================
|
||
*> PLAN ALLOWANCE FIELDS
|
||
*> ============================================================
|
||
01 WS-PLAN-ALLOWANCE.
|
||
05 WS-PLAN-VOICE-MIN PIC 9(05) VALUE 0.
|
||
05 WS-PLAN-DATA-MB PIC 9(09) VALUE 0.
|
||
05 WS-PLAN-MSG-COUNT PIC 9(05) VALUE 0.
|
||
05 WS-PLAN-PRICE-VOICE PIC 9(05)V99 VALUE 0.
|
||
05 WS-PLAN-PRICE-DATA PIC 9(05)V99 VALUE 0.
|
||
05 WS-PLAN-PRICE-MSG PIC 9(05)V99 VALUE 0.
|
||
05 WS-PLAN-EXCESS-VOICE PIC 9(05)V99 VALUE 0.
|
||
05 WS-PLAN-EXCESS-DATA PIC 9(09)V99 VALUE 0.
|
||
05 WS-PLAN-EXCESS-MSG PIC 9(05)V99 VALUE 0.
|
||
|
||
*> ============================================================
|
||
*> EXCESS USAGE TRACKING
|
||
*> ============================================================
|
||
01 WS-EXCESS-USAGE.
|
||
05 WS-EXCESS-VOICE-MIN PIC 9(05) VALUE 0.
|
||
05 WS-EXCESS-DATA-MB PIC 9(09) VALUE 0.
|
||
05 WS-EXCESS-MSG-COUNT PIC 9(05) VALUE 0.
|
||
05 WS-EXCESS-AMOUNT PIC 9(09)V99 VALUE 0.
|
||
|
||
*> ============================================================
|
||
*> CHARGE LINE GENERATION
|
||
*> ============================================================
|
||
01 WS-CHARGE-LINE.
|
||
05 WS-CL-CONTRACT PIC X(10).
|
||
05 WS-CL-CALL-TYPE PIC X(02).
|
||
05 WS-CL-USAGE PIC 9(09).
|
||
05 WS-CL-UNIT-PRICE PIC 9(05)V99.
|
||
05 WS-CL-LINE-TOTAL PIC 9(09)V99.
|
||
05 WS-CL-EXCESS-FLAG PIC X(01).
|
||
88 WS-CL-WITHIN-ALLOWANCE VALUE 'N'.
|
||
88 WS-CL-EXCESS VALUE 'Y' FALSE 'N'.
|
||
|
||
*> ============================================================
|
||
*> 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(21) VALUE '20-matching-MN-to-MxN'.
|
||
|
||
*> ============================================================
|
||
*> ERROR FIELDS
|
||
*> ============================================================
|
||
01 WS-ERROR-COUNT PIC 9(05) 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(42) VALUE
|
||
'=== 20-matching-MN-to-MxN AUDIT REPORT ==='.
|
||
01 WS-AUDIT-FOOTER.
|
||
05 FILLER PIC X(50) VALUE
|
||
'--- END OF 20-matching-MN-to-MxN AUDIT REPORT ---'.
|
||
01 WS-AUDIT-LINE1.
|
||
05 FILLER PIC X(20) VALUE 'Master Groups: '.
|
||
05 AL-MAST-GP PIC Z(9)9.
|
||
05 FILLER PIC X(16) VALUE ' Detail Groups: '.
|
||
05 AL-DTL-GP PIC Z(9)9.
|
||
05 FILLER PIC X(16) VALUE ' Output: '.
|
||
05 AL-OUT PIC Z(9)9.
|
||
01 WS-AUDIT-LINE2.
|
||
05 FILLER PIC X(20) VALUE 'Total Masters: '.
|
||
05 AL-TOT-MAST PIC Z(9)9.
|
||
05 FILLER PIC X(16) VALUE ' Total Details: '.
|
||
05 AL-TOT-DTL PIC Z(9)9.
|
||
01 WS-AUDIT-LINE3.
|
||
05 FILLER PIC X(20) VALUE 'Hash Master In: '.
|
||
05 AL-HASH-M PIC Z(14)9.
|
||
01 WS-AUDIT-LINE4.
|
||
05 FILLER PIC X(20) VALUE 'Hash Detail In: '.
|
||
05 AL-HASH-D PIC Z(14)9.
|
||
01 WS-AUDIT-LINE5.
|
||
05 FILLER PIC X(20) VALUE 'Hash Output: '.
|
||
05 AL-HASH-O 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(20) VALUE 'Excess Voice: '.
|
||
05 AL-EX-VOICE PIC Z(9)9.
|
||
05 FILLER PIC X(16) VALUE ' Excess Data: '.
|
||
05 AL-EX-DATA PIC Z(9)9.
|
||
05 FILLER PIC X(16) VALUE ' Excess Msg: '.
|
||
05 AL-EX-MSG PIC Z(9)9.
|
||
01 WS-AUDIT-LINE9.
|
||
05 FILLER PIC X(20) VALUE 'Excess Amount: '.
|
||
05 AL-EX-AMT PIC Z(11)9.99.
|
||
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-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-UNMATCH-MASTER-GRP PIC 9(09) VALUE 0.
|
||
01 WS-UNMATCH-DETAIL-GRP PIC 9(09) VALUE 0.
|
||
|
||
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-TOTAL-MASTERS
|
||
MOVE 0 TO WS-TOTAL-DETAILS
|
||
MOVE 0 TO WS-OUT-COUNT
|
||
MOVE 0 TO WS-MASTER-GROUPS
|
||
MOVE 0 TO WS-DETAIL-GROUPS
|
||
MOVE 0 TO WS-UNMATCH-MASTER
|
||
MOVE 0 TO WS-UNMATCH-DETAIL
|
||
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-EXCESS-VOICE-MIN
|
||
MOVE 0 TO WS-EXCESS-DATA-MB
|
||
MOVE 0 TO WS-EXCESS-MSG-COUNT
|
||
MOVE 0 TO WS-EXCESS-AMOUNT
|
||
MOVE 'Y' TO WS-CONTROL-OK
|
||
MOVE 'Y' TO WS-HASH-OK
|
||
MOVE 0 TO WS-UNMATCH-MASTER-GRP
|
||
MOVE 0 TO WS-UNMATCH-DETAIL-GRP
|
||
|
||
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-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-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-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
|
||
*> ============================================================
|
||
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 — output='
|
||
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-EXIT
|
||
END-IF.
|
||
|
||
IF NOT EOF-MASTER
|
||
ADD 1 TO WS-TOTAL-MASTERS
|
||
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-EXIT
|
||
END-IF.
|
||
|
||
IF NOT EOF-DETAIL
|
||
ADD 1 TO WS-TOTAL-DETAILS
|
||
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: Cartesian product + validation
|
||
*> ============================================================
|
||
3300-PROCESS-MATCH SECTION.
|
||
3300-START.
|
||
|
||
DISPLAY '[TRACE] MATCH group key=' WS-MASTER-KEY.
|
||
MOVE WS-MASTER-KEY TO WS-KEY-HOLD.
|
||
ADD 1 TO WS-MASTER-GROUPS.
|
||
|
||
*> Load all master records for this key
|
||
MOVE 0 TO WS-MASTER-COUNT.
|
||
PERFORM UNTIL EOF-MASTER
|
||
OR WS-MASTER-KEY NOT = WS-KEY-HOLD
|
||
ADD 1 TO WS-MASTER-COUNT
|
||
MOVE MASTER-REC TO WS-MASTER-ENTRY(WS-MASTER-COUNT)
|
||
PERFORM 3100-READ-MASTER
|
||
THRU 3100-READ-MASTER-EXIT
|
||
END-PERFORM.
|
||
|
||
DISPLAY '[TRACE] Masters loaded=' WS-MASTER-COUNT.
|
||
|
||
*> Load all detail records for this key
|
||
MOVE 0 TO WS-DETAIL-COUNT.
|
||
PERFORM UNTIL EOF-DETAIL
|
||
OR WS-DETAIL-KEY NOT = WS-KEY-HOLD
|
||
ADD 1 TO WS-DETAIL-COUNT
|
||
MOVE DETAIL-REC TO WS-DETAIL-ENTRY(WS-DETAIL-COUNT)
|
||
PERFORM 3200-READ-DETAIL
|
||
THRU 3200-READ-DETAIL-EXIT
|
||
END-PERFORM.
|
||
|
||
ADD 1 TO WS-DETAIL-GROUPS.
|
||
DISPLAY '[TRACE] Details loaded=' WS-DETAIL-COUNT.
|
||
|
||
*> For each master × detail, validate CDR and generate charge line
|
||
PERFORM VARYING WS-I FROM 1 BY 1
|
||
UNTIL WS-I > WS-MASTER-COUNT
|
||
PERFORM VARYING WS-J FROM 1 BY 1
|
||
UNTIL WS-J > WS-DETAIL-COUNT
|
||
|
||
*> Validate CDR-to-plan mapping
|
||
PERFORM 3400-VALIDATE-CDR
|
||
THRU 3400-VALIDATE-CDR-EXIT
|
||
PERFORM 3500-CHECK-ALLOWANCE
|
||
THRU 3500-CHECK-ALLOWANCE-EXIT
|
||
|
||
*> Generate charge line with excess tracking
|
||
PERFORM 3510-GENERATE-CHARGE
|
||
THRU 3510-GENERATE-CHARGE-EXIT
|
||
|
||
*> Write the output record
|
||
MOVE WS-DETAIL-ENTRY(WS-J) 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-EXIT
|
||
END-IF
|
||
ADD 1 TO WS-OUT-COUNT
|
||
MOVE WS-DTL-DATA2(WS-J)
|
||
TO WS-AMOUNT-OUT
|
||
ADD WS-AMOUNT-OUT TO WS-HASH-OUT
|
||
END-PERFORM
|
||
END-PERFORM.
|
||
|
||
3300-PROCESS-MATCH-EXIT.
|
||
EXIT.
|
||
|
||
*> ============================================================
|
||
*> 3400-VALIDATE-CDR — Validate CDR record fields
|
||
*> ============================================================
|
||
3400-VALIDATE-CDR SECTION.
|
||
3400-START.
|
||
|
||
*> Extract CDR call type from detail DATA1
|
||
MOVE WS-DTL-DATA1(WS-J)(1:2) TO WS-CDR-CALL-TYPE.
|
||
MOVE WS-DTL-DATA1(WS-J)(3:5) TO WS-CDR-DURATION.
|
||
MOVE WS-DTL-DATA1(WS-J)(8:9) TO WS-CDR-DATA-VOLUME.
|
||
MOVE WS-DTL-DATA1(WS-J)(17:1) TO WS-CDR-STATUS.
|
||
|
||
DISPLAY '[TRACE] CDR type=' WS-CDR-CALL-TYPE
|
||
' dur=' WS-CDR-DURATION
|
||
' vol=' WS-CDR-DATA-VOLUME
|
||
' status=' WS-CDR-STATUS.
|
||
|
||
*> Validate CDR status
|
||
IF WS-CDR-INVALID
|
||
DISPLAY '[TRACE] CDR INVALID — marking'
|
||
ADD 1 TO WS-ERROR-COUNT
|
||
END-IF.
|
||
|
||
*> Determine call type and set default allowances
|
||
MOVE 500 TO WS-PLAN-VOICE-MIN
|
||
MOVE 1024 TO WS-PLAN-DATA-MB
|
||
MOVE 1000 TO WS-PLAN-MSG-COUNT
|
||
MOVE 0.05 TO WS-PLAN-PRICE-VOICE
|
||
MOVE 0.01 TO WS-PLAN-PRICE-DATA
|
||
MOVE 0.02 TO WS-PLAN-PRICE-MSG
|
||
MOVE 0.10 TO WS-PLAN-EXCESS-VOICE
|
||
MOVE 0.05 TO WS-PLAN-EXCESS-DATA
|
||
MOVE 0.05 TO WS-PLAN-EXCESS-MSG.
|
||
|
||
DISPLAY '[TRACE] Allowances: voice=' WS-PLAN-VOICE-MIN
|
||
' data=' WS-PLAN-DATA-MB
|
||
' msg=' WS-PLAN-MSG-COUNT.
|
||
|
||
3400-VALIDATE-CDR-EXIT.
|
||
EXIT.
|
||
|
||
*> ============================================================
|
||
*> 3500-CHECK-ALLOWANCE — Check CDR usage against plan allowance
|
||
*> ============================================================
|
||
3500-CHECK-ALLOWANCE SECTION.
|
||
3500-START.
|
||
|
||
EVALUATE TRUE
|
||
WHEN WS-CDR-VOICE-CALL
|
||
IF WS-CDR-DURATION > WS-PLAN-VOICE-MIN
|
||
COMPUTE WS-EXCESS-VOICE-MIN =
|
||
WS-CDR-DURATION - WS-PLAN-VOICE-MIN
|
||
COMPUTE WS-EXCESS-AMOUNT =
|
||
WS-EXCESS-AMOUNT +
|
||
(WS-EXCESS-VOICE-MIN * WS-PLAN-EXCESS-VOICE)
|
||
DISPLAY '[TRACE] VOICE EXCESS: '
|
||
WS-EXCESS-VOICE-MIN ' min'
|
||
END-IF
|
||
|
||
WHEN WS-CDR-DATA-CALL
|
||
IF WS-CDR-DATA-VOLUME > WS-PLAN-DATA-MB
|
||
COMPUTE WS-EXCESS-DATA-MB =
|
||
WS-CDR-DATA-VOLUME - WS-PLAN-DATA-MB
|
||
COMPUTE WS-EXCESS-AMOUNT =
|
||
WS-EXCESS-AMOUNT +
|
||
(WS-EXCESS-DATA-MB * WS-PLAN-EXCESS-DATA)
|
||
DISPLAY '[TRACE] DATA EXCESS: '
|
||
WS-EXCESS-DATA-MB ' MB'
|
||
END-IF
|
||
|
||
WHEN WS-CDR-MESSAGE-CALL
|
||
IF WS-CDR-DURATION > WS-PLAN-MSG-COUNT
|
||
COMPUTE WS-EXCESS-MSG-COUNT =
|
||
WS-CDR-DURATION - WS-PLAN-MSG-COUNT
|
||
COMPUTE WS-EXCESS-AMOUNT =
|
||
WS-EXCESS-AMOUNT +
|
||
(WS-EXCESS-MSG-COUNT * WS-PLAN-EXCESS-MSG)
|
||
DISPLAY '[TRACE] MSG EXCESS: '
|
||
WS-EXCESS-MSG-COUNT ' msgs'
|
||
END-IF
|
||
|
||
WHEN WS-CDR-VIDEO-CALL
|
||
DISPLAY '[TRACE] VIDEO call — special pricing'
|
||
IF WS-CDR-DURATION > 100
|
||
COMPUTE WS-EXCESS-VOICE-MIN =
|
||
WS-CDR-DURATION - 100
|
||
COMPUTE WS-EXCESS-AMOUNT =
|
||
WS-EXCESS-AMOUNT +
|
||
(WS-EXCESS-VOICE-MIN * 0.15)
|
||
END-IF
|
||
|
||
WHEN WS-CDR-ROAMING-CALL
|
||
DISPLAY '[TRACE] ROAMING call — premium rate'
|
||
COMPUTE WS-EXCESS-AMOUNT =
|
||
WS-EXCESS-AMOUNT +
|
||
(WS-CDR-DURATION * 0.25)
|
||
|
||
WHEN OTHER
|
||
DISPLAY '[TRACE] Unknown call type no allowance'
|
||
ADD 1 TO WS-ERROR-COUNT
|
||
END-EVALUATE.
|
||
|
||
3500-CHECK-ALLOWANCE-EXIT.
|
||
EXIT.
|
||
|
||
*> ============================================================
|
||
*> 3510-GENERATE-CHARGE — Build charge line entry
|
||
*> ============================================================
|
||
3510-GENERATE-CHARGE SECTION.
|
||
3510-START.
|
||
|
||
*> Build a charge line record for audit/reporting
|
||
MOVE WS-MST-KEY(WS-I) TO WS-CL-CONTRACT.
|
||
MOVE WS-CDR-CALL-TYPE TO WS-CL-CALL-TYPE.
|
||
|
||
EVALUATE TRUE
|
||
WHEN WS-CDR-VOICE-CALL
|
||
MOVE WS-CDR-DURATION TO WS-CL-USAGE
|
||
MOVE WS-PLAN-PRICE-VOICE TO WS-CL-UNIT-PRICE
|
||
WHEN WS-CDR-DATA-CALL
|
||
MOVE WS-CDR-DATA-VOLUME TO WS-CL-USAGE
|
||
MOVE WS-PLAN-PRICE-DATA TO WS-CL-UNIT-PRICE
|
||
WHEN WS-CDR-MESSAGE-CALL
|
||
MOVE WS-CDR-DURATION TO WS-CL-USAGE
|
||
MOVE WS-PLAN-PRICE-MSG TO WS-CL-UNIT-PRICE
|
||
WHEN OTHER
|
||
MOVE 0 TO WS-CL-USAGE
|
||
MOVE 0 TO WS-CL-UNIT-PRICE
|
||
END-EVALUATE.
|
||
|
||
COMPUTE WS-CL-LINE-TOTAL =
|
||
WS-CL-USAGE * WS-CL-UNIT-PRICE.
|
||
|
||
DISPLAY '[TRACE] CHARGE: contract=' WS-CL-CONTRACT
|
||
' type=' WS-CL-CALL-TYPE
|
||
' usage=' WS-CL-USAGE
|
||
' total=' WS-CL-LINE-TOTAL.
|
||
|
||
3510-GENERATE-CHARGE-EXIT.
|
||
EXIT.
|
||
|
||
*> ============================================================
|
||
*> 3610-SKIP-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.
|
||
ADD 1 TO WS-UNMATCH-DETAIL-GRP.
|
||
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
|
||
*> ============================================================
|
||
3620-SKIP-MASTER-GROUP SECTION.
|
||
3620-START.
|
||
|
||
DISPLAY '[TRACE] SKIP-MASTER-GROUP key=' WS-MASTER-KEY.
|
||
MOVE WS-MASTER-KEY TO WS-KEY-HOLD.
|
||
ADD 1 TO WS-UNMATCH-MASTER-GRP.
|
||
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 — Control and hash validation
|
||
*> ============================================================
|
||
4000-VALIDATE SECTION.
|
||
4000-START.
|
||
|
||
DISPLAY '[TRACE] ' WS-PROGRAM-NAME ' 4000-VALIDATE start'.
|
||
|
||
*> Expected output = total-masters * total-details (groups only)
|
||
COMPUTE WS-AMOUNT-OUT =
|
||
WS-TOTAL-MASTERS * WS-TOTAL-DETAILS
|
||
IF WS-OUT-COUNT NOT =
|
||
WS-AMOUNT-OUT
|
||
MOVE 'N' TO WS-CONTROL-OK
|
||
MOVE 'Control FAIL: output count mismatch'
|
||
TO WS-ERROR-MESSAGE
|
||
PERFORM 6000-ERROR THRU 6000-EXIT
|
||
DISPLAY 'CONTROL FAIL: out=' WS-OUT-COUNT
|
||
' expected masters*total: '
|
||
WS-TOTAL-MASTERS ' * ' WS-TOTAL-DETAILS
|
||
' = ' WS-AMOUNT-OUT
|
||
ELSE
|
||
DISPLAY 'CONTROL OK: output=' WS-OUT-COUNT
|
||
' = masters*details'
|
||
END-IF.
|
||
|
||
*> Hash check
|
||
IF WS-HASH-MASTER-IN NOT =
|
||
WS-HASH-DETAIL-IN
|
||
MOVE 'N' TO WS-HASH-OK
|
||
MOVE 'Hash FAIL: master/detail mismatch'
|
||
TO WS-ERROR-MESSAGE
|
||
PERFORM 6000-ERROR THRU 6000-EXIT
|
||
DISPLAY 'HASH FAIL: master=' WS-HASH-MASTER-IN
|
||
' detail=' WS-HASH-DETAIL-IN
|
||
ELSE
|
||
DISPLAY 'HASH OK: master/detail balanced'
|
||
END-IF.
|
||
|
||
DISPLAY '[TRACE] ' WS-PROGRAM-NAME
|
||
' 4000-VALIDATE complete'.
|
||
|
||
4000-EXIT.
|
||
EXIT.
|
||
|
||
*> ============================================================
|
||
*> 5000-REPORT — Audit report generation
|
||
*> ============================================================
|
||
5000-REPORT SECTION.
|
||
5000-START.
|
||
|
||
DISPLAY '[TRACE] ' WS-PROGRAM-NAME ' 5000-REPORT start'.
|
||
|
||
MOVE WS-MASTER-GROUPS TO AL-MAST-GP.
|
||
MOVE WS-DETAIL-GROUPS TO AL-DTL-GP.
|
||
MOVE WS-OUT-COUNT TO AL-OUT.
|
||
WRITE AUDIT-LINE FROM WS-AUDIT-LINE1.
|
||
|
||
MOVE WS-TOTAL-MASTERS TO AL-TOT-MAST.
|
||
MOVE WS-TOTAL-DETAILS TO AL-TOT-DTL.
|
||
WRITE AUDIT-LINE FROM WS-AUDIT-LINE2.
|
||
|
||
MOVE WS-HASH-MASTER-IN TO AL-HASH-M.
|
||
WRITE AUDIT-LINE FROM WS-AUDIT-LINE3.
|
||
|
||
MOVE WS-HASH-DETAIL-IN TO AL-HASH-D.
|
||
WRITE AUDIT-LINE FROM WS-AUDIT-LINE4.
|
||
|
||
MOVE WS-HASH-OUT TO AL-HASH-O.
|
||
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.
|
||
|
||
MOVE WS-EXCESS-VOICE-MIN TO AL-EX-VOICE.
|
||
MOVE WS-EXCESS-DATA-MB TO AL-EX-DATA.
|
||
MOVE WS-EXCESS-MSG-COUNT TO AL-EX-MSG.
|
||
WRITE AUDIT-LINE FROM WS-AUDIT-LINE8.
|
||
|
||
MOVE WS-EXCESS-AMOUNT TO AL-EX-AMT.
|
||
WRITE AUDIT-LINE FROM WS-AUDIT-LINE9.
|
||
|
||
*> Console summary
|
||
DISPLAY '20-matching-MN-to-MxN: Masters=' WS-TOTAL-MASTERS
|
||
' Details=' WS-TOTAL-DETAILS
|
||
' Output=' WS-OUT-COUNT
|
||
' ExcessAmt=' WS-EXCESS-AMOUNT.
|
||
|
||
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-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 "20-matching-MN-to-MxN: PASS".
|
||
IF WS-ERROR-COUNT > 0
|
||
DISPLAY '20-matching-MN-to-MxN: Errors=' WS-ERROR-COUNT
|
||
' — see error-report-20.txt'
|
||
END-IF.
|
||
|
||
DISPLAY '[TRACE] ' WS-PROGRAM-NAME ' END'.
|
||
STOP RUN.
|
||
|
||
9000-EXIT-EXIT.
|
||
EXIT.
|
||
|
||
END PROGRAM main-20-matching-MN-to-MxN.
|