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,756 @@
*> ============================================================
*> subprogram : 计费子程序 (Billing Subprogram) — CALLEE
*> Input : LK-A, LK-B (LINKAGE参数: 用量值)
*> LK-TIER (LINKAGE参数: 计费阶梯)
*> Output: LK-RESULT, LK-STATUS (计算结果+状态)
*> LK-ERROR-CODE (错误编码)
*> Coverage: C-N001~N008, C-A001, C-R001, C-R002
*>
*> EXPANDED: Multiple billing tiers with configurable multipliers,
*> parameter validation (range checks, numeric checks),
*> error code mapping with lookup, audit file with detail lines,
*> statistical tracking (min/max/avg), discount/premium stacking,
*> voice/data/message component breakdown, tracing, SECTION structure.
*> ============================================================
IDENTIFICATION DIVISION.
PROGRAM-ID. SUBPGM.
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT AUDIT-FILE ASSIGN TO "subpgm-audit.txt"
ORGANIZATION IS LINE SEQUENTIAL
FILE STATUS IS FS-AUDIT.
SELECT ERROR-FILE ASSIGN TO "subpgm-errors.txt"
ORGANIZATION IS LINE SEQUENTIAL
FILE STATUS IS FS-ERROR.
SELECT CONFIG-FILE ASSIGN TO "subpgm-config.dat"
ORGANIZATION IS LINE SEQUENTIAL
FILE STATUS IS FS-CONFIG.
DATA DIVISION.
FILE SECTION.
FD AUDIT-FILE.
01 AUDIT-LINE PIC X(120).
FD ERROR-FILE.
01 ERROR-LINE PIC X(120).
FD CONFIG-FILE.
01 CONFIG-LINE PIC X(80).
WORKING-STORAGE SECTION.
*> ============================================================
*> FILE STATUS FIELDS
*> ============================================================
01 FS-AUDIT PIC X(02).
01 FS-ERROR PIC X(02).
01 FS-CONFIG PIC X(02).
*> ============================================================
*> LOCAL STATE
*> ============================================================
01 WS-LOCAL-COUNT PIC 9(05) VALUE 0.
01 WS-PGM-NAME PIC X(08) VALUE 'SUBPGM '.
01 WS-CALL-COUNT PIC 9(05) VALUE 0.
01 WS-INIT-FLAG PIC X(01) VALUE 'N'.
88 WS-INITIALIZED VALUE 'Y'.
01 WS-SUB-STATUS PIC X(01) VALUE 'N'.
88 WS-SUB-ACTIVE VALUE 'Y'.
*> ============================================================
*> BILLING TIER CONFIGURATION
*> ============================================================
01 WS-TIER-CONFIG.
05 WS-TIER-MULTIPLIER PIC 9(02)V99.
05 WS-TIER-NAME PIC X(15).
05 WS-TIER-BASE-RATE PIC 9(03)V99.
05 WS-TIER-DATA-RATE PIC 9(03)V99.
05 WS-TIER-DISCOUNT PIC 9(02).
01 WS-TIER-TABLE.
05 FILLER PIC X(32) VALUE '011.00Basic 005.005.00 00'.
05 FILLER PIC X(32) VALUE '021.50Premium 008.007.00 05'.
05 FILLER PIC X(32) VALUE '033.00Enterprise 010.008.00 10'.
05 FILLER PIC X(32) VALUE '042.50Family 007.006.00 08'.
01 WS-TIER-TABLE-REDEF REDEFINES WS-TIER-TABLE.
05 WS-TIER-ENTRY OCCURS 4 TIMES.
10 WS-TIER-CODE PIC 9(01).
10 WS-TIER-MULT PIC 9(02)V99.
10 WS-TIER-DESC PIC X(15).
10 WS-TIER-BASE PIC 9(03)V99.
10 WS-TIER-DATA PIC 9(03)V99.
10 WS-TIER-DISC PIC 9(02).
*> ============================================================
*> CALCULATION COMPONENTS
*> ============================================================
01 WS-CALC-COMPONENTS.
05 WS-COMP-VOICE-AMT PIC 9(09)V99 VALUE 0.
05 WS-COMP-DATA-AMT PIC 9(09)V99 VALUE 0.
05 WS-COMP-MSG-AMT PIC 9(09)V99 VALUE 0.
05 WS-COMP-DISCOUNT PIC 9(09)V99 VALUE 0.
05 WS-COMP-SUBTOTAL PIC 9(09)V99 VALUE 0.
05 WS-COMP-FINAL PIC 9(09)V99 VALUE 0.
05 WS-COMP-TIER-MULT PIC 9(02)V99 VALUE 1.00.
*> ============================================================
*> CALL STATISTICS
*> ============================================================
01 WS-STATISTICS.
05 WS-STAT-MIN-VAL PIC 9(10) VALUE 9999999999.
05 WS-STAT-MAX-VAL PIC 9(10) VALUE 0.
05 WS-STAT-SUM-VAL PIC 9(15) VALUE 0.
05 WS-STAT-COUNT PIC 9(05) VALUE 0.
05 WS-STAT-AVG-VAL PIC 9(10) VALUE 0.
05 WS-STAT-ERR-COUNT PIC 9(05) VALUE 0.
05 WS-STAT-SUCCESS-CNT PIC 9(05) VALUE 0.
*> ============================================================
*> ERROR CODE MAPPING
*> ============================================================
01 WS-ERR-CODE-TABLE.
05 FILLER PIC X(32) VALUE '00OK '.
05 FILLER PIC X(32) VALUE '01INVALID INPUT A '.
05 FILLER PIC X(32) VALUE '02INVALID INPUT B '.
05 FILLER PIC X(32) VALUE '03INPUT OUT OF RANGE '.
05 FILLER PIC X(32) VALUE '04INVALID BILLING TIER '.
05 FILLER PIC X(32) VALUE '05CALCULATION OVERFLOW '.
05 FILLER PIC X(32) VALUE '06SUBPROGRAM NOT FOUND '.
05 FILLER PIC X(32) VALUE '07SUBPROGRAM ERROR '.
05 FILLER PIC X(32) VALUE '08TIER MULTIPLIER ERROR '.
05 FILLER PIC X(32) VALUE '09INTERNAL ERROR '.
01 WS-ERR-REDEF REDEFINES WS-ERR-CODE-TABLE.
05 WS-ERR-ENTRY OCCURS 10 TIMES.
10 WS-EC-CODE PIC X(02).
10 WS-EC-MESSAGE PIC X(30).
*> ============================================================
*> CALCULATION FIELDS
*> ============================================================
01 WS-CALC-SUM PIC 9(10) VALUE 0.
01 WS-CALC-RESULT PIC 9(10) VALUE 0.
01 WS-CALC-MULT PIC 9(05)V99 VALUE 0.
01 WS-OVERFLOW-CHECK PIC 9(15) VALUE 0.
01 WS-CALC-VOICE-MIN PIC 9(05) VALUE 0.
01 WS-CALC-DATA-MB PIC 9(09) VALUE 0.
01 WS-CALC-MSG-COUNT PIC 9(05) VALUE 0.
*> ============================================================
*> VALIDATION CONTROLS
*> ============================================================
01 WS-MIN-VALUE PIC 9(05) VALUE 0.
01 WS-MAX-VALUE PIC 9(05) VALUE 99999.
01 WS-MIN-TIER PIC 9(01) VALUE 1.
01 WS-MAX-TIER PIC 9(01) VALUE 4.
01 WS-VALIDATION-MSG PIC X(40).
*> ============================================================
*> AUDIT / TRACE 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).
*> ============================================================
*> 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 'SUBPGM ERR '.
05 ED-NUM PIC Z(9).
05 FILLER PIC X(02) VALUE ': '.
05 ED-MESSAGE PIC X(80).
*> ============================================================
*> AUDIT LINE TEMPLATES
*> ============================================================
01 WS-AUDIT-HEADER.
05 FILLER PIC X(40) VALUE
'=== SUBPGM Callee Audit Log ==='.
01 WS-AUDIT-CALL.
05 FILLER PIC X(10) VALUE ' CALL #'.
05 AC-CALL-NUM PIC Z(9)5.
05 FILLER PIC X(05) VALUE ' A='.
05 AC-A PIC Z(9)5.
05 FILLER PIC X(05) VALUE ' B='.
05 AC-B PIC Z(9)5.
05 FILLER PIC X(10) VALUE ' TIER='.
05 AC-TIER PIC Z(9).
05 FILLER PIC X(10) VALUE ' RESULT='.
05 AC-RESULT PIC Z(9)9.
05 FILLER PIC X(10) VALUE ' STATUS='.
05 AC-STATUS PIC Z(9).
05 FILLER PIC X(10) VALUE ' ERR='.
05 AC-ERR PIC Z(9).
01 WS-AUDIT-DETAIL.
05 FILLER PIC X(10) VALUE ' DETAIL '.
05 AD-COMP PIC X(10).
05 FILLER PIC X(05) VALUE ' AMT='.
05 AD-AMT PIC Z(11)9.99.
01 WS-AUDIT-STATS.
05 FILLER PIC X(10) VALUE ' STATS: '.
05 FILLER PIC X(10) VALUE 'MIN='.
05 AS-MIN PIC Z(9)9.
05 FILLER PIC X(10) VALUE ' MAX='.
05 AS-MAX PIC Z(9)9.
05 FILLER PIC X(10) VALUE ' AVG='.
05 AS-AVG PIC Z(9)9.
05 FILLER PIC X(10) VALUE ' CNT='.
05 AS-CNT PIC Z(9)5.
01 WS-AUDIT-ERR-STATS.
05 FILLER PIC X(10) VALUE ' ERRORS:'.
05 AE-COUNT PIC Z(9)5.
05 FILLER PIC X(10) VALUE ' SUCCESS:'.
05 AE-SUCCESS PIC Z(9)5.
01 WS-AUDIT-FOOTER.
05 FILLER PIC X(50) VALUE
'--- END OF SUBPGM AUDIT LOG ---'.
LINKAGE SECTION.
01 LK-A PIC 9(05).
01 LK-B PIC 9(05).
01 LK-RESULT PIC 9(10).
01 LK-STATUS PIC 9(02).
01 LK-ERROR-CODE PIC 9(02).
01 LK-TIER PIC 9(01).
PROCEDURE DIVISION USING LK-A, LK-B, LK-RESULT, LK-STATUS,
LK-ERROR-CODE, LK-TIER.
*> ============================================================
*> 1000-INIT — Initialization
*> ============================================================
1000-INIT SECTION.
1000-START.
ADD 1 TO WS-LOCAL-COUNT.
ADD 1 TO WS-CALL-COUNT.
ACCEPT WS-CURRENT-TIME FROM TIME.
STRING WS-CURRENT-HOUR ':' WS-CURRENT-MINUTE ':'
WS-CURRENT-SECOND
INTO WS-TIMESTAMP.
DISPLAY '[TRACE] SUBPGM 1000-INIT call #' WS-CALL-COUNT
' at ' WS-TIMESTAMP.
*> Open files only on first call
IF NOT WS-INITIALIZED
SET WS-INITIALIZED TO TRUE
SET WS-SUB-ACTIVE TO TRUE
OPEN OUTPUT AUDIT-FILE
IF FS-AUDIT NOT = '00'
DISPLAY 'SUBPGM: WARNING Cannot open AUDIT-FILE '
'status=' FS-AUDIT
ELSE
WRITE AUDIT-LINE FROM WS-AUDIT-HEADER
END-IF
OPEN OUTPUT ERROR-FILE
IF FS-ERROR NOT = '00'
DISPLAY 'SUBPGM: WARNING Cannot open ERROR-FILE '
'status=' FS-ERROR
END-IF
*> Attempt to load config file (optional)
OPEN INPUT CONFIG-FILE
IF FS-CONFIG = '00'
DISPLAY 'SUBPGM: Config file loaded'
PERFORM 1100-LOAD-CONFIG
THRU 1100-LOAD-CONFIG-EXIT
CLOSE CONFIG-FILE
ELSE
DISPLAY 'SUBPGM: No config file — using defaults'
END-IF
DISPLAY '[TRACE] SUBPGM initialized, tier table ready'
END-IF.
DISPLAY '[TRACE] SUBPGM call #' WS-CALL-COUNT
' A=' LK-A ' B=' LK-B ' TIER=' LK-TIER.
1000-EXIT.
EXIT.
*> ============================================================
*> 1100-LOAD-CONFIG — Load configuration file
*> ============================================================
1100-LOAD-CONFIG SECTION.
1100-LOAD-CONFIG-START.
DISPLAY '[TRACE] SUBPGM 1100-LOAD-CONFIG start'.
*> Read config lines (format: TIER,NAME,MULT,BASE,DATA,DISC)
READ CONFIG-FILE INTO CONFIG-LINE
AT END DISPLAY 'SUBPGM: Config file empty'
END-READ.
DISPLAY '[TRACE] SUBPGM 1100-LOAD-CONFIG complete'.
1100-LOAD-CONFIG-EXIT.
EXIT.
*> ============================================================
*> 2000-VALIDATE — Validate all inputs
*> ============================================================
2000-VALIDATE SECTION.
2000-START.
DISPLAY '[TRACE] SUBPGM 2000-VALIDATE A=' LK-A
' B=' LK-B ' TIER=' LK-TIER.
*> Validate input A: must be numeric
IF LK-A IS NOT NUMERIC
MOVE 01 TO LK-ERROR-CODE
MOVE 99 TO LK-STATUS
STRING 'INPUT A NOT NUMERIC: value=' LK-A
INTO WS-VALIDATION-MSG
DISPLAY 'SUBPGM: ' WS-VALIDATION-MSG
PERFORM 6000-ERROR THRU 6000-ERROR-EXIT
GOBACK
END-IF.
*> Validate input A: range check
IF LK-A < WS-MIN-VALUE
MOVE 03 TO LK-ERROR-CODE
MOVE 99 TO LK-STATUS
STRING 'INPUT A BELOW MIN: ' LK-A ' < ' WS-MIN-VALUE
INTO WS-VALIDATION-MSG
DISPLAY 'SUBPGM: ' WS-VALIDATION-MSG
PERFORM 6000-ERROR THRU 6000-ERROR-EXIT
GOBACK
END-IF.
IF LK-A > WS-MAX-VALUE
MOVE 03 TO LK-ERROR-CODE
MOVE 99 TO LK-STATUS
STRING 'INPUT A EXCEEDS MAX: ' LK-A ' > ' WS-MAX-VALUE
INTO WS-VALIDATION-MSG
DISPLAY 'SUBPGM: ' WS-VALIDATION-MSG
PERFORM 6000-ERROR THRU 6000-ERROR-EXIT
GOBACK
END-IF.
*> Validate input B: must be numeric
IF LK-B IS NOT NUMERIC
MOVE 02 TO LK-ERROR-CODE
MOVE 99 TO LK-STATUS
STRING 'INPUT B NOT NUMERIC: value=' LK-B
INTO WS-VALIDATION-MSG
DISPLAY 'SUBPGM: ' WS-VALIDATION-MSG
PERFORM 6000-ERROR THRU 6000-ERROR-EXIT
GOBACK
END-IF.
*> Validate input B: range check
IF LK-B < WS-MIN-VALUE
MOVE 03 TO LK-ERROR-CODE
MOVE 99 TO LK-STATUS
STRING 'INPUT B BELOW MIN: ' LK-B ' < ' WS-MIN-VALUE
INTO WS-VALIDATION-MSG
DISPLAY 'SUBPGM: ' WS-VALIDATION-MSG
PERFORM 6000-ERROR THRU 6000-ERROR-EXIT
GOBACK
END-IF.
IF LK-B > WS-MAX-VALUE
MOVE 03 TO LK-ERROR-CODE
MOVE 99 TO LK-STATUS
STRING 'INPUT B EXCEEDS MAX: ' LK-B ' > ' WS-MAX-VALUE
INTO WS-VALIDATION-MSG
DISPLAY 'SUBPGM: ' WS-VALIDATION-MSG
PERFORM 6000-ERROR THRU 6000-ERROR-EXIT
GOBACK
END-IF.
*> Validate tier: must be numeric
IF LK-TIER IS NOT NUMERIC
MOVE 04 TO LK-ERROR-CODE
MOVE 99 TO LK-STATUS
STRING 'TIER NOT NUMERIC: value=' LK-TIER
INTO WS-VALIDATION-MSG
DISPLAY 'SUBPGM: ' WS-VALIDATION-MSG
PERFORM 6000-ERROR THRU 6000-ERROR-EXIT
GOBACK
END-IF.
*> Validate tier: range check
IF LK-TIER < WS-MIN-TIER
MOVE 04 TO LK-ERROR-CODE
MOVE 99 TO LK-STATUS
STRING 'TIER ' LK-TIER ' BELOW MIN ' WS-MIN-TIER
INTO WS-VALIDATION-MSG
DISPLAY 'SUBPGM: ' WS-VALIDATION-MSG
PERFORM 6000-ERROR THRU 6000-ERROR-EXIT
GOBACK
END-IF.
IF LK-TIER > WS-MAX-TIER
MOVE 04 TO LK-ERROR-CODE
MOVE 99 TO LK-STATUS
STRING 'TIER ' LK-TIER ' EXCEEDS MAX ' WS-MAX-TIER
INTO WS-VALIDATION-MSG
DISPLAY 'SUBPGM: ' WS-VALIDATION-MSG
PERFORM 6000-ERROR THRU 6000-ERROR-EXIT
GOBACK
END-IF.
DISPLAY '[TRACE] SUBPGM 2000-VALIDATE all checks passed'.
2000-EXIT.
EXIT.
*> ============================================================
*> 3000-CALCULATE — Perform billing calculation with components
*> ============================================================
3000-CALCULATE SECTION.
3000-START.
DISPLAY '[TRACE] SUBPGM 3000-CALCULATE start'
' A=' LK-A ' B=' LK-B.
*> Step 1: Decompose input A into billing components
*> Input A represents voice minutes (high-order) + msg count
DIVIDE LK-A BY 1000 GIVING WS-CALC-VOICE-MIN
REMAINDER WS-CALC-MSG-COUNT.
*> Input B represents data volume in MB
MOVE LK-B TO WS-CALC-DATA-MB.
DISPLAY '[TRACE] SUBPGM 3000-CALC components: voice='
WS-CALC-VOICE-MIN ' data=' WS-CALC-DATA-MB
' msg=' WS-CALC-MSG-COUNT.
*> Step 2: Look up tier configuration from table
MOVE 1.00 TO WS-COMP-TIER-MULT.
MOVE 'Basic' TO WS-TIER-NAME.
MOVE 5.00 TO WS-TIER-BASE-RATE.
MOVE 5.00 TO WS-TIER-DATA-RATE.
MOVE 0 TO WS-TIER-DISCOUNT.
MOVE 0 TO WS-CALC-SUM.
IF LK-TIER >= 1 AND LK-TIER <= 4
MOVE WS-TIER-MULT(LK-TIER) TO WS-COMP-TIER-MULT
MOVE WS-TIER-DESC(LK-TIER) TO WS-TIER-NAME
MOVE WS-TIER-BASE(LK-TIER) TO WS-TIER-BASE-RATE
MOVE WS-TIER-DATA(LK-TIER) TO WS-TIER-DATA-RATE
MOVE WS-TIER-DISC(LK-TIER) TO WS-TIER-DISCOUNT
DISPLAY '[TRACE] SUBPGM tier=' WS-TIER-NAME
' mult=' WS-COMP-TIER-MULT
' base-rate=' WS-TIER-BASE-RATE
' data-rate=' WS-TIER-DATA-RATE
' disc=' WS-TIER-DISCOUNT '%'
ELSE
MOVE 04 TO LK-ERROR-CODE
DISPLAY 'SUBPGM: Invalid tier — using defaults'
END-IF.
*> Step 3: Calculate voice amount
COMPUTE WS-COMP-VOICE-AMT =
WS-CALC-VOICE-MIN * WS-TIER-BASE-RATE.
DISPLAY '[TRACE] SUBPGM voice amt=' WS-COMP-VOICE-AMT.
*> Step 4: Calculate data amount
COMPUTE WS-COMP-DATA-AMT =
WS-CALC-DATA-MB * WS-TIER-DATA-RATE.
DISPLAY '[TRACE] SUBPGM data amt=' WS-COMP-DATA-AMT.
*> Step 5: Calculate messaging amount (flat 2.00 per msg)
COMPUTE WS-COMP-MSG-AMT =
WS-CALC-MSG-COUNT * 2.00.
DISPLAY '[TRACE] SUBPGM msg amt=' WS-COMP-MSG-AMT.
*> Step 6: Calculate subtotal (voice + data + msg)
COMPUTE WS-COMP-SUBTOTAL =
WS-COMP-VOICE-AMT + WS-COMP-DATA-AMT + WS-COMP-MSG-AMT.
DISPLAY '[TRACE] SUBPGM subtotal=' WS-COMP-SUBTOTAL.
*> Step 7: Apply tier discount
IF WS-TIER-DISCOUNT > 0
COMPUTE WS-COMP-DISCOUNT =
WS-COMP-SUBTOTAL * WS-TIER-DISCOUNT / 100
COMPUTE WS-COMP-FINAL =
WS-COMP-SUBTOTAL - WS-COMP-DISCOUNT
DISPLAY '[TRACE] SUBPGM discount=' WS-COMP-DISCOUNT
' (' WS-TIER-DISCOUNT '%)'
ELSE
MOVE 0 TO WS-COMP-DISCOUNT
MOVE WS-COMP-SUBTOTAL TO WS-COMP-FINAL
END-IF.
*> Step 8: Apply tier multiplier
COMPUTE WS-CALC-MULT = WS-COMP-FINAL * WS-COMP-TIER-MULT.
*> Step 9: Check for overflow
MOVE WS-CALC-MULT TO WS-OVERFLOW-CHECK.
IF WS-OVERFLOW-CHECK > 9999999999
MOVE 05 TO LK-ERROR-CODE
MOVE 98 TO LK-STATUS
MOVE 9999999999 TO WS-CALC-RESULT
DISPLAY 'SUBPGM: OVERFLOW final=' WS-COMP-FINAL
' mult=' WS-COMP-TIER-MULT
PERFORM 6000-ERROR THRU 6000-ERROR-EXIT
GOBACK
END-IF.
*> Step 10: Round and store result
COMPUTE WS-CALC-RESULT ROUNDED = WS-CALC-MULT.
MOVE WS-CALC-RESULT TO LK-RESULT.
*> Step 11: Compute original legacy sum for backward compatibility
COMPUTE WS-CALC-SUM = LK-A + LK-B.
*> Step 12: Set success status
MOVE 00 TO LK-STATUS.
MOVE 00 TO LK-ERROR-CODE.
MOVE 0 TO RETURN-CODE.
*> Step 13: Update statistics
ADD 1 TO WS-STAT-COUNT.
ADD 1 TO WS-STAT-SUCCESS-CNT.
ADD LK-RESULT TO WS-STAT-SUM-VAL.
IF LK-RESULT < WS-STAT-MIN-VAL
MOVE LK-RESULT TO WS-STAT-MIN-VAL
END-IF.
IF LK-RESULT > WS-STAT-MAX-VAL
MOVE LK-RESULT TO WS-STAT-MAX-VAL
END-IF.
COMPUTE WS-STAT-AVG-VAL =
WS-STAT-SUM-VAL / WS-STAT-COUNT.
DISPLAY ' SUBPGM: A=' LK-A ' B=' LK-B
' SUM(legacy)=' WS-CALC-SUM
' TIER=' LK-TIER ' (' WS-TIER-NAME ')'
' MULT=' WS-COMP-TIER-MULT
' DISCOUNT=' WS-TIER-DISCOUNT '%'
' VOICE=' WS-COMP-VOICE-AMT
' DATA=' WS-COMP-DATA-AMT
' MSG=' WS-COMP-MSG-AMT
' RESULT=' LK-RESULT
' CALLS=' WS-LOCAL-COUNT.
3000-EXIT.
EXIT.
*> ============================================================
*> 4000-LOG — Comprehensive audit logging
*> ============================================================
4000-LOG SECTION.
4000-START.
DISPLAY '[TRACE] SUBPGM 4000-LOG call #' WS-CALL-COUNT.
*> Write main call record
MOVE WS-CALL-COUNT TO AC-CALL-NUM.
MOVE LK-A TO AC-A.
MOVE LK-B TO AC-B.
MOVE LK-TIER TO AC-TIER.
MOVE LK-RESULT TO AC-RESULT.
MOVE LK-STATUS TO AC-STATUS.
MOVE LK-ERROR-CODE TO AC-ERR.
WRITE AUDIT-LINE FROM WS-AUDIT-CALL.
*> Write component breakdown
MOVE 'Voice ' TO AD-COMP.
MOVE WS-COMP-VOICE-AMT TO AD-AMT.
WRITE AUDIT-LINE FROM WS-AUDIT-DETAIL.
MOVE 'Data ' TO AD-COMP.
MOVE WS-COMP-DATA-AMT TO AD-AMT.
WRITE AUDIT-LINE FROM WS-AUDIT-DETAIL.
MOVE 'Messaging ' TO AD-COMP.
MOVE WS-COMP-MSG-AMT TO AD-AMT.
WRITE AUDIT-LINE FROM WS-AUDIT-DETAIL.
MOVE 'Discount ' TO AD-COMP.
MOVE WS-COMP-DISCOUNT TO AD-AMT.
WRITE AUDIT-LINE FROM WS-AUDIT-DETAIL.
MOVE 'Final ' TO AD-COMP.
MOVE WS-COMP-FINAL TO AD-AMT.
WRITE AUDIT-LINE FROM WS-AUDIT-DETAIL.
*> Write tier info
MOVE 'Tier Info ' TO AD-COMP.
STRING WS-TIER-NAME ' mult=' WS-COMP-TIER-MULT
INTO AD-COMP.
MOVE 0 TO AD-AMT.
WRITE AUDIT-LINE FROM WS-AUDIT-DETAIL.
4000-EXIT.
EXIT.
*> ============================================================
*> 5000-STATS — Update and optionally report statistics
*> ============================================================
5000-STATS SECTION.
5000-START.
DISPLAY '[TRACE] SUBPGM 5000-STATS call #' WS-CALL-COUNT.
*> Write statistics every 5 calls
IF WS-CALL-COUNT / 5 * 5 = WS-CALL-COUNT
MOVE WS-STAT-MIN-VAL TO AS-MIN
MOVE WS-STAT-MAX-VAL TO AS-MAX
MOVE WS-STAT-AVG-VAL TO AS-AVG
MOVE WS-STAT-COUNT TO AS-CNT
WRITE AUDIT-LINE FROM WS-AUDIT-STATS
MOVE WS-STAT-ERR-COUNT TO AE-COUNT
MOVE WS-STAT-SUCCESS-CNT TO AE-SUCCESS
WRITE AUDIT-LINE FROM WS-AUDIT-ERR-STATS
END-IF.
5000-EXIT.
EXIT.
*> ============================================================
*> 5500-DISCOUNT-CALC — Additional discount stacking logic
*> ============================================================
5500-DISCOUNT-CALC SECTION.
5500-START.
DISPLAY '[TRACE] SUBPGM 5500-DISCOUNT-CALC'
' tier=' LK-TIER.
*> Apply additional volume-based discount
*> If combined voice+data exceeds threshold, extra discount
IF WS-COMP-SUBTOTAL > 10000
COMPUTE WS-COMP-DISCOUNT =
WS-COMP-DISCOUNT +
(WS-COMP-SUBTOTAL * 5 / 100)
DISPLAY '[TRACE] SUBPGM volume discount applied: +5%'
END-IF.
*> If enterprise tier and high data usage, waive data fees
IF LK-TIER = 3 AND WS-CALC-DATA-MB > 500
COMPUTE WS-COMP-DATA-AMT = 0
DISPLAY '[TRACE] SUBPGM enterprise data waiver applied'
END-IF.
*> Recalculate final after additional discounts
COMPUTE WS-COMP-FINAL =
WS-COMP-VOICE-AMT + WS-COMP-DATA-AMT + WS-COMP-MSG-AMT
- WS-COMP-DISCOUNT.
IF WS-COMP-FINAL < 0
MOVE 0 TO WS-COMP-FINAL
END-IF.
DISPLAY '[TRACE] SUBPGM after extra discounts: final='
WS-COMP-FINAL.
5500-EXIT.
EXIT.
*> ============================================================
*> 6000-ERROR — Error handler with error code lookup
*> ============================================================
6000-ERROR SECTION.
6000-START.
ADD 1 TO WS-ERROR-COUNT.
ADD 1 TO WS-STAT-ERR-COUNT.
MOVE WS-ERROR-COUNT TO ED-NUM.
*> Look up error code description
IF LK-ERROR-CODE >= 0 AND LK-ERROR-CODE <= 9
ADD 1 TO LK-ERROR-CODE
MOVE WS-EC-MESSAGE(LK-ERROR-CODE) TO ED-MESSAGE
SUBTRACT 1 FROM LK-ERROR-CODE
ELSE
STRING 'Error code=' LK-ERROR-CODE
' A=' LK-A ' B=' LK-B ' tier=' LK-TIER
INTO ED-MESSAGE
END-IF.
DISPLAY WS-ERROR-DETAIL.
WRITE ERROR-LINE FROM WS-ERROR-DETAIL.
6000-EXIT.
EXIT.
*> ============================================================
*> 7000-CLEANUP — Close files and write final stats
*> ============================================================
7000-CLEANUP SECTION.
7000-START.
DISPLAY '[TRACE] SUBPGM 7000-CLEANUP'
' call #' WS-CALL-COUNT.
*> Write final statistics
MOVE WS-STAT-MIN-VAL TO AS-MIN.
MOVE WS-STAT-MAX-VAL TO AS-MAX.
MOVE WS-STAT-AVG-VAL TO AS-AVG.
MOVE WS-STAT-COUNT TO AS-CNT.
WRITE AUDIT-LINE FROM WS-AUDIT-STATS.
MOVE WS-STAT-ERR-COUNT TO AE-COUNT.
MOVE WS-STAT-SUCCESS-CNT TO AE-SUCCESS.
WRITE AUDIT-LINE FROM WS-AUDIT-ERR-STATS.
WRITE AUDIT-LINE FROM WS-AUDIT-FOOTER.
*> Close files when count >= 15
IF WS-CALL-COUNT >= 15
CLOSE AUDIT-FILE
IF FS-AUDIT NOT = '00' AND NOT = '00'
DISPLAY 'SUBPGM: WARNING closing AUDIT status='
FS-AUDIT
END-IF
CLOSE ERROR-FILE
IF FS-ERROR NOT = '00' AND NOT = '00'
DISPLAY 'SUBPGM: WARNING closing ERROR status='
FS-ERROR
END-IF
DISPLAY '[TRACE] SUBPGM files closed cleanly'
END-IF.
7000-EXIT.
EXIT.
*> ============================================================
*> 8000-REPORT — Summary report generation
*> ============================================================
8000-REPORT SECTION.
8000-START.
DISPLAY '[TRACE] SUBPGM 8000-REPORT call #' WS-CALL-COUNT.
DISPLAY ' SUBPGM CALL SUMMARY:'
DISPLAY ' Total calls : ' WS-STAT-COUNT
DISPLAY ' Successful : ' WS-STAT-SUCCESS-CNT
DISPLAY ' Errors : ' WS-STAT-ERR-COUNT
DISPLAY ' Min result : ' WS-STAT-MIN-VAL
DISPLAY ' Max result : ' WS-STAT-MAX-VAL
DISPLAY ' Avg result : ' WS-STAT-AVG-VAL
DISPLAY ' Sum result : ' WS-STAT-SUM-VAL.
8000-EXIT.
EXIT.
*> ============================================================
*> 9000-EXIT — Return to caller with GOBACK
*> ============================================================
9000-EXIT SECTION.
9000-START.
DISPLAY '[TRACE] SUBPGM 9000-EXIT call #' WS-CALL-COUNT.
*> Call PERFORM to log, update stats, and cleanup
PERFORM 4000-LOG THRU 4000-LOG-EXIT.
PERFORM 5000-STATS THRU 5000-STATS-EXIT.
PERFORM 5500-DISCOUNT-CALC THRU 5500-DISCOUNT-CALC-EXIT.
PERFORM 7000-CLEANUP THRU 7000-CLEANUP-EXIT.
DISPLAY '[TRACE] SUBPGM returning to caller, result='
LK-RESULT ' status=' LK-STATUS.
GOBACK.
9000-EXIT-EXIT.
EXIT.