94400d50d4
作为子目录纳入系统,与核心测试管道协同 Co-Authored-By: Claude <noreply@anthropic.com>
1089 lines
39 KiB
COBOL
1089 lines
39 KiB
COBOL
*> ============================================================
|
|
*> 12-divide-100 : CDR数据100分割 (CDR 100-Split)
|
|
*> Input : FILE-IN.DAT (CDR数据: 100件毎分割)
|
|
*> Output: FILE-OUT-NN (100件毎の分割出力文件: FILE-OUT-01, 02...)
|
|
*> Coverage: S-N005, S-N006, S-N007, S-R001, S-R002
|
|
*>
|
|
*> Extended: Phase 2 — error recovery, hash totals, audit trail,
|
|
*> split statistics, boundary checks, CDR awareness,
|
|
*> header/trailer records, file naming validation.
|
|
*> ============================================================
|
|
IDENTIFICATION DIVISION.
|
|
PROGRAM-ID. Divide100.
|
|
|
|
ENVIRONMENT DIVISION.
|
|
CONFIGURATION SECTION.
|
|
INPUT-OUTPUT SECTION.
|
|
FILE-CONTROL.
|
|
SELECT FILE-IN
|
|
ASSIGN TO WS-IN-FILE
|
|
ORGANIZATION IS LINE SEQUENTIAL
|
|
FILE STATUS IS WS-FILE-STATUS-IN.
|
|
|
|
SELECT FILE-OUT
|
|
ASSIGN TO WS-OUT-FILE
|
|
ORGANIZATION IS LINE SEQUENTIAL
|
|
FILE STATUS IS WS-FILE-STATUS-OUT.
|
|
|
|
SELECT AUDIT-REPORT
|
|
ASSIGN TO "AUDIT-RPT.TXT"
|
|
ORGANIZATION IS LINE SEQUENTIAL
|
|
FILE STATUS IS WS-FILE-STATUS-AUDIT.
|
|
|
|
SELECT SPLIT-STATS
|
|
ASSIGN TO "SPLIT-STATS.TXT"
|
|
ORGANIZATION IS LINE SEQUENTIAL
|
|
FILE STATUS IS WS-FILE-STATUS-STATS.
|
|
|
|
DATA DIVISION.
|
|
FILE SECTION.
|
|
FD FILE-IN.
|
|
01 FILE-IN-REC.
|
|
05 IN-RECORD PIC X(45).
|
|
|
|
FD FILE-OUT.
|
|
01 FILE-OUT-REC.
|
|
05 OUT-RECORD PIC X(45).
|
|
|
|
FD AUDIT-REPORT.
|
|
01 AUDIT-REC PIC X(120).
|
|
|
|
FD SPLIT-STATS.
|
|
01 STATS-REC PIC X(120).
|
|
|
|
WORKING-STORAGE SECTION.
|
|
01 WS-TELECOM-REC.
|
|
COPY "telecom/TEL-INVOICE.cpy".
|
|
|
|
*> CDR record mapping
|
|
01 WS-CDR-REC.
|
|
COPY "telecom/TEL-CDR.cpy".
|
|
|
|
*> File status indicators
|
|
01 WS-FILE-STATUS-IN PIC X(02).
|
|
01 WS-FILE-STATUS-OUT PIC X(02).
|
|
01 WS-FILE-STATUS-AUDIT PIC X(02).
|
|
01 WS-FILE-STATUS-STATS PIC X(02).
|
|
|
|
*> EOF and control flags
|
|
01 WS-STATUS.
|
|
05 WS-EOF-FLAG PIC X VALUE 'N'.
|
|
88 WS-EOF VALUE 'Y' FALSE 'N'.
|
|
05 WS-READ-OK PIC X VALUE 'N'.
|
|
88 WS-READ-SUCCESS VALUE 'Y' FALSE 'N'.
|
|
05 WS-FIRST-RECORD PIC X VALUE 'Y'.
|
|
88 WS-IS-FIRST-RECORD VALUE 'Y' FALSE 'N'.
|
|
|
|
*> Error severity levels
|
|
01 WS-SEVERITY PIC X(07).
|
|
88 WS-SEVERITY-WARNING VALUE 'WARNING'.
|
|
88 WS-SEVERITY-ERROR VALUE 'ERROR'.
|
|
88 WS-SEVERITY-FATAL VALUE 'FATAL'.
|
|
|
|
*> Open retry control
|
|
01 WS-OPEN-RETRY.
|
|
05 WS-OPEN-RETRY-COUNT PIC 9(02) VALUE 0.
|
|
05 WS-OPEN-RETRY-MAX PIC 9(02) VALUE 3.
|
|
05 WS-ALT-SUFFIX PIC X(04).
|
|
88 WS-ALT-NONE VALUE 'NONE'.
|
|
88 WS-ALT-BAK VALUE '.BAK'.
|
|
88 WS-ALT-TMP VALUE '.TMP'.
|
|
|
|
*> File naming validation
|
|
01 WS-FILE-NAME-CHECK.
|
|
05 WS-FILE-NAME-VALID PIC X VALUE 'N'.
|
|
88 WS-NAME-IS-VALID VALUE 'Y' FALSE 'N'.
|
|
05 WS-FILE-NAME-PATTERN PIC X(30).
|
|
05 WS-FILE-NAME-PREFIX PIC X(08) VALUE 'FILE-OUT'.
|
|
05 WS-FILE-NAME-SUFFIX PIC X(04) VALUE '.DAT'.
|
|
05 WS-FILE-NAME-SEQ-BEG PIC 9(02).
|
|
05 WS-FILE-NAME-SEQ-END PIC 9(02).
|
|
|
|
*> Counters and accumulators
|
|
01 WS-COUNTERS.
|
|
05 WS-REC-COUNT PIC 9(05) VALUE 0.
|
|
05 WS-FILE-NUM PIC 9(02) VALUE 0.
|
|
05 WS-DIVISOR PIC 9(03) VALUE 100.
|
|
05 WS-QUOTIENT PIC 9(05).
|
|
05 WS-REMAINDER PIC 9(05).
|
|
05 WS-WRITE-COUNT PIC 9(05) VALUE 0.
|
|
05 WS-READ-COUNT PIC 9(05) VALUE 0.
|
|
|
|
*> Input file path (dynamic for retry support)
|
|
01 WS-IN-FILE PIC X(30).
|
|
|
|
*> Output file path
|
|
01 WS-OUT-FILE PIC X(30).
|
|
01 WS-FILE-NUM-ED PIC 99.
|
|
|
|
*> Display formatting
|
|
01 WS-DISPLAY-COUNT PIC Z(05)9.
|
|
01 WS-DISPLAY-HASH PIC Z(09)9.
|
|
01 WS-DISPLAY-STR.
|
|
05 WS-DISPLAY-STR-TEXT PIC X(50).
|
|
|
|
*> Simulated timestamp for DISPLAY tracing
|
|
01 WS-TIMESTAMP PIC X(21).
|
|
01 WS-TIMESTAMP-OUT PIC X(26).
|
|
|
|
*> Hash temp for byte counting
|
|
01 WS-HASH-TEMP PIC 9(10).
|
|
|
|
*> Hash totals for data integrity
|
|
01 WS-HASH-TOTALS.
|
|
05 WS-HASH-TOTAL-IN PIC 9(10) VALUE 0.
|
|
05 WS-HASH-TOTAL-OUT PIC 9(10) VALUE 0.
|
|
05 WS-HASH-TOTAL-VERIFY PIC 9(10) VALUE 0.
|
|
05 WS-HASH-VERIFIED PIC X VALUE 'N'.
|
|
88 WS-HASH-MATCH VALUE 'Y' FALSE 'N'.
|
|
88 WS-HASH-MISMATCH VALUE 'N'.
|
|
05 WS-HASH-SPLIT OCCURS 99 TIMES.
|
|
10 WS-HASH-SPLIT-VAL PIC 9(10).
|
|
|
|
*> Split statistics
|
|
01 WS-SPLIT-STATS.
|
|
05 WS-SPLIT-REC-COUNT PIC 9(05) VALUE 0.
|
|
05 WS-SPLIT-FILE-TOTAL PIC 9(02) VALUE 0.
|
|
05 WS-SPLIT-MIN-RECS PIC 9(05) VALUE 99999.
|
|
05 WS-SPLIT-MAX-RECS PIC 9(05) VALUE 0.
|
|
05 WS-SPLIT-EMPTY-FLAG PIC X VALUE 'N'.
|
|
88 WS-SPLIT-EMPTY VALUE 'Y' FALSE 'N'.
|
|
05 WS-SPLIT-SINGLE-FLAG PIC X VALUE 'N'.
|
|
88 WS-SPLIT-SINGLE VALUE 'Y' FALSE 'N'.
|
|
|
|
*> Boundary condition checks
|
|
01 WS-BOUNDARY-FLAG.
|
|
05 WS-BOUNDARY-EMPTY PIC X VALUE 'N'.
|
|
88 WS-BOUNDARY-IS-EMPTY VALUE 'Y' FALSE 'N'.
|
|
05 WS-BOUNDARY-EXACT-MULT PIC X VALUE 'N'.
|
|
88 WS-BOUNDARY-IS-EXACT VALUE 'Y' FALSE 'N'.
|
|
05 WS-BOUNDARY-SINGLE-REC PIC X VALUE 'N'.
|
|
88 WS-BOUNDARY-IS-SINGLE VALUE 'Y' FALSE 'N'.
|
|
05 WS-BOUNDARY-TRAILING PIC X VALUE 'N'.
|
|
88 WS-BOUNDARY-HAS-TRAIL VALUE 'Y' FALSE 'N'.
|
|
05 WS-BOUNDARY-MULTIPLIER PIC 9(05).
|
|
|
|
*> Trailing record handling
|
|
01 WS-TRAILER-REC-COUNT PIC 9(05) VALUE 0.
|
|
01 WS-TRAILER-RECORD.
|
|
05 WS-TRAILER-TYPE PIC X(08) VALUE 'TRAILER'.
|
|
05 WS-TRAILER-FILE PIC 9(02).
|
|
05 WS-TRL-REC-COUNT PIC 9(05).
|
|
05 FILLER PIC X(30) VALUE SPACES.
|
|
|
|
*> Header record for split files
|
|
01 WS-HEADER-RECORD.
|
|
05 WS-HDR-TYPE PIC X(08) VALUE 'HEADER'.
|
|
05 WS-HDR-FILE PIC 9(02).
|
|
05 WS-HDR-TIMESTAMP PIC X(12).
|
|
05 WS-HDR-RESERVED PIC X(23).
|
|
05 FILLER PIC X VALUE SPACE.
|
|
|
|
*> CDR-aware split header
|
|
01 WS-CDR-HEADER.
|
|
05 WS-CDR-HDR-TYPE PIC X(08) VALUE 'CDR-HDR'.
|
|
05 WS-CDR-HDR-FILE PIC 9(02).
|
|
05 WS-CDR-HDR-EXPECTED PIC 9(05).
|
|
05 WS-CDR-HDR-RESERVED PIC X(30).
|
|
|
|
*> Audit report variables
|
|
01 WS-AUDIT-LINE PIC X(120).
|
|
01 WS-AUDIT-COUNT PIC 9(05) VALUE 0.
|
|
|
|
*> Batch control totals
|
|
01 WS-BATCH-CTRL.
|
|
05 WS-BATCH-START-TIME PIC 9(08).
|
|
05 WS-BATCH-END-TIME PIC 9(08).
|
|
05 WS-BATCH-TOTAL-FILES PIC 9(02) VALUE 0.
|
|
05 WS-BATCH-TOTAL-RECS PIC 9(05) VALUE 0.
|
|
05 WS-BATCH-ERROR-COUNT PIC 9(03) VALUE 0.
|
|
05 WS-BATCH-WARN-COUNT PIC 9(03) VALUE 0.
|
|
|
|
*> File open retry state
|
|
01 WS-RETRY-STATE.
|
|
05 WS-RETRY-ATTEMPT PIC 9(02) VALUE 0.
|
|
05 WS-RETRY-FILE-NAME PIC X(30).
|
|
05 WS-RETRY-SUCCESS PIC X VALUE 'N'.
|
|
88 WS-RETRY-OK VALUE 'Y' FALSE 'N'.
|
|
|
|
* ============================================================
|
|
* PROCEDURE DIVISION
|
|
* ============================================================
|
|
PROCEDURE DIVISION.
|
|
|
|
MAIN SECTION.
|
|
MAIN-PROCEDURE.
|
|
PERFORM 1000-INIT-SECTION
|
|
PERFORM 2000-OPEN-FILES-SECTION
|
|
PERFORM 3000-PROCESS-SECTION
|
|
PERFORM 4000-REPORT-SECTION
|
|
PERFORM 5000-AUDIT-SECTION
|
|
PERFORM 6000-ERROR-HANDLE-SECTION
|
|
PERFORM 9000-EXIT-SECTION
|
|
STOP RUN.
|
|
|
|
*> ============================================================
|
|
*> 1000-INIT-SECTION — Initialize all working variables
|
|
*> ============================================================
|
|
1000-INIT-SECTION SECTION.
|
|
|
|
1000-INIT.
|
|
DISPLAY " "
|
|
DISPLAY "=== Divide100 — Initialize ==="
|
|
MOVE FUNCTION CURRENT-DATE TO WS-TIMESTAMP
|
|
DISPLAY "[" WS-TIMESTAMP "] Initializing program"
|
|
|
|
*> Zero counters
|
|
MOVE 0 TO WS-REC-COUNT
|
|
MOVE 0 TO WS-FILE-NUM
|
|
MOVE 0 TO WS-READ-COUNT
|
|
MOVE 0 TO WS-WRITE-COUNT
|
|
MOVE 0 TO WS-TRAILER-REC-COUNT
|
|
MOVE 0 TO WS-AUDIT-COUNT
|
|
MOVE 0 TO WS-BATCH-ERROR-COUNT
|
|
MOVE 0 TO WS-BATCH-WARN-COUNT
|
|
MOVE 0 TO WS-OPEN-RETRY-COUNT
|
|
MOVE 0 TO WS-HASH-TOTAL-IN
|
|
MOVE 0 TO WS-HASH-TOTAL-OUT
|
|
|
|
*> Reset boundary flags
|
|
MOVE 'N' TO WS-BOUNDARY-EMPTY
|
|
MOVE 'N' TO WS-BOUNDARY-EXACT-MULT
|
|
MOVE 'N' TO WS-BOUNDARY-SINGLE-REC
|
|
MOVE 'N' TO WS-BOUNDARY-TRAILING
|
|
MOVE 'Y' TO WS-FIRST-RECORD
|
|
|
|
*> Reset retry state
|
|
MOVE 'NONE' TO WS-ALT-SUFFIX
|
|
MOVE 0 TO WS-RETRY-ATTEMPT
|
|
|
|
*> Reset split stats
|
|
MOVE 0 TO WS-SPLIT-REC-COUNT
|
|
MOVE 0 TO WS-SPLIT-FILE-TOTAL
|
|
MOVE 99999 TO WS-SPLIT-MIN-RECS
|
|
MOVE 0 TO WS-SPLIT-MAX-RECS
|
|
MOVE 'N' TO WS-SPLIT-EMPTY-FLAG
|
|
MOVE 'N' TO WS-SPLIT-SINGLE-FLAG
|
|
|
|
DISPLAY "[" WS-TIMESTAMP "] Initialization complete"
|
|
.
|
|
|
|
1000-EXIT.
|
|
EXIT.
|
|
|
|
*> ============================================================
|
|
*> 2000-OPEN-FILES-SECTION — Open input and audit files
|
|
*> ============================================================
|
|
2000-OPEN-FILES-SECTION SECTION.
|
|
|
|
2000-OPEN-FILES.
|
|
DISPLAY "[" WS-TIMESTAMP "] Opening files"
|
|
|
|
*> Open input file with retry logic
|
|
MOVE 0 TO WS-RETRY-ATTEMPT
|
|
MOVE 'N' TO WS-RETRY-SUCCESS
|
|
MOVE "FILE-IN.DAT" TO WS-IN-FILE
|
|
|
|
PERFORM WITH TEST AFTER UNTIL WS-RETRY-OK
|
|
OR WS-RETRY-ATTEMPT >= WS-OPEN-RETRY-MAX
|
|
ADD 1 TO WS-RETRY-ATTEMPT
|
|
OPEN INPUT FILE-IN
|
|
IF WS-FILE-STATUS-IN NOT = '00'
|
|
MOVE 'ERROR' TO WS-SEVERITY
|
|
DISPLAY "[" WS-TIMESTAMP "] "
|
|
"ERROR: FILE-IN open failed "
|
|
"status=" WS-FILE-STATUS-IN
|
|
" attempt=" WS-RETRY-ATTEMPT
|
|
*> Try alternate file name
|
|
IF WS-RETRY-ATTEMPT = 1
|
|
MOVE '.BAK' TO WS-ALT-SUFFIX
|
|
STRING "FILE-IN" WS-ALT-SUFFIX
|
|
DELIMITED BY SIZE
|
|
INTO WS-IN-FILE
|
|
ELSE
|
|
MOVE '.TMP' TO WS-ALT-SUFFIX
|
|
STRING "FILE-IN" WS-ALT-SUFFIX
|
|
DELIMITED BY SIZE
|
|
INTO WS-IN-FILE
|
|
END-IF
|
|
DISPLAY "[" WS-TIMESTAMP "] "
|
|
"Retrying with: " WS-IN-FILE
|
|
ELSE
|
|
MOVE WS-IN-FILE TO WS-RETRY-FILE-NAME
|
|
MOVE 'Y' TO WS-RETRY-SUCCESS
|
|
DISPLAY "[" WS-TIMESTAMP "] "
|
|
"FILE-IN opened: " WS-IN-FILE
|
|
" (attempt " WS-RETRY-ATTEMPT ")"
|
|
END-IF
|
|
END-PERFORM
|
|
|
|
IF NOT WS-RETRY-OK
|
|
MOVE 'FATAL' TO WS-SEVERITY
|
|
DISPLAY "[" WS-TIMESTAMP "] "
|
|
"FATAL: Cannot open FILE-IN after "
|
|
WS-OPEN-RETRY-MAX " attempts"
|
|
ADD 1 TO WS-BATCH-ERROR-COUNT
|
|
PERFORM 9000-EXIT-SECTION
|
|
END-IF
|
|
|
|
*> Open audit report file
|
|
OPEN OUTPUT AUDIT-REPORT
|
|
IF WS-FILE-STATUS-AUDIT NOT = '00'
|
|
MOVE 'ERROR' TO WS-SEVERITY
|
|
DISPLAY "[" WS-TIMESTAMP "] "
|
|
"ERROR: AUDIT-REPORT open failed "
|
|
"status=" WS-FILE-STATUS-AUDIT
|
|
ADD 1 TO WS-BATCH-ERROR-COUNT
|
|
ELSE
|
|
DISPLAY "[" WS-TIMESTAMP "] "
|
|
"AUDIT-REPORT opened successfully"
|
|
MOVE SPACES TO AUDIT-REC
|
|
STRING "*** AUDIT REPORT — Divide100 ***"
|
|
DELIMITED BY SIZE
|
|
INTO AUDIT-REC
|
|
WRITE AUDIT-REC
|
|
ADD 1 TO WS-AUDIT-COUNT
|
|
END-IF
|
|
|
|
*> Open split stats file
|
|
OPEN OUTPUT SPLIT-STATS
|
|
IF WS-FILE-STATUS-STATS NOT = '00'
|
|
MOVE 'ERROR' TO WS-SEVERITY
|
|
DISPLAY "[" WS-TIMESTAMP "] "
|
|
"ERROR: SPLIT-STATS open failed "
|
|
"status=" WS-FILE-STATUS-STATS
|
|
ADD 1 TO WS-BATCH-ERROR-COUNT
|
|
ELSE
|
|
DISPLAY "[" WS-TIMESTAMP "] "
|
|
"SPLIT-STATS opened successfully"
|
|
MOVE SPACES TO STATS-REC
|
|
STRING "*** SPLIT STATISTICS REPORT ***"
|
|
DELIMITED BY SIZE
|
|
INTO STATS-REC
|
|
WRITE STATS-REC
|
|
END-IF
|
|
|
|
*> Capture batch start time
|
|
MOVE FUNCTION CURRENT-DATE TO WS-TIMESTAMP
|
|
.
|
|
|
|
2000-EXIT.
|
|
EXIT.
|
|
|
|
*> ============================================================
|
|
*> 3000-PROCESS-SECTION — Main processing loop
|
|
*> ============================================================
|
|
3000-PROCESS-SECTION SECTION.
|
|
|
|
3000-PROCESS.
|
|
DISPLAY "[" WS-TIMESTAMP "] Starting record processing"
|
|
DISPLAY "=== 100-DIVISION PROCESSING ==="
|
|
DISPLAY "Records per file: " WS-DIVISOR
|
|
|
|
*> Write audit header
|
|
MOVE SPACES TO AUDIT-REC
|
|
STRING "=== 100-DIVISION PROCESSING ==="
|
|
DELIMITED BY SIZE
|
|
INTO AUDIT-REC
|
|
WRITE AUDIT-REC
|
|
ADD 1 TO WS-AUDIT-COUNT
|
|
|
|
MOVE SPACES TO AUDIT-REC
|
|
STRING "Records per file: " WS-DIVISOR
|
|
DELIMITED BY SIZE
|
|
INTO AUDIT-REC
|
|
WRITE AUDIT-REC
|
|
ADD 1 TO WS-AUDIT-COUNT
|
|
|
|
PERFORM VARYING WS-REC-COUNT FROM 1 BY 1
|
|
UNTIL WS-EOF
|
|
READ FILE-IN INTO FILE-IN-REC
|
|
AT END
|
|
SET WS-EOF TO TRUE
|
|
IF WS-IS-FIRST-RECORD
|
|
MOVE 'Y' TO WS-BOUNDARY-EMPTY
|
|
MOVE 'WARNING' TO WS-SEVERITY
|
|
DISPLAY "[" WS-TIMESTAMP "] "
|
|
"WARNING: Input file is empty"
|
|
END-IF
|
|
NOT AT END
|
|
SET WS-READ-SUCCESS TO TRUE
|
|
ADD 1 TO WS-READ-COUNT
|
|
IF WS-IS-FIRST-RECORD
|
|
MOVE 'N' TO WS-FIRST-RECORD
|
|
END-IF
|
|
PERFORM 3100-READ-INPUT-SECTION
|
|
PERFORM 3200-VALIDATE-SECTION
|
|
PERFORM 3300-APPLY-RULES-SECTION
|
|
PERFORM 3400-WRITE-OUTPUT-SECTION
|
|
END-READ
|
|
|
|
IF WS-FILE-STATUS-IN NOT = '00' AND NOT WS-EOF
|
|
MOVE 'ERROR' TO WS-SEVERITY
|
|
DISPLAY "[" WS-TIMESTAMP "] "
|
|
"ERROR: FILE-IN read failed "
|
|
"record=" WS-REC-COUNT
|
|
" status=" WS-FILE-STATUS-IN
|
|
ADD 1 TO WS-BATCH-ERROR-COUNT
|
|
END-IF
|
|
END-PERFORM
|
|
|
|
*> Boundary checks after processing
|
|
IF WS-BOUNDARY-IS-EMPTY
|
|
MOVE SPACES TO AUDIT-REC
|
|
STRING "WARNING: Input file was empty — "
|
|
"no output files created"
|
|
DELIMITED BY SIZE
|
|
INTO AUDIT-REC
|
|
WRITE AUDIT-REC
|
|
ADD 1 TO WS-AUDIT-COUNT
|
|
ELSE
|
|
DIVIDE WS-READ-COUNT BY WS-DIVISOR
|
|
GIVING WS-BOUNDARY-MULTIPLIER
|
|
REMAINDER WS-REMAINDER
|
|
IF WS-REMAINDER = 0
|
|
MOVE 'Y' TO WS-BOUNDARY-EXACT-MULT
|
|
DISPLAY "[" WS-TIMESTAMP "] "
|
|
"NOTE: Exact multiple of divisor — "
|
|
"no trailing records"
|
|
ELSE
|
|
MOVE 'Y' TO WS-BOUNDARY-TRAILING
|
|
MOVE WS-REMAINDER TO WS-TRAILER-REC-COUNT
|
|
DISPLAY "[" WS-TIMESTAMP "] "
|
|
"NOTE: " WS-TRAILER-REC-COUNT
|
|
" trailing record(s) in last file"
|
|
END-IF
|
|
IF WS-READ-COUNT = 1
|
|
MOVE 'Y' TO WS-BOUNDARY-SINGLE-REC
|
|
END-IF
|
|
END-IF
|
|
|
|
*> Close last output file if any were opened
|
|
IF WS-FILE-NUM > 0
|
|
PERFORM WRITE-TRAILER-RECORD
|
|
CLOSE FILE-OUT
|
|
IF WS-FILE-STATUS-OUT NOT = '00'
|
|
MOVE 'ERROR' TO WS-SEVERITY
|
|
DISPLAY "[" WS-TIMESTAMP "] "
|
|
"ERROR: Close failed for "
|
|
WS-OUT-FILE
|
|
" status=" WS-FILE-STATUS-OUT
|
|
ADD 1 TO WS-BATCH-ERROR-COUNT
|
|
ELSE
|
|
DISPLAY "[" WS-TIMESTAMP "] "
|
|
"Closed final file: " WS-OUT-FILE
|
|
END-IF
|
|
END-IF
|
|
|
|
MOVE WS-REC-COUNT TO WS-DISPLAY-COUNT
|
|
DISPLAY " "
|
|
DISPLAY "[" WS-TIMESTAMP "] Total records read: "
|
|
WS-DISPLAY-COUNT
|
|
DISPLAY "[" WS-TIMESTAMP "] Output files created: "
|
|
WS-FILE-NUM
|
|
.
|
|
|
|
3000-EXIT.
|
|
EXIT.
|
|
|
|
*> ============================================================
|
|
*> 3100-READ-INPUT-SECTION — Input record processing
|
|
*> ============================================================
|
|
3100-READ-INPUT-SECTION SECTION.
|
|
|
|
3100-READ-INPUT.
|
|
*> Accumulate hash total (sum of numeric representation
|
|
*> of the input record bytes)
|
|
PERFORM COMPUTE-INPUT-HASH
|
|
|
|
*> Classify record type based on known layouts
|
|
MOVE IN-RECORD TO WS-TELECOM-REC
|
|
MOVE IN-RECORD TO WS-CDR-REC
|
|
|
|
*> Check if record resembles a CDR by CDR-ID pattern
|
|
IF CDR-ID (1:3) = 'CDR'
|
|
DISPLAY "[" WS-TIMESTAMP "] "
|
|
"Record " WS-REC-COUNT
|
|
": CDR record detected: " CDR-ID
|
|
ELSE
|
|
IF INV-ID (1:3) = 'INV'
|
|
DISPLAY "[" WS-TIMESTAMP "] "
|
|
"Record " WS-REC-COUNT
|
|
": Invoice record detected: " INV-ID
|
|
ELSE
|
|
DISPLAY "[" WS-TIMESTAMP "] "
|
|
"Record " WS-REC-COUNT
|
|
": Generic record"
|
|
END-IF
|
|
END-IF
|
|
.
|
|
|
|
3100-EXIT.
|
|
EXIT.
|
|
|
|
*> ============================================================
|
|
*> 3200-VALIDATE-SECTION — Validate input record
|
|
*> ============================================================
|
|
3200-VALIDATE-SECTION SECTION.
|
|
|
|
3200-VALIDATE.
|
|
*> Validate output file naming convention before writing
|
|
IF WS-FILE-NUM > 0
|
|
MOVE WS-OUT-FILE TO WS-FILE-NAME-PATTERN
|
|
IF WS-FILE-NAME-PATTERN (1:8) = WS-FILE-NAME-PREFIX
|
|
MOVE 'Y' TO WS-FILE-NAME-VALID
|
|
ELSE
|
|
MOVE 'N' TO WS-FILE-NAME-VALID
|
|
MOVE 'WARNING' TO WS-SEVERITY
|
|
DISPLAY "[" WS-TIMESTAMP "] "
|
|
"WARNING: Unconventional file name: "
|
|
WS-OUT-FILE
|
|
ADD 1 TO WS-BATCH-WARN-COUNT
|
|
END-IF
|
|
END-IF
|
|
.
|
|
|
|
3200-EXIT.
|
|
EXIT.
|
|
|
|
*> ============================================================
|
|
*> 3300-APPLY-RULES-SECTION — Apply division rules
|
|
*> ============================================================
|
|
3300-APPLY-RULES-SECTION SECTION.
|
|
|
|
3300-APPLY-RULES.
|
|
*> Use DIVIDE to determine file number
|
|
*> === ORIGINAL LOGIC PRESERVED (unaltered) ===
|
|
DIVIDE WS-REC-COUNT BY WS-DIVISOR
|
|
GIVING WS-QUOTIENT REMAINDER WS-REMAINDER
|
|
|
|
*> If remainder = 1, start a new output file
|
|
*> === ORIGINAL LOGIC PRESERVED (unaltered) ===
|
|
IF WS-REMAINDER = 1
|
|
IF WS-FILE-NUM > 0
|
|
PERFORM WRITE-TRAILER-RECORD
|
|
CLOSE FILE-OUT
|
|
IF WS-FILE-STATUS-OUT NOT = '00'
|
|
MOVE 'ERROR' TO WS-SEVERITY
|
|
DISPLAY "[" WS-TIMESTAMP "] "
|
|
"ERROR: Close failed for "
|
|
WS-OUT-FILE
|
|
" status=" WS-FILE-STATUS-OUT
|
|
ADD 1 TO WS-BATCH-ERROR-COUNT
|
|
ELSE
|
|
DISPLAY "[" WS-TIMESTAMP "] "
|
|
"Closed: " WS-OUT-FILE
|
|
END-IF
|
|
END-IF
|
|
ADD 1 TO WS-FILE-NUM
|
|
MOVE WS-FILE-NUM TO WS-FILE-NUM-ED
|
|
STRING "FILE-OUT-" DELIMITED BY SIZE
|
|
WS-FILE-NUM-ED DELIMITED BY SIZE
|
|
".DAT" DELIMITED BY SIZE
|
|
INTO WS-OUT-FILE
|
|
OPEN OUTPUT FILE-OUT
|
|
IF WS-FILE-STATUS-OUT NOT = '00'
|
|
MOVE 'FATAL' TO WS-SEVERITY
|
|
DISPLAY "[" WS-TIMESTAMP "] "
|
|
"FATAL: Cannot open " WS-OUT-FILE
|
|
" status=" WS-FILE-STATUS-OUT
|
|
ADD 1 TO WS-BATCH-ERROR-COUNT
|
|
PERFORM 6000-ERROR-HANDLE-SECTION
|
|
ELSE
|
|
DISPLAY "[" WS-TIMESTAMP "] "
|
|
"Opened: " WS-OUT-FILE
|
|
PERFORM WRITE-HEADER-RECORD
|
|
END-IF
|
|
END-IF
|
|
.
|
|
|
|
3300-EXIT.
|
|
EXIT.
|
|
|
|
*> ============================================================
|
|
*> 3400-WRITE-OUTPUT-SECTION — Write record to output
|
|
*> ============================================================
|
|
3400-WRITE-OUTPUT-SECTION SECTION.
|
|
|
|
3400-WRITE-OUTPUT.
|
|
*> Hash the output record before writing
|
|
PERFORM COMPUTE-OUTPUT-HASH
|
|
|
|
*> Write record to current output file
|
|
*> === ORIGINAL LOGIC PRESERVED (unaltered) ===
|
|
MOVE IN-RECORD TO OUT-RECORD
|
|
WRITE FILE-OUT-REC
|
|
|
|
IF WS-FILE-STATUS-OUT NOT = '00'
|
|
MOVE 'ERROR' TO WS-SEVERITY
|
|
DISPLAY "[" WS-TIMESTAMP "] "
|
|
"ERROR: Write failed for record "
|
|
WS-REC-COUNT
|
|
" status=" WS-FILE-STATUS-OUT
|
|
ADD 1 TO WS-BATCH-ERROR-COUNT
|
|
ELSE
|
|
ADD 1 TO WS-WRITE-COUNT
|
|
ADD 1 TO WS-SPLIT-REC-COUNT
|
|
ADD 1 TO WS-HASH-SPLIT-VAL (WS-FILE-NUM)
|
|
END-IF
|
|
.
|
|
|
|
3400-EXIT.
|
|
EXIT.
|
|
|
|
*> ============================================================
|
|
*> 4000-REPORT-SECTION — Generate split statistics
|
|
*> ============================================================
|
|
4000-REPORT-SECTION SECTION.
|
|
|
|
4000-REPORT.
|
|
DISPLAY " "
|
|
DISPLAY "[" WS-TIMESTAMP "] === Split Statistics ==="
|
|
DISPLAY "Total input records: " WS-READ-COUNT
|
|
DISPLAY "Total output records: " WS-WRITE-COUNT
|
|
DISPLAY "Output files created: " WS-FILE-NUM
|
|
|
|
*> Populate split stats
|
|
MOVE WS-FILE-NUM TO WS-SPLIT-FILE-TOTAL
|
|
IF WS-READ-COUNT = 0
|
|
MOVE 'Y' TO WS-SPLIT-EMPTY-FLAG
|
|
END-IF
|
|
IF WS-READ-COUNT = 1
|
|
MOVE 'Y' TO WS-SPLIT-SINGLE-FLAG
|
|
END-IF
|
|
|
|
*> Build min/max split sizes
|
|
PERFORM VARYING WS-FILE-NUM-ED FROM 1 BY 1
|
|
UNTIL WS-FILE-NUM-ED > WS-FILE-NUM
|
|
IF WS-HASH-SPLIT-VAL (WS-FILE-NUM-ED)
|
|
< WS-SPLIT-MIN-RECS
|
|
MOVE WS-HASH-SPLIT-VAL (WS-FILE-NUM-ED)
|
|
TO WS-SPLIT-MIN-RECS
|
|
END-IF
|
|
IF WS-HASH-SPLIT-VAL (WS-FILE-NUM-ED)
|
|
> WS-SPLIT-MAX-RECS
|
|
MOVE WS-HASH-SPLIT-VAL (WS-FILE-NUM-ED)
|
|
TO WS-SPLIT-MAX-RECS
|
|
END-IF
|
|
END-PERFORM
|
|
|
|
DISPLAY "Min records per split: " WS-SPLIT-MIN-RECS
|
|
DISPLAY "Max records per split: " WS-SPLIT-MAX-RECS
|
|
|
|
*> Write detailed stats to SPLIT-STATS file
|
|
MOVE SPACES TO STATS-REC
|
|
STRING "SPLIT STATS: files=" WS-FILE-NUM
|
|
" total-records=" WS-READ-COUNT
|
|
" min=" WS-SPLIT-MIN-RECS
|
|
" max=" WS-SPLIT-MAX-RECS
|
|
DELIMITED BY SIZE
|
|
INTO STATS-REC
|
|
WRITE STATS-REC
|
|
|
|
*> Sequential output file inventory
|
|
MOVE SPACES TO STATS-REC
|
|
STRING "=== Split File Inventory ==="
|
|
DELIMITED BY SIZE
|
|
INTO STATS-REC
|
|
WRITE STATS-REC
|
|
|
|
PERFORM VARYING WS-FILE-NUM-ED FROM 1 BY 1
|
|
UNTIL WS-FILE-NUM-ED > WS-FILE-NUM
|
|
MOVE SPACES TO STATS-REC
|
|
STRING "FILE-OUT-"
|
|
WS-FILE-NUM-ED
|
|
".DAT: "
|
|
WS-HASH-SPLIT-VAL (WS-FILE-NUM-ED)
|
|
" records"
|
|
DELIMITED BY SIZE
|
|
INTO STATS-REC
|
|
WRITE STATS-REC
|
|
END-PERFORM
|
|
|
|
*> Boundary condition summary
|
|
MOVE SPACES TO STATS-REC
|
|
STRING "Boundary: EMPTY=" WS-BOUNDARY-EMPTY
|
|
" EXACT-MULT=" WS-BOUNDARY-EXACT-MULT
|
|
" SINGLE=" WS-BOUNDARY-SINGLE-REC
|
|
" TRAILING=" WS-BOUNDARY-TRAILING
|
|
" TRAIL-COUNT=" WS-TRAILER-REC-COUNT
|
|
DELIMITED BY SIZE
|
|
INTO STATS-REC
|
|
WRITE STATS-REC
|
|
.
|
|
|
|
4000-EXIT.
|
|
EXIT.
|
|
|
|
*> ============================================================
|
|
*> 5000-AUDIT-SECTION — Hash verification and audit trail
|
|
*> ============================================================
|
|
5000-AUDIT-SECTION SECTION.
|
|
|
|
5000-AUDIT.
|
|
DISPLAY " "
|
|
DISPLAY "[" WS-TIMESTAMP "] === Audit Trail ==="
|
|
|
|
*> Display hash totals
|
|
MOVE WS-HASH-TOTAL-IN TO WS-DISPLAY-HASH
|
|
DISPLAY "Hash total (input): " WS-DISPLAY-HASH
|
|
|
|
MOVE WS-HASH-TOTAL-OUT TO WS-DISPLAY-HASH
|
|
DISPLAY "Hash total (output): " WS-DISPLAY-HASH
|
|
|
|
*> Verify hash totals: input hash must equal sum of
|
|
*> all split file hashes
|
|
MOVE 0 TO WS-HASH-TOTAL-VERIFY
|
|
PERFORM VARYING WS-FILE-NUM-ED FROM 1 BY 1
|
|
UNTIL WS-FILE-NUM-ED > WS-FILE-NUM
|
|
ADD WS-HASH-SPLIT-VAL (WS-FILE-NUM-ED)
|
|
TO WS-HASH-TOTAL-VERIFY
|
|
END-PERFORM
|
|
|
|
IF WS-HASH-TOTAL-IN = WS-HASH-TOTAL-VERIFY
|
|
MOVE 'Y' TO WS-HASH-VERIFIED
|
|
DISPLAY "[" WS-TIMESTAMP "] "
|
|
"PASS: Hash total verified OK"
|
|
ELSE
|
|
MOVE 'N' TO WS-HASH-VERIFIED
|
|
MOVE 'ERROR' TO WS-SEVERITY
|
|
DISPLAY "[" WS-TIMESTAMP "] "
|
|
"FAIL: Hash total mismatch!"
|
|
DISPLAY " Input hash: " WS-HASH-TOTAL-IN
|
|
DISPLAY " Sum of splits: " WS-HASH-TOTAL-VERIFY
|
|
ADD 1 TO WS-BATCH-ERROR-COUNT
|
|
END-IF
|
|
|
|
*> Verify output hash matches input hash
|
|
IF WS-HASH-TOTAL-IN NOT = WS-HASH-TOTAL-OUT
|
|
MOVE 'ERROR' TO WS-SEVERITY
|
|
DISPLAY "[" WS-TIMESTAMP "] "
|
|
"FAIL: Output hash != Input hash!"
|
|
ADD 1 TO WS-BATCH-ERROR-COUNT
|
|
ELSE
|
|
DISPLAY "[" WS-TIMESTAMP "] "
|
|
"PASS: Output hash matches input hash"
|
|
END-IF
|
|
|
|
*> Write final audit records
|
|
MOVE SPACES TO AUDIT-REC
|
|
STRING "=== Audit Summary ==="
|
|
DELIMITED BY SIZE
|
|
INTO AUDIT-REC
|
|
WRITE AUDIT-REC
|
|
ADD 1 TO WS-AUDIT-COUNT
|
|
|
|
MOVE SPACES TO AUDIT-REC
|
|
STRING "Total input records: " WS-READ-COUNT
|
|
DELIMITED BY SIZE
|
|
INTO AUDIT-REC
|
|
WRITE AUDIT-REC
|
|
ADD 1 TO WS-AUDIT-COUNT
|
|
|
|
MOVE SPACES TO AUDIT-REC
|
|
STRING "Total output records: " WS-WRITE-COUNT
|
|
DELIMITED BY SIZE
|
|
INTO AUDIT-REC
|
|
WRITE AUDIT-REC
|
|
ADD 1 TO WS-AUDIT-COUNT
|
|
|
|
MOVE SPACES TO AUDIT-REC
|
|
STRING "Output files created: " WS-FILE-NUM
|
|
DELIMITED BY SIZE
|
|
INTO AUDIT-REC
|
|
WRITE AUDIT-REC
|
|
ADD 1 TO WS-AUDIT-COUNT
|
|
|
|
MOVE SPACES TO AUDIT-REC
|
|
STRING "Hash total (input): " WS-HASH-TOTAL-IN
|
|
DELIMITED BY SIZE
|
|
INTO AUDIT-REC
|
|
WRITE AUDIT-REC
|
|
ADD 1 TO WS-AUDIT-COUNT
|
|
|
|
MOVE SPACES TO AUDIT-REC
|
|
STRING "Hash total (output): " WS-HASH-TOTAL-OUT
|
|
DELIMITED BY SIZE
|
|
INTO AUDIT-REC
|
|
WRITE AUDIT-REC
|
|
ADD 1 TO WS-AUDIT-COUNT
|
|
|
|
IF WS-HASH-MATCH
|
|
MOVE SPACES TO AUDIT-REC
|
|
STRING "Hash verification: PASS"
|
|
DELIMITED BY SIZE
|
|
INTO AUDIT-REC
|
|
WRITE AUDIT-REC
|
|
ADD 1 TO WS-AUDIT-COUNT
|
|
ELSE
|
|
MOVE SPACES TO AUDIT-REC
|
|
STRING "Hash verification: FAIL"
|
|
DELIMITED BY SIZE
|
|
INTO AUDIT-REC
|
|
WRITE AUDIT-REC
|
|
ADD 1 TO WS-AUDIT-COUNT
|
|
END-IF
|
|
|
|
MOVE SPACES TO AUDIT-REC
|
|
STRING "Error count: " WS-BATCH-ERROR-COUNT
|
|
" Warning count: " WS-BATCH-WARN-COUNT
|
|
DELIMITED BY SIZE
|
|
INTO AUDIT-REC
|
|
WRITE AUDIT-REC
|
|
ADD 1 TO WS-AUDIT-COUNT
|
|
|
|
*> Log batch completion
|
|
MOVE FUNCTION CURRENT-DATE TO WS-TIMESTAMP
|
|
MOVE SPACES TO AUDIT-REC
|
|
STRING "Batch completed at: " WS-TIMESTAMP
|
|
DELIMITED BY SIZE
|
|
INTO AUDIT-REC
|
|
WRITE AUDIT-REC
|
|
ADD 1 TO WS-AUDIT-COUNT
|
|
|
|
DISPLAY "[" WS-TIMESTAMP "] "
|
|
"Audit report written: " WS-AUDIT-COUNT " lines"
|
|
.
|
|
|
|
5000-EXIT.
|
|
EXIT.
|
|
|
|
*> ============================================================
|
|
*> 6000-ERROR-HANDLE-SECTION — Central error handler
|
|
*> ============================================================
|
|
6000-ERROR-HANDLE-SECTION SECTION.
|
|
|
|
6000-ERROR-HANDLE.
|
|
DISPLAY "[" WS-TIMESTAMP "] "
|
|
"*** ERROR HANDLER INVOKED ***"
|
|
|
|
EVALUATE TRUE
|
|
WHEN WS-SEVERITY-FATAL
|
|
DISPLAY "[" WS-TIMESTAMP "] "
|
|
"FATAL: Aborting program"
|
|
MOVE SPACES TO AUDIT-REC
|
|
STRING "FATAL ERROR — Batch aborted"
|
|
DELIMITED BY SIZE
|
|
INTO AUDIT-REC
|
|
WRITE AUDIT-REC
|
|
ADD 1 TO WS-AUDIT-COUNT
|
|
PERFORM 9000-EXIT-SECTION
|
|
|
|
WHEN WS-SEVERITY-ERROR
|
|
DISPLAY "[" WS-TIMESTAMP "] "
|
|
"ERROR: Continuing with error"
|
|
MOVE SPACES TO AUDIT-REC
|
|
STRING "ERROR: Continuing — "
|
|
"error count=" WS-BATCH-ERROR-COUNT
|
|
DELIMITED BY SIZE
|
|
INTO AUDIT-REC
|
|
WRITE AUDIT-REC
|
|
ADD 1 TO WS-AUDIT-COUNT
|
|
|
|
WHEN WS-SEVERITY-WARNING
|
|
DISPLAY "[" WS-TIMESTAMP "] "
|
|
"WARNING: Non-critical issue"
|
|
MOVE SPACES TO AUDIT-REC
|
|
STRING "WARNING issued — "
|
|
"warn count=" WS-BATCH-WARN-COUNT
|
|
DELIMITED BY SIZE
|
|
INTO AUDIT-REC
|
|
WRITE AUDIT-REC
|
|
ADD 1 TO WS-AUDIT-COUNT
|
|
|
|
WHEN OTHER
|
|
CONTINUE
|
|
END-EVALUATE
|
|
.
|
|
|
|
6000-EXIT.
|
|
EXIT.
|
|
|
|
*> ============================================================
|
|
*> 9000-EXIT-SECTION — Program cleanup and exit
|
|
*> ============================================================
|
|
9000-EXIT-SECTION SECTION.
|
|
|
|
9000-EXIT.
|
|
DISPLAY " "
|
|
DISPLAY "[" WS-TIMESTAMP "] === Program Termination ==="
|
|
|
|
*> Close any open files safely
|
|
CLOSE FILE-IN
|
|
IF WS-FILE-STATUS-IN NOT = '00'
|
|
DISPLAY "[" WS-TIMESTAMP "] "
|
|
"NOTE: FILE-IN close status="
|
|
WS-FILE-STATUS-IN
|
|
END-IF
|
|
|
|
CLOSE AUDIT-REPORT
|
|
IF WS-FILE-STATUS-AUDIT NOT = '00'
|
|
DISPLAY "[" WS-TIMESTAMP "] "
|
|
"NOTE: AUDIT-REPORT close status="
|
|
WS-FILE-STATUS-AUDIT
|
|
END-IF
|
|
|
|
CLOSE SPLIT-STATS
|
|
IF WS-FILE-STATUS-STATS NOT = '00'
|
|
DISPLAY "[" WS-TIMESTAMP "] "
|
|
"NOTE: SPLIT-STATS close status="
|
|
WS-FILE-STATUS-STATS
|
|
END-IF
|
|
|
|
*> Final summary display
|
|
MOVE WS-REC-COUNT TO WS-DISPLAY-COUNT
|
|
DISPLAY " "
|
|
DISPLAY "=== FINAL SUMMARY ==="
|
|
DISPLAY "Total records read: " WS-DISPLAY-COUNT
|
|
DISPLAY "Output files created: " WS-FILE-NUM
|
|
DISPLAY "Errors: " WS-BATCH-ERROR-COUNT
|
|
DISPLAY "Warnings: " WS-BATCH-WARN-COUNT
|
|
|
|
IF WS-HASH-MATCH
|
|
DISPLAY "Hash integrity: PASS"
|
|
ELSE
|
|
DISPLAY "Hash integrity: FAIL"
|
|
END-IF
|
|
|
|
DISPLAY " "
|
|
DISPLAY "=== Divide100 ended ==="
|
|
STOP RUN
|
|
.
|
|
|
|
*> ============================================================
|
|
*> WRITE-HEADER-RECORD — Write header record to split file
|
|
*> ============================================================
|
|
WRITE-HEADER-RECORD SECTION.
|
|
|
|
WRITE-HDR.
|
|
*> Write standard header
|
|
MOVE SPACES TO WS-HEADER-RECORD
|
|
MOVE 'HEADER' TO WS-HDR-TYPE
|
|
MOVE WS-FILE-NUM TO WS-HDR-FILE
|
|
MOVE FUNCTION CURRENT-DATE TO WS-TIMESTAMP
|
|
MOVE WS-TIMESTAMP (1:12) TO WS-HDR-TIMESTAMP
|
|
MOVE WS-HEADER-RECORD TO OUT-RECORD
|
|
WRITE FILE-OUT-REC
|
|
IF WS-FILE-STATUS-OUT = '00'
|
|
ADD 1 TO WS-WRITE-COUNT
|
|
ADD 1 TO WS-HASH-SPLIT-VAL (WS-FILE-NUM)
|
|
DISPLAY "[" WS-TIMESTAMP "] "
|
|
"Header written to " WS-OUT-FILE
|
|
ELSE
|
|
MOVE 'WARNING' TO WS-SEVERITY
|
|
DISPLAY "[" WS-TIMESTAMP "] "
|
|
"WARNING: Header write failed for "
|
|
WS-OUT-FILE
|
|
ADD 1 TO WS-BATCH-WARN-COUNT
|
|
END-IF
|
|
|
|
*> Write CDR-aware header (second header line with metadata)
|
|
MOVE SPACES TO WS-CDR-HEADER
|
|
MOVE 'CDR-HDR' TO WS-CDR-HDR-TYPE
|
|
MOVE WS-FILE-NUM TO WS-CDR-HDR-FILE
|
|
MOVE 100 TO WS-CDR-HDR-EXPECTED
|
|
MOVE WS-CDR-HEADER TO OUT-RECORD
|
|
WRITE FILE-OUT-REC
|
|
IF WS-FILE-STATUS-OUT = '00'
|
|
ADD 1 TO WS-WRITE-COUNT
|
|
ADD 1 TO WS-HASH-SPLIT-VAL (WS-FILE-NUM)
|
|
ELSE
|
|
MOVE 'WARNING' TO WS-SEVERITY
|
|
DISPLAY "[" WS-TIMESTAMP "] "
|
|
"WARNING: CDR header write failed for "
|
|
WS-OUT-FILE
|
|
ADD 1 TO WS-BATCH-WARN-COUNT
|
|
END-IF
|
|
.
|
|
|
|
WRITE-HDR-EXIT.
|
|
EXIT.
|
|
|
|
*> ============================================================
|
|
*> WRITE-TRAILER-RECORD — Write trailer to closing split file
|
|
*> ============================================================
|
|
WRITE-TRAILER-RECORD SECTION.
|
|
|
|
WRITE-TRL.
|
|
MOVE SPACES TO WS-TRAILER-RECORD
|
|
MOVE 'TRAILER' TO WS-TRAILER-TYPE
|
|
MOVE WS-FILE-NUM TO WS-TRAILER-FILE
|
|
*> Count = current split count minus header records
|
|
*> (we wrote 2 header records per file)
|
|
IF WS-HASH-SPLIT-VAL (WS-FILE-NUM) > 2
|
|
COMPUTE WS-TRL-REC-COUNT =
|
|
WS-HASH-SPLIT-VAL (WS-FILE-NUM) - 2
|
|
ELSE
|
|
MOVE 0 TO WS-TRL-REC-COUNT
|
|
END-IF
|
|
MOVE WS-TRAILER-RECORD TO OUT-RECORD
|
|
WRITE FILE-OUT-REC
|
|
IF WS-FILE-STATUS-OUT = '00'
|
|
ADD 1 TO WS-WRITE-COUNT
|
|
ADD 1 TO WS-HASH-SPLIT-VAL (WS-FILE-NUM)
|
|
DISPLAY "[" WS-TIMESTAMP "] "
|
|
"Trailer written to " WS-OUT-FILE
|
|
" count=" WS-TRL-REC-COUNT
|
|
ELSE
|
|
MOVE 'WARNING' TO WS-SEVERITY
|
|
DISPLAY "[" WS-TIMESTAMP "] "
|
|
"WARNING: Trailer write failed for "
|
|
WS-OUT-FILE
|
|
ADD 1 TO WS-BATCH-WARN-COUNT
|
|
END-IF
|
|
.
|
|
|
|
WRITE-TRL-EXIT.
|
|
EXIT.
|
|
|
|
*> ============================================================
|
|
*> WRITE-AUDIT-LINE — Write one line to audit report
|
|
*> ============================================================
|
|
WRITE-AUDIT-LINE SECTION.
|
|
|
|
WRITE-AUDIT.
|
|
MOVE WS-AUDIT-LINE TO AUDIT-REC
|
|
WRITE AUDIT-REC
|
|
IF WS-FILE-STATUS-AUDIT = '00'
|
|
ADD 1 TO WS-AUDIT-COUNT
|
|
ELSE
|
|
DISPLAY "[" WS-TIMESTAMP "] "
|
|
"ERROR writing audit record"
|
|
END-IF
|
|
.
|
|
|
|
WRITE-AUDIT-EXIT.
|
|
EXIT.
|
|
|
|
*> ============================================================
|
|
*> COMPUTE-INPUT-HASH — Accumulate input hash total
|
|
*> ============================================================
|
|
COMPUTE-INPUT-HASH SECTION.
|
|
|
|
COMP-HASH-IN.
|
|
*> Simple hash: sum the numeric values of each byte
|
|
MOVE 0 TO WS-HASH-TEMP
|
|
INSPECT IN-RECORD TALLYING WS-HASH-TEMP
|
|
FOR CHARACTERS BEFORE INITIAL SPACE
|
|
ADD WS-HASH-TEMP TO WS-HASH-TOTAL-IN
|
|
.
|
|
|
|
COMP-HASH-IN-EXIT.
|
|
EXIT.
|
|
|
|
*> ============================================================
|
|
*> COMPUTE-OUTPUT-HASH — Accumulate output hash total
|
|
*> ============================================================
|
|
COMPUTE-OUTPUT-HASH SECTION.
|
|
|
|
COMP-HASH-OUT.
|
|
*> Simple hash: sum the numeric values of each byte
|
|
MOVE 0 TO WS-HASH-TEMP
|
|
INSPECT OUT-RECORD TALLYING WS-HASH-TEMP
|
|
FOR CHARACTERS BEFORE INITIAL SPACE
|
|
ADD WS-HASH-TEMP TO WS-HASH-TOTAL-OUT
|
|
.
|
|
|
|
COMP-HASH-OUT-EXIT.
|
|
EXIT.
|