feat: add benchmark-programs — 58 telecom COBOL test programs

作为子目录纳入系统,与核心测试管道协同

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
NB-076
2026-06-25 09:53:21 +08:00
parent 50f9f0f52f
commit 94400d50d4
278 changed files with 44125 additions and 0 deletions
@@ -0,0 +1 @@
0000000000
@@ -0,0 +1,33 @@
# 06-branch-evaluate — EVALUATE Branch Program
## 电信业务场景
套餐类型判定。根据套餐代码(P01/P02/P03)进行EVALUATE分支,按套餐类型分流处理。
Demonstrates GnuCOBOL EVALUATE patterns:
- **EVALUATE with ALSO**: Two-condition EVALUATE on KEY and DATA2
- **EVALUATE TRUE/FALSE**: Evaluate boolean conditions
- **EVALUATE multi-value WHEN**: Multiple WHEN values for same action
- **WHEN OTHER**: Default/catch-all branch
## Files
| File | Purpose |
|------|---------|
| `main-06-branch-evaluate.cbl` | COBOL program (fixed format) |
| `data-gen.sh` | Generate test data |
| `run.sh` | Compile, run, verify outputs |
## Input Record
Same as 05-branch-if: KEY(10) + DATA1(20) + DATA2(10)
## Branch Logic
| KEY Value | Output File |
|-----------|-------------|
| 'A' | FILE-A.DAT |
| 'B' | FILE-B.DAT |
| 'C' | FILE-C.DAT |
| any other | FILE-OTHER.DAT |
@@ -0,0 +1,961 @@
*> ============================================================
*> main-06-branch-evaluate.cbl : 套餐类型判定 (EVALUATE Plan)
*> Input : plan-record (套餐代码记录)
*> Output: FILE-A (套餐P01: 基本套餐)
*> FILE-B (套餐P02: 商务套餐)
*> FILE-C (套餐P03: 无限套餐)
*> FILE-D (套餐P04: 家庭套餐)
*> FILE-E (套餐P05: 学生套餐)
*> FILE-F (套餐P06: 老人套餐)
*> FILE-G (套餐P07: 企业套餐)
*> FILE-OTHER (未定义套餐 → 异常处理)
*> Coverage: B-N006~N009, B-A002, B-R001
*> ============================================================
IDENTIFICATION DIVISION.
PROGRAM-ID. BranchEval.
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT FILE-IN
ASSIGN TO "FILE-IN.DAT"
ORGANIZATION IS LINE SEQUENTIAL
FILE STATUS IS FS-IN.
SELECT FILE-A
ASSIGN TO "FILE-A.DAT"
ORGANIZATION IS LINE SEQUENTIAL
FILE STATUS IS FS-A.
SELECT FILE-B
ASSIGN TO "FILE-B.DAT"
ORGANIZATION IS LINE SEQUENTIAL
FILE STATUS IS FS-B.
SELECT FILE-C
ASSIGN TO "FILE-C.DAT"
ORGANIZATION IS LINE SEQUENTIAL
FILE STATUS IS FS-C.
SELECT FILE-D
ASSIGN TO "FILE-D.DAT"
ORGANIZATION IS LINE SEQUENTIAL
FILE STATUS IS FS-D.
SELECT FILE-E
ASSIGN TO "FILE-E.DAT"
ORGANIZATION IS LINE SEQUENTIAL
FILE STATUS IS FS-E.
SELECT FILE-F
ASSIGN TO "FILE-F.DAT"
ORGANIZATION IS LINE SEQUENTIAL
FILE STATUS IS FS-F.
SELECT FILE-G
ASSIGN TO "FILE-G.DAT"
ORGANIZATION IS LINE SEQUENTIAL
FILE STATUS IS FS-G.
SELECT FILE-OTHER
ASSIGN TO "FILE-OTHER.DAT"
ORGANIZATION IS LINE SEQUENTIAL
FILE STATUS IS FS-OTHER.
SELECT FILE-AUDIT
ASSIGN TO "audit-report.txt"
ORGANIZATION IS LINE SEQUENTIAL
FILE STATUS IS FS-AUDIT.
DATA DIVISION.
FILE SECTION.
FD FILE-IN.
01 FILE-IN-REC.
05 IN-KEY PIC X(10).
05 IN-DATA1 PIC X(20).
05 IN-DATA2 PIC 9(10).
FD FILE-A.
01 FILE-A-REC.
05 A-KEY PIC X(10).
05 FILLER PIC X VALUE SPACE.
05 A-DATA1 PIC X(20).
05 FILLER PIC X VALUE SPACE.
05 A-DATA2 PIC 9(10).
FD FILE-B.
01 FILE-B-REC.
05 B-KEY PIC X(10).
05 FILLER PIC X VALUE SPACE.
05 B-DATA1 PIC X(20).
05 FILLER PIC X VALUE SPACE.
05 B-DATA2 PIC 9(10).
FD FILE-C.
01 FILE-C-REC.
05 C-KEY PIC X(10).
05 FILLER PIC X VALUE SPACE.
05 C-DATA1 PIC X(20).
05 FILLER PIC X VALUE SPACE.
05 C-DATA2 PIC 9(10).
FD FILE-D.
01 FILE-D-REC.
05 D-KEY PIC X(10).
05 FILLER PIC X VALUE SPACE.
05 D-DATA1 PIC X(20).
05 FILLER PIC X VALUE SPACE.
05 D-DATA2 PIC 9(10).
FD FILE-E.
01 FILE-E-REC.
05 E-KEY PIC X(10).
05 FILLER PIC X VALUE SPACE.
05 E-DATA1 PIC X(20).
05 FILLER PIC X VALUE SPACE.
05 E-DATA2 PIC 9(10).
FD FILE-F.
01 FILE-F-REC.
05 F-KEY PIC X(10).
05 FILLER PIC X VALUE SPACE.
05 F-DATA1 PIC X(20).
05 FILLER PIC X VALUE SPACE.
05 F-DATA2 PIC 9(10).
FD FILE-G.
01 FILE-G-REC.
05 G-KEY PIC X(10).
05 FILLER PIC X VALUE SPACE.
05 G-DATA1 PIC X(20).
05 FILLER PIC X VALUE SPACE.
05 G-DATA2 PIC 9(10).
FD FILE-OTHER.
01 FILE-OTHER-REC.
05 O-KEY PIC X(10).
05 FILLER PIC X VALUE SPACE.
05 O-DATA1 PIC X(20).
05 FILLER PIC X VALUE SPACE.
05 O-DATA2 PIC 9(10).
FD FILE-AUDIT.
01 FILE-AUDIT-REC PIC X(80).
WORKING-STORAGE SECTION.
01 WS-TELECOM-REC.
COPY "telecom/TEL-BILLING.cpy".
*> File status fields
01 FS-IN PIC X(2).
01 FS-A PIC X(2).
01 FS-B PIC X(2).
01 FS-C PIC X(2).
01 FS-D PIC X(2).
01 FS-E PIC X(2).
01 FS-F PIC X(2).
01 FS-G PIC X(2).
01 FS-OTHER PIC X(2).
01 FS-AUDIT PIC X(2).
*> 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'.
*> Counters per tier
01 WS-COUNTERS.
05 WS-COUNT-A PIC 9(5) VALUE 0.
05 WS-COUNT-B PIC 9(5) VALUE 0.
05 WS-COUNT-C PIC 9(5) VALUE 0.
05 WS-COUNT-D PIC 9(5) VALUE 0.
05 WS-COUNT-E PIC 9(5) VALUE 0.
05 WS-COUNT-F PIC 9(5) VALUE 0.
05 WS-COUNT-G PIC 9(5) VALUE 0.
05 WS-COUNT-OTHER PIC 9(5) VALUE 0.
*> Hash totals
01 WS-HASH-TOTALS.
05 WS-HASH-IN PIC 9(12) VALUE 0.
05 WS-HASH-OUT-A PIC 9(12) VALUE 0.
05 WS-HASH-OUT-B PIC 9(12) VALUE 0.
05 WS-HASH-OUT-C PIC 9(12) VALUE 0.
05 WS-HASH-OUT-D PIC 9(12) VALUE 0.
05 WS-HASH-OUT-E PIC 9(12) VALUE 0.
05 WS-HASH-OUT-F PIC 9(12) VALUE 0.
05 WS-HASH-OUT-G PIC 9(12) VALUE 0.
05 WS-HASH-OUT-OTHER PIC 9(12) VALUE 0.
05 WS-HASH-VERIFIED PIC X(3) VALUE 'NO '.
88 WS-HASH-OK VALUE 'YES'.
*> Batch totals
01 WS-BATCH-TOTALS.
05 WS-RECORDS-READ PIC 9(5) VALUE 0.
05 WS-RECORDS-WRITTEN PIC 9(5) VALUE 0.
05 WS-ERROR-COUNT PIC 9(5) VALUE 0.
05 WS-WARN-COUNT PIC 9(5) VALUE 0.
05 WS-BATCH-DATE PIC 9(8).
05 WS-BATCH-TIME PIC 9(8).
05 WS-BATCH-TOTAL-AMT PIC 9(15) VALUE 0.
05 WS-HASH-TOTAL PIC 9(15) VALUE 0.
*> Timestamp fields
01 WS-DATE-TIME.
05 WS-DATE PIC X(10).
05 WS-TIME PIC X(10).
01 WS-TIMESTAMP PIC X(20).
01 WS-DATA2-NUM PIC 9(10).
01 WS-TRUE-FALSE PIC X.
88 WS-IS-TRUE VALUE 'Y' FALSE 'N'.
*> Telecom business rule fields
01 WS-PLAN-RULES.
05 WS-CALL-TYPE PIC X(10).
05 WS-DESTINATION PIC X(10).
05 WS-DURATION-CAT PIC X(10).
05 WS-DATA-CAP PIC 9(6).
05 WS-INTL-RATE PIC 9(3)V99.
05 WS-PLAN-NAME PIC X(10).
05 WS-PLAN-RATE PIC 9(5)V99.
05 WS-PEAK-FLAG PIC X.
88 WS-PEAK VALUE 'P'.
88 WS-OFF-PEAK VALUE 'O'.
05 WS-DAY-TYPE PIC X.
88 WS-WEEKDAY VALUE 'W'.
88 WS-WEEKEND VALUE 'E'.
05 WS-DOM-ROAM PIC X.
88 WS-DOMESTIC VALUE 'D'.
88 WS-ROAMING VALUE 'R'.
05 WS-MIN-CHARGE PIC 9(5)V99 VALUE 5.00.
05 WS-CAP-AMOUNT PIC 9(9)V99 VALUE 99999.99.
05 WS-FALLBACK-RATE PIC 9(5)V99 VALUE 2.00.
05 WS-PLAN-CODE PIC X(03).
*> Audit fields
01 WS-AUDIT-LINE.
05 AU-TIMESTAMP PIC X(20).
05 FILLER PIC X VALUE SPACE.
05 AU-TIER PIC X(10).
05 FILLER PIC X VALUE SPACE.
05 AU-KEY PIC X(10).
05 FILLER PIC X VALUE SPACE.
05 AU-AMOUNT PIC Z(9)9.
05 FILLER PIC X VALUE SPACE.
05 AU-STATUS PIC X(15).
*> Error fields
01 WS-SEVERITY PIC X(10).
01 WS-ERROR-MSG PIC X(60).
PROCEDURE DIVISION.
*
1000-INIT-SECTION.
*
1000-INIT.
MOVE FUNCTION CURRENT-DATE (1:10) TO WS-DATE
MOVE FUNCTION CURRENT-DATE (12:8) TO WS-TIME
MOVE FUNCTION CURRENT-DATE (1:8) TO WS-BATCH-DATE
MOVE FUNCTION CURRENT-DATE (12:8) TO WS-BATCH-TIME
STRING WS-DATE ' ' WS-TIME INTO WS-TIMESTAMP
DISPLAY '[' WS-TIMESTAMP '] BranchEval STARTED'
DISPLAY ' '
PERFORM 2000-OPEN-FILES-SECTION
PERFORM 5000-AUDIT-SECTION
THRU AUDIT-LOG-START
.
*
2000-OPEN-FILES-SECTION.
*
2000-OPEN-FILES.
OPEN INPUT FILE-IN
IF FS-IN NOT = '00'
MOVE 'FATAL' TO WS-SEVERITY
STRING 'Open FILE-IN failed FS=' FS-IN
INTO WS-ERROR-MSG
PERFORM 6000-ERROR-HANDLE-SECTION
STOP RUN
END-IF
OPEN OUTPUT FILE-A FILE-B FILE-C
FILE-D FILE-E FILE-F
FILE-G FILE-OTHER
IF FS-A NOT = '00' OR FS-B NOT = '00'
OR FS-C NOT = '00' OR FS-D NOT = '00'
OR FS-E NOT = '00' OR FS-F NOT = '00'
OR FS-G NOT = '00' OR FS-OTHER NOT = '00'
MOVE 'FATAL' TO WS-SEVERITY
STRING 'Open output files failed'
INTO WS-ERROR-MSG
PERFORM 6000-ERROR-HANDLE-SECTION
STOP RUN
END-IF
OPEN OUTPUT FILE-AUDIT
IF FS-AUDIT NOT = '00'
DISPLAY 'WARNING: Audit file open failed FS='
FS-AUDIT
END-IF
DISPLAY 'Files opened successfully'
.
*
3000-PROCESS-SECTION.
*
3000-PROCESS.
DISPLAY 'Processing records with EVALUATE...'
PERFORM UNTIL WS-EOF
PERFORM 3100-READ-INPUT-SECTION
IF NOT WS-EOF
PERFORM 3200-VALIDATE-SECTION
PERFORM 3300-APPLY-RULES-SECTION
END-IF
END-PERFORM
.
*
3100-READ-INPUT-SECTION.
*
3100-READ-INPUT.
READ FILE-IN INTO FILE-IN-REC
AT END SET WS-EOF TO TRUE
NOT AT END
ADD 1 TO WS-RECORDS-READ
ADD WS-DATA2-NUM TO WS-HASH-IN
IF FS-IN NOT = '00'
MOVE 'ERROR' TO WS-SEVERITY
STRING 'Read FILE-IN FS=' FS-IN
INTO WS-ERROR-MSG
PERFORM 6000-ERROR-HANDLE-SECTION
END-IF
END-READ
.
*
3200-VALIDATE-SECTION.
*
3200-VALIDATE.
MOVE IN-DATA2 TO WS-DATA2-NUM
*> Plan code validation
IF IN-KEY = SPACES OR IN-KEY = LOW-VALUES
MOVE 'WARNING' TO WS-SEVERITY
STRING 'Empty plan code detected'
INTO WS-ERROR-MSG
PERFORM 6000-ERROR-HANDLE-SECTION
END-IF
*> Duration range validation
IF WS-DATA2-NUM = 0
MOVE 'WARNING' TO WS-SEVERITY
STRING 'Zero duration: ' IN-KEY
INTO WS-ERROR-MSG
PERFORM 6000-ERROR-HANDLE-SECTION
END-IF
*> Set call type and destination from DATA1
EVALUATE IN-DATA1 (1:4)
WHEN 'PEAK'
MOVE 'PEAK' TO WS-CALL-TYPE
MOVE 'DOM' TO WS-DESTINATION
WHEN 'OFFP'
MOVE 'OFF-PEAK' TO WS-CALL-TYPE
MOVE 'DOM' TO WS-DESTINATION
WHEN 'ROAM'
MOVE 'PEAK' TO WS-CALL-TYPE
MOVE 'INTL' TO WS-DESTINATION
WHEN 'WKND'
MOVE 'OFF-PEAK' TO WS-CALL-TYPE
MOVE 'DOM' TO WS-DESTINATION
WHEN OTHER
MOVE 'STANDARD' TO WS-CALL-TYPE
MOVE 'DOM' TO WS-DESTINATION
END-EVALUATE
*> Duration category
EVALUATE TRUE
WHEN WS-DATA2-NUM <= 60
MOVE 'SHORT' TO WS-DURATION-CAT
WHEN WS-DATA2-NUM <= 300
MOVE 'MEDIUM' TO WS-DURATION-CAT
WHEN WS-DATA2-NUM <= 1800
MOVE 'LONG' TO WS-DURATION-CAT
WHEN OTHER
MOVE 'EXTENDED' TO WS-DURATION-CAT
END-EVALUATE
.
*
3300-APPLY-RULES-SECTION.
*
3300-APPLY-RULES.
*> ============================================================
*> ORIGINAL EVALUATE with ALSO — 3-way preserved
*> Expanded to 8-way: A, B, C, D, E, F, G, OTHER
*> ============================================================
EVALUATE IN-KEY ALSO WS-DATA2-NUM
WHEN 'A' ALSO ANY
MOVE IN-KEY TO A-KEY
MOVE IN-DATA1 TO A-DATA1
MOVE IN-DATA2 TO A-DATA2
WRITE FILE-A-REC
IF FS-A NOT = '00'
MOVE 'FATAL' TO WS-SEVERITY
STRING 'Write FILE-A FS=' FS-A
INTO WS-ERROR-MSG
PERFORM 6000-ERROR-HANDLE-SECTION
END-IF
ADD 1 TO WS-COUNT-A
ADD WS-DATA2-NUM TO WS-HASH-OUT-A
ADD 1 TO WS-RECORDS-WRITTEN
DISPLAY ' -> Key=''A'' routed to FILE-A'
MOVE 'BASIC-P01' TO WS-PLAN-NAME
WHEN 'B' ALSO ANY
MOVE IN-KEY TO B-KEY
MOVE IN-DATA1 TO B-DATA1
MOVE IN-DATA2 TO B-DATA2
WRITE FILE-B-REC
IF FS-B NOT = '00'
MOVE 'FATAL' TO WS-SEVERITY
STRING 'Write FILE-B FS=' FS-B
INTO WS-ERROR-MSG
PERFORM 6000-ERROR-HANDLE-SECTION
END-IF
ADD 1 TO WS-COUNT-B
ADD WS-DATA2-NUM TO WS-HASH-OUT-B
ADD 1 TO WS-RECORDS-WRITTEN
DISPLAY ' -> Key=''B'' routed to FILE-B'
MOVE 'BUSINESS-P02' TO WS-PLAN-NAME
WHEN 'C' ALSO ANY
MOVE IN-KEY TO C-KEY
MOVE IN-DATA1 TO C-DATA1
MOVE IN-DATA2 TO C-DATA2
WRITE FILE-C-REC
IF FS-C NOT = '00'
MOVE 'FATAL' TO WS-SEVERITY
STRING 'Write FILE-C FS=' FS-C
INTO WS-ERROR-MSG
PERFORM 6000-ERROR-HANDLE-SECTION
END-IF
ADD 1 TO WS-COUNT-C
ADD WS-DATA2-NUM TO WS-HASH-OUT-C
ADD 1 TO WS-RECORDS-WRITTEN
DISPLAY ' -> Key=''C'' routed to FILE-C'
MOVE 'UNLIMITED-P03' TO WS-PLAN-NAME
WHEN 'D' ALSO ANY
MOVE IN-KEY TO D-KEY
MOVE IN-DATA1 TO D-DATA1
MOVE IN-DATA2 TO D-DATA2
WRITE FILE-D-REC
IF FS-D NOT = '00'
MOVE 'FATAL' TO WS-SEVERITY
STRING 'Write FILE-D FS=' FS-D
INTO WS-ERROR-MSG
PERFORM 6000-ERROR-HANDLE-SECTION
END-IF
ADD 1 TO WS-COUNT-D
ADD WS-DATA2-NUM TO WS-HASH-OUT-D
ADD 1 TO WS-RECORDS-WRITTEN
DISPLAY ' -> Key=''D'' routed to FILE-D'
MOVE 'FAMILY-P04' TO WS-PLAN-NAME
WHEN 'E' ALSO ANY
MOVE IN-KEY TO E-KEY
MOVE IN-DATA1 TO E-DATA1
MOVE IN-DATA2 TO E-DATA2
WRITE FILE-E-REC
IF FS-E NOT = '00'
MOVE 'FATAL' TO WS-SEVERITY
STRING 'Write FILE-E FS=' FS-E
INTO WS-ERROR-MSG
PERFORM 6000-ERROR-HANDLE-SECTION
END-IF
ADD 1 TO WS-COUNT-E
ADD WS-DATA2-NUM TO WS-HASH-OUT-E
ADD 1 TO WS-RECORDS-WRITTEN
DISPLAY ' -> Key=''E'' routed to FILE-E'
MOVE 'STUDENT-P05' TO WS-PLAN-NAME
WHEN 'F' ALSO ANY
MOVE IN-KEY TO F-KEY
MOVE IN-DATA1 TO F-DATA1
MOVE IN-DATA2 TO F-DATA2
WRITE FILE-F-REC
IF FS-F NOT = '00'
MOVE 'FATAL' TO WS-SEVERITY
STRING 'Write FILE-F FS=' FS-F
INTO WS-ERROR-MSG
PERFORM 6000-ERROR-HANDLE-SECTION
END-IF
ADD 1 TO WS-COUNT-F
ADD WS-DATA2-NUM TO WS-HASH-OUT-F
ADD 1 TO WS-RECORDS-WRITTEN
DISPLAY ' -> Key=''F'' routed to FILE-F'
MOVE 'SENIOR-P06' TO WS-PLAN-NAME
WHEN 'G' ALSO ANY
MOVE IN-KEY TO G-KEY
MOVE IN-DATA1 TO G-DATA1
MOVE IN-DATA2 TO G-DATA2
WRITE FILE-G-REC
IF FS-G NOT = '00'
MOVE 'FATAL' TO WS-SEVERITY
STRING 'Write FILE-G FS=' FS-G
INTO WS-ERROR-MSG
PERFORM 6000-ERROR-HANDLE-SECTION
END-IF
ADD 1 TO WS-COUNT-G
ADD WS-DATA2-NUM TO WS-HASH-OUT-G
ADD 1 TO WS-RECORDS-WRITTEN
DISPLAY ' -> Key=''G'' routed to FILE-G'
MOVE 'CORP-P07' TO WS-PLAN-NAME
WHEN OTHER
MOVE IN-KEY TO O-KEY
MOVE IN-DATA1 TO O-DATA1
MOVE IN-DATA2 TO O-DATA2
WRITE FILE-OTHER-REC
IF FS-OTHER NOT = '00'
MOVE 'FATAL' TO WS-SEVERITY
STRING 'Write FILE-OTHER FS=' FS-OTHER
INTO WS-ERROR-MSG
PERFORM 6000-ERROR-HANDLE-SECTION
END-IF
ADD 1 TO WS-COUNT-OTHER
ADD WS-DATA2-NUM TO WS-HASH-OUT-OTHER
ADD 1 TO WS-RECORDS-WRITTEN
DISPLAY ' -> Key=''' IN-KEY
''' routed to FILE-OTHER'
MOVE 'FALLBACK' TO WS-PLAN-NAME
END-EVALUATE
*> ============================================================
*> ORIGINAL EVALUATE TRUE/FALSE — preserved
*> ============================================================
IF WS-DATA2-NUM > 5000
SET WS-IS-TRUE TO TRUE
ELSE
MOVE 'N' TO WS-TRUE-FALSE
END-IF
EVALUATE TRUE
WHEN WS-DATA2-NUM < 1000
DISPLAY ' [EVAL TRUE] DATA2 small (< 1000)'
WHEN WS-DATA2-NUM >= 1000
AND WS-DATA2-NUM <= 5000
DISPLAY ' [EVAL TRUE] DATA2 medium (1000-5000)'
WHEN WS-IS-TRUE
DISPLAY ' [EVAL TRUE] DATA2 large (> 5000)'
WHEN OTHER
DISPLAY ' [EVAL TRUE] OTHER (unexpected)'
END-EVALUATE
*> ============================================================
*> ORIGINAL EVALUATE multi-value WHEN — preserved
*> ============================================================
EVALUATE IN-DATA1 (1:7)
WHEN 'SPECIAL'
WHEN 'SPECIAL'
DISPLAY ' [EVAL MULTI] DATA1 starts with SPECIAL'
WHEN 'HIGH'
DISPLAY ' [EVAL MULTI] DATA1 starts with HIGH'
WHEN OTHER
DISPLAY ' [EVAL MULTI] DATA1 starts with normal'
END-EVALUATE
*> NEW: EVALUATE for multi-factor plan rules
EVALUATE WS-CALL-TYPE ALSO WS-DESTINATION
ALSO WS-DURATION-CAT
WHEN 'PEAK' ALSO 'DOM' ALSO 'SHORT'
DISPLAY ' [MULTI] Peak Domestic Short'
WHEN 'PEAK' ALSO 'DOM' ALSO ANY
DISPLAY ' [MULTI] Peak Domestic Any'
WHEN 'OFF-PEAK' ALSO 'DOM' ALSO ANY
DISPLAY ' [MULTI] Off-Peak Domestic Any'
WHEN ANY ALSO 'INTL' ALSO ANY
DISPLAY ' [MULTI] International call'
WHEN OTHER
DISPLAY ' [MULTI] Unmapped call combo'
END-EVALUATE
*> NEW: EVALUATE for data cap rules
EVALUATE WS-DATA-CAP
WHEN 0 THRU 1000
DISPLAY ' [DATA-CAP] Low: ' WS-DATA-CAP 'MB'
WHEN 1001 THRU 5000
DISPLAY ' [DATA-CAP] Medium: ' WS-DATA-CAP 'MB'
WHEN 5001 THRU 99999
DISPLAY ' [DATA-CAP] High: ' WS-DATA-CAP 'MB'
WHEN OTHER
DISPLAY ' [DATA-CAP] Unlimited or unknown'
END-EVALUATE
*> NEW: Nested EVALUATE for plan-specific business rules
*> (data cap, international rates per plan tier)
MOVE SPACES TO WS-PLAN-CODE
EVALUATE IN-KEY
WHEN 'A' MOVE 'P01' TO WS-PLAN-CODE
WHEN 'B' MOVE 'P02' TO WS-PLAN-CODE
WHEN 'C' MOVE 'P03' TO WS-PLAN-CODE
WHEN 'D' MOVE 'P04' TO WS-PLAN-CODE
WHEN 'E' MOVE 'P05' TO WS-PLAN-CODE
WHEN 'F' MOVE 'P06' TO WS-PLAN-CODE
WHEN 'G' MOVE 'P07' TO WS-PLAN-CODE
WHEN OTHER MOVE 'P00' TO WS-PLAN-CODE
END-EVALUATE
EVALUATE WS-PLAN-CODE
WHEN 'P01'
MOVE 1000 TO WS-DATA-CAP
MOVE 2.50 TO WS-INTL-RATE
EVALUATE TRUE
WHEN WS-DURATION-CAT = 'LONG'
DISPLAY ' [P01 MAX] Basic long call'
WHEN WS-DURATION-CAT = 'EXTENDED'
DISPLAY ' [P01 CAP] Basic cap applied'
END-EVALUATE
DISPLAY ' [PLAN P01] Basic plan rules'
WHEN 'P02'
MOVE 5000 TO WS-DATA-CAP
MOVE 1.50 TO WS-INTL-RATE
EVALUATE TRUE
WHEN WS-DURATION-CAT = 'LONG'
DISPLAY ' [P02 DISCOUNT] Business bulk'
WHEN WS-DURATION-CAT = 'EXTENDED'
DISPLAY ' [P02 CAP] Business cap warning'
END-EVALUATE
DISPLAY ' [PLAN P02] Business plan rules'
WHEN 'P03'
MOVE 99999 TO WS-DATA-CAP
MOVE 0.50 TO WS-INTL-RATE
DISPLAY ' [PLAN P03] Unlimited - no data cap'
WHEN 'P04'
MOVE 8000 TO WS-DATA-CAP
MOVE 1.00 TO WS-INTL-RATE
EVALUATE WS-DURATION-CAT ALSO WS-DESTINATION
WHEN 'LONG' ALSO 'INTL'
DISPLAY ' [P04 FAM] Family intl discount'
WHEN 'EXTENDED' ALSO ANY
DISPLAY ' [P04 FAM] Family extended cap'
WHEN OTHER
DISPLAY ' [P04 FAM] Standard family rate'
END-EVALUATE
WHEN 'P05'
MOVE 2000 TO WS-DATA-CAP
MOVE 1.75 TO WS-INTL-RATE
DISPLAY ' [PLAN P05] Student plan - limited cap'
WHEN 'P06'
MOVE 1500 TO WS-DATA-CAP
MOVE 1.25 TO WS-INTL-RATE
DISPLAY ' [PLAN P06] Senior plan - reduced rates'
WHEN 'P07'
MOVE 50000 TO WS-DATA-CAP
MOVE 0.75 TO WS-INTL-RATE
DISPLAY ' [PLAN P07] Corporate plan - bulk rates'
WHEN OTHER
MOVE 500 TO WS-DATA-CAP
MOVE 3.00 TO WS-INTL-RATE
DISPLAY ' [PLAN P00] Default plan - basic rates'
END-EVALUATE
*> NEW: EVALUATE TRUE/FALSE for weekday/weekend and domestic/roaming
EVALUATE IN-DATA1 (1:4)
WHEN 'PEAK'
WHEN 'ROAM'
SET WS-PEAK TO TRUE
WHEN 'OFFP'
WHEN 'WKND'
SET WS-OFF-PEAK TO TRUE
WHEN OTHER
MOVE 'P' TO WS-PEAK-FLAG
END-EVALUATE
EVALUATE IN-DATA1 (1:4)
WHEN 'WKND'
SET WS-WEEKEND TO TRUE
WHEN 'PEAK'
SET WS-WEEKDAY TO TRUE
WHEN 'OFFP'
SET WS-WEEKDAY TO TRUE
WHEN OTHER
SET WS-WEEKDAY TO TRUE
END-EVALUATE
EVALUATE IN-DATA1 (1:4)
WHEN 'ROAM'
SET WS-ROAMING TO TRUE
WHEN OTHER
SET WS-DOMESTIC TO TRUE
END-EVALUATE
EVALUATE TRUE ALSO TRUE ALSO TRUE
WHEN WS-PEAK ALSO WS-WEEKDAY ALSO WS-DOMESTIC
DISPLAY ' [TIME/DST] Peak weekday domestic'
WHEN WS-PEAK ALSO WS-WEEKEND ALSO WS-DOMESTIC
DISPLAY ' [TIME/DST] Peak weekend domestic'
WHEN WS-OFF-PEAK ALSO WS-WEEKDAY ALSO WS-DOMESTIC
DISPLAY ' [TIME/DST] Off-peak weekday domestic'
WHEN WS-OFF-PEAK ALSO WS-WEEKEND ALSO WS-DOMESTIC
DISPLAY ' [TIME/DST] Off-peak weekend domestic'
WHEN WS-PEAK ALSO WS-WEEKDAY ALSO WS-ROAMING
DISPLAY ' [TIME/DST] Peak weekday roaming'
WHEN WS-PEAK ALSO WS-WEEKEND ALSO WS-ROAMING
DISPLAY ' [TIME/DST] Peak weekend roaming'
WHEN WS-OFF-PEAK ALSO WS-WEEKDAY ALSO WS-ROAMING
DISPLAY ' [TIME/DST] Off-peak weekday roaming'
WHEN WS-OFF-PEAK ALSO WS-WEEKEND ALSO WS-ROAMING
DISPLAY ' [TIME/DST] Off-peak weekend roaming'
WHEN OTHER
DISPLAY ' [TIME/DST] Unmapped time/destination'
END-EVALUATE
*> NEW: EVALUATE for peak flag
EVALUATE WS-PEAK-FLAG
WHEN 'P'
DISPLAY ' [PEAK] Peak rate applies'
WHEN 'O'
DISPLAY ' [PEAK] Off-peak rate applies'
WHEN OTHER
DISPLAY ' [PEAK] Undefined peak flag'
END-EVALUATE
*> NEW: Minimum charge check using EVALUATE
EVALUATE TRUE
WHEN WS-PLAN-NAME = SPACES
MOVE WS-FALLBACK-RATE TO WS-PLAN-RATE
DISPLAY ' [MIN-CHG] Fallback rate applied'
WHEN WS-PLAN-RATE < WS-MIN-CHARGE
MOVE 'WARNING' TO WS-SEVERITY
STRING 'Rate below min charge: '
WS-PLAN-RATE INTO WS-ERROR-MSG
PERFORM 6000-ERROR-HANDLE-SECTION
WHEN OTHER
CONTINUE
END-EVALUATE
*> NEW: Cap check using EVALUATE
EVALUATE TRUE
WHEN WS-PLAN-RATE > WS-CAP-AMOUNT
MOVE 'WARNING' TO WS-SEVERITY
STRING 'Rate exceeds cap: '
WS-PLAN-RATE INTO WS-ERROR-MSG
PERFORM 6000-ERROR-HANDLE-SECTION
WHEN OTHER
CONTINUE
END-EVALUATE
*> NEW: Fallback default rate - EVALUATE multiple WHEN
EVALUATE WS-PLAN-NAME
WHEN SPACES
WHEN LOW-VALUES
WHEN 'FALLBACK'
MOVE WS-FALLBACK-RATE TO WS-PLAN-RATE
MOVE 'STANDARD' TO WS-PLAN-NAME
DISPLAY ' [FALLBACK] Default rate for unmapped'
WHEN OTHER
DISPLAY ' [FALLBACK] Plan ' WS-PLAN-NAME
' has valid rate'
END-EVALUATE
*> NEW: EVALUATE for rate lookup validation per plan
EVALUATE WS-PLAN-RATE ALSO WS-PLAN-CODE
WHEN 0.00 THRU 5.00 ALSO 'P01'
DISPLAY ' [RATE-VAL] P01 rate: ' WS-PLAN-RATE
WHEN 0.00 THRU 10.00 ALSO 'P02'
DISPLAY ' [RATE-VAL] P02 rate: ' WS-PLAN-RATE
WHEN 0.00 THRU 20.00 ALSO 'P03'
DISPLAY ' [RATE-VAL] P03 rate: ' WS-PLAN-RATE
WHEN 0.00 THRU 8.00 ALSO 'P04'
DISPLAY ' [RATE-VAL] P04 rate: ' WS-PLAN-RATE
WHEN 0.00 THRU 6.00 ALSO 'P05'
DISPLAY ' [RATE-VAL] P05 rate: ' WS-PLAN-RATE
WHEN 0.00 THRU 5.00 ALSO 'P06'
DISPLAY ' [RATE-VAL] P06 rate: ' WS-PLAN-RATE
WHEN 0.00 THRU 25.00 ALSO 'P07'
DISPLAY ' [RATE-VAL] P07 rate: ' WS-PLAN-RATE
WHEN OTHER
MOVE 'WARNING' TO WS-SEVERITY
STRING 'Rate ' WS-PLAN-RATE ' invalid for plan '
WS-PLAN-CODE INTO WS-ERROR-MSG
PERFORM 6000-ERROR-HANDLE-SECTION
END-EVALUATE
*> NEW: Error severity classification using EVALUATE
EVALUATE WS-ERROR-COUNT
WHEN 0
DISPLAY ' [SEVERITY] No errors - clean batch'
WHEN 1 THRU 5
DISPLAY ' [SEVERITY] Low error count (1-5)'
WHEN 6 THRU 20
DISPLAY ' [SEVERITY] Medium error count (6-20)'
WHEN 21 THRU 99999
DISPLAY ' [SEVERITY] High error count (>20)'
WHEN OTHER
DISPLAY ' [SEVERITY] Error count overflow'
END-EVALUATE
EVALUATE WS-WARN-COUNT
WHEN 0
DISPLAY ' [SEVERITY] No warnings'
WHEN 1 THRU 10
DISPLAY ' [SEVERITY] Low warning count (1-10)'
WHEN 11 THRU 50
DISPLAY ' [SEVERITY] Medium warning count (11-50)'
WHEN 51 THRU 99999
DISPLAY ' [SEVERITY] High warning count (>50)'
WHEN OTHER
DISPLAY ' [SEVERITY] Warning count overflow'
END-EVALUATE
PERFORM 5000-AUDIT-SECTION
THRU AUDIT-LOG-RECORD
.
*
3400-WRITE-OUTPUT-SECTION.
*
3400-WRITE-OUTPUT.
*> Writing is handled within each EVALUATE WHEN branch
.
*
4000-REPORT-SECTION.
*
4000-REPORT.
DISPLAY ' '
DISPLAY '=== RESULTS ==='
DISPLAY 'FILE-A (P01 Basic): ' WS-COUNT-A ' records'
DISPLAY 'FILE-B (P02 Bus): ' WS-COUNT-B ' records'
DISPLAY 'FILE-C (P03 Unlim): ' WS-COUNT-C ' records'
DISPLAY 'FILE-D (P04 Fam): ' WS-COUNT-D ' records'
DISPLAY 'FILE-E (P05 Stdnt): ' WS-COUNT-E ' records'
DISPLAY 'FILE-F (P06 Senior): ' WS-COUNT-F ' records'
DISPLAY 'FILE-G (P07 Corp): ' WS-COUNT-G ' records'
DISPLAY 'FILE-OTHER: ' WS-COUNT-OTHER ' records'
DISPLAY ' '
DISPLAY 'Total records read: ' WS-RECORDS-READ
DISPLAY 'Total records written: ' WS-RECORDS-WRITTEN
DISPLAY 'Errors: ' WS-ERROR-COUNT
DISPLAY 'Warnings: ' WS-WARN-COUNT
*> Hash total verification
DISPLAY ' '
DISPLAY 'Hash total verification:'
DISPLAY ' Input hash: ' WS-HASH-IN
DISPLAY ' Out-A hash: ' WS-HASH-OUT-A
DISPLAY ' Out-B hash: ' WS-HASH-OUT-B
DISPLAY ' Out-C hash: ' WS-HASH-OUT-C
DISPLAY ' Out-D hash: ' WS-HASH-OUT-D
DISPLAY ' Out-E hash: ' WS-HASH-OUT-E
DISPLAY ' Out-F hash: ' WS-HASH-OUT-F
DISPLAY ' Out-G hash: ' WS-HASH-OUT-G
DISPLAY ' Out-Other hash:' WS-HASH-OUT-OTHER
IF WS-HASH-IN =
(WS-HASH-OUT-A + WS-HASH-OUT-B + WS-HASH-OUT-C
+ WS-HASH-OUT-D + WS-HASH-OUT-E + WS-HASH-OUT-F
+ WS-HASH-OUT-G + WS-HASH-OUT-OTHER)
MOVE 'YES' TO WS-HASH-VERIFIED
DISPLAY ' HASH VERIFICATION: PASSED'
ELSE
MOVE 'NO ' TO WS-HASH-VERIFIED
DISPLAY ' HASH VERIFICATION: FAILED'
END-IF
*> Batch control totals
COMPUTE WS-BATCH-TOTAL-AMT =
WS-HASH-OUT-A + WS-HASH-OUT-B + WS-HASH-OUT-C
+ WS-HASH-OUT-D + WS-HASH-OUT-E + WS-HASH-OUT-F
+ WS-HASH-OUT-G + WS-HASH-OUT-OTHER
MOVE WS-HASH-IN TO WS-HASH-TOTAL
DISPLAY ' '
DISPLAY 'Batch Control:'
DISPLAY ' Batch Date: ' WS-BATCH-DATE
DISPLAY ' Batch Time: ' WS-BATCH-TIME
DISPLAY ' Total Amt: ' WS-BATCH-TOTAL-AMT
DISPLAY ' Hash Total: ' WS-HASH-TOTAL
.
*
5000-AUDIT-SECTION.
*
AUDIT-LOG-START.
MOVE WS-TIMESTAMP TO AU-TIMESTAMP
MOVE 'START' TO AU-TIER
MOVE 'PROGRAM' TO AU-KEY
MOVE 0 TO AU-AMOUNT
MOVE 'OK' TO AU-STATUS
WRITE FILE-AUDIT-REC FROM WS-AUDIT-LINE
IF FS-AUDIT NOT = '00'
DISPLAY 'Audit write warning FS=' FS-AUDIT
END-IF
.
AUDIT-LOG-RECORD.
MOVE WS-TIMESTAMP TO AU-TIMESTAMP
MOVE IN-KEY TO AU-TIER
MOVE IN-KEY TO AU-KEY
MOVE WS-DATA2-NUM TO AU-AMOUNT
MOVE 'OK' TO AU-STATUS
WRITE FILE-AUDIT-REC FROM WS-AUDIT-LINE
IF FS-AUDIT NOT = '00'
DISPLAY 'Audit write warning FS=' FS-AUDIT
END-IF
.
AUDIT-LOG-FINISH.
MOVE WS-TIMESTAMP TO AU-TIMESTAMP
MOVE 'END' TO AU-TIER
MOVE 'PROGRAM' TO AU-KEY
MOVE WS-RECORDS-READ TO AU-AMOUNT
STRING 'REC=' WS-RECORDS-READ
' ERR=' WS-ERROR-COUNT
INTO AU-STATUS
WRITE FILE-AUDIT-REC FROM WS-AUDIT-LINE
IF FS-AUDIT NOT = '00'
DISPLAY 'Audit write warning FS=' FS-AUDIT
END-IF
.
*
6000-ERROR-HANDLE-SECTION.
*
6000-ERROR-HANDLE.
DISPLAY '[' WS-TIMESTAMP '] [' WS-SEVERITY '] '
WS-ERROR-MSG
IF WS-SEVERITY = 'FATAL'
PERFORM 9000-EXIT-SECTION
STOP RUN
ELSE
IF WS-SEVERITY = 'ERROR'
ADD 1 TO WS-ERROR-COUNT
ELSE
IF WS-SEVERITY = 'WARNING'
ADD 1 TO WS-WARN-COUNT
END-IF
END-IF
END-IF
.
*
9000-EXIT-SECTION.
*
9000-EXIT.
MOVE FUNCTION CURRENT-DATE (1:10) TO WS-DATE
MOVE FUNCTION CURRENT-DATE (12:8) TO WS-TIME
STRING WS-DATE ' ' WS-TIME INTO WS-TIMESTAMP
PERFORM 4000-REPORT-SECTION
PERFORM 5000-AUDIT-SECTION
THRU AUDIT-LOG-FINISH
CLOSE FILE-IN FILE-A FILE-B FILE-C
FILE-D FILE-E FILE-F
FILE-G FILE-OTHER
IF FS-AUDIT NOT = '00'
CLOSE FILE-AUDIT
END-IF
DISPLAY '[' WS-TIMESTAMP '] BranchEval COMPLETED'
.