IDENTIFICATION DIVISION. PROGRAM-ID. Main35Merge. *> ============================================================ *> 35-merge : 多源CDR合并 (Multi-Source CDR Merge) *> Input : merge-input1.dat (BSS-A CDR) *> merge-input2.dat (BSS-B CDR) *> merge-input3.dat (BSS-C CDR) *> merge-input4.dat (BSS-D CDR - enhanced) *> merge-input5.dat (BSS-E CDR - enhanced) *> merge-input6.dat (BSS-F CDR - enhanced) *> Output: merge-output.dat (統合CDR) *> Report: merge-report.txt (合并处理报告) *> Audit : merge-audit.txt (审计跟踪) *> Stats : merge-stats.txt (合并统计) *> Coverage: MR-N001~N009, MR-A001 *> ============================================================ *> Multi-source CDR MERGE for telecom billing mediation *> Tests: 2-file merge, 3-file merge, duplicate keys, *> OUTPUT PROCEDURE, unsorted input handling, *> source tagging, dedup logic, conflict resolution, *> source validation, merge statistics ENVIRONMENT DIVISION. CONFIGURATION SECTION. INPUT-OUTPUT SECTION. FILE-CONTROL. SELECT FILE-IN1 ASSIGN TO "merge-input1.dat" ORGANIZATION IS LINE SEQUENTIAL FILE STATUS IS FS-IN1. SELECT FILE-IN2 ASSIGN TO "merge-input2.dat" ORGANIZATION IS LINE SEQUENTIAL FILE STATUS IS FS-IN2. SELECT FILE-IN3 ASSIGN TO "merge-input3.dat" ORGANIZATION IS LINE SEQUENTIAL FILE STATUS IS FS-IN3. SELECT FILE-OUT ASSIGN TO "merge-output.dat" ORGANIZATION IS LINE SEQUENTIAL FILE STATUS IS FS-OUT. SELECT FILE-WORK ASSIGN TO "merge-work.tmp" FILE STATUS IS FS-WORK. SELECT FILE-REPORT ASSIGN TO "merge-report.txt" ORGANIZATION IS LINE SEQUENTIAL FILE STATUS IS FS-REPORT. SELECT FILE-AUDIT ASSIGN TO "merge-audit.txt" ORGANIZATION IS LINE SEQUENTIAL FILE STATUS IS FS-AUDIT. SELECT FILE-STATS ASSIGN TO "merge-stats.txt" ORGANIZATION IS LINE SEQUENTIAL FILE STATUS IS FS-STATS. *> Enhanced input files for source-tagged merge SELECT FILE-IN4 ASSIGN TO "merge-input4.dat" ORGANIZATION IS LINE SEQUENTIAL FILE STATUS IS FS-IN4. SELECT FILE-IN5 ASSIGN TO "merge-input5.dat" ORGANIZATION IS LINE SEQUENTIAL FILE STATUS IS FS-IN5. SELECT FILE-IN6 ASSIGN TO "merge-input6.dat" ORGANIZATION IS LINE SEQUENTIAL FILE STATUS IS FS-IN6. *> Enhanced work file with source tagging SELECT FILE-WORK2 ASSIGN TO "merge-work2.tmp" FILE STATUS IS FS-WORK2. DATA DIVISION. FILE SECTION. FD FILE-IN1. 01 IN1-REC. 05 IN1-KEY PIC X(10). 05 IN1-DATA PIC X(20). 05 IN1-VALUE PIC 9(05). FD FILE-IN2. 01 IN2-REC. 05 IN2-KEY PIC X(10). 05 IN2-DATA PIC X(20). 05 IN2-VALUE PIC 9(05). FD FILE-IN3. 01 IN3-REC. 05 IN3-KEY PIC X(10). 05 IN3-DATA PIC X(20). 05 IN3-VALUE PIC 9(05). FD FILE-OUT. 01 OUT-REC. 05 OUT-KEY PIC X(10). 05 OUT-DATA PIC X(20). 05 OUT-VALUE PIC 9(05). SD FILE-WORK. 01 WORK-REC. 05 WR-KEY PIC X(10). 05 WR-DATA PIC X(20). 05 WR-VALUE PIC 9(05). FD FILE-REPORT. 01 REPORT-REC PIC X(80). FD FILE-AUDIT. 01 AUDIT-REC PIC X(80). FD FILE-STATS. 01 STATS-REC PIC X(80). *> Enhanced input files with source tag FD FILE-IN4. 01 IN4-REC. 05 IN4-KEY PIC X(10). 05 IN4-DATA PIC X(20). 05 IN4-VALUE PIC 9(05). 05 IN4-SOURCE PIC X(05). 05 IN4-TIMESTAMP PIC 9(08). FD FILE-IN5. 01 IN5-REC. 05 IN5-KEY PIC X(10). 05 IN5-DATA PIC X(20). 05 IN5-VALUE PIC 9(05). 05 IN5-SOURCE PIC X(05). 05 IN5-TIMESTAMP PIC 9(08). FD FILE-IN6. 01 IN6-REC. 05 IN6-KEY PIC X(10). 05 IN6-DATA PIC X(20). 05 IN6-VALUE PIC 9(05). 05 IN6-SOURCE PIC X(05). 05 IN6-TIMESTAMP PIC 9(08). *> Enhanced work file with source tagging SD FILE-WORK2. 01 WORK2-REC. 05 W2R-KEY PIC X(10). 05 W2R-DATA PIC X(20). 05 W2R-VALUE PIC 9(05). 05 W2R-SOURCE PIC X(05). 05 W2R-TIMESTAMP PIC 9(08). WORKING-STORAGE SECTION. 01 WS-TELECOM-REC. COPY "telecom/TEL-CDR.cpy". 01 WS-EOF PIC X(01) VALUE "N". 88 WS-EOF-Y VALUE "Y". 01 WS-RECORD-COUNT PIC 9(02) VALUE 0. 01 WS-TOTAL-VALUE PIC 9(07) VALUE 0. 01 WS-MERGE-SOURCE PIC X(05). 01 WS-DETAIL-LINE. 05 DL-KEY PIC X(10). 05 FILLER PIC X(02) VALUE SPACES. 05 DL-DATA PIC X(20). 05 FILLER PIC X(02) VALUE SPACES. 05 DL-VALUE PIC Z(9)9. 05 FILLER PIC X(04) VALUE SPACES. 05 DL-SOURCE PIC X(05). 01 WS-HEADER-LINE. 05 FILLER PIC X(10) VALUE "KEY ". 05 FILLER PIC X(22) VALUE "DATA ". 05 FILLER PIC X(07) VALUE "VALUE ". 05 FILLER PIC X(05) VALUE "SRC ". *> Test data for Input 1 (BSS System A CDRs, sorted ascending) 01 TEST1-DATA. 05 FILLER PIC X(35) VALUE "CDRA00000113800138001 00100". 05 FILLER PIC X(35) VALUE "CDRB00000113900139001 00200". 05 FILLER PIC X(35) VALUE "CDRD00000113700137001 00400". 01 TEST1-REDEF REDEFINES TEST1-DATA. 05 T1-ENTRY OCCURS 3 TIMES. 10 T1-KEY PIC X(10). 10 T1-DATA PIC X(20). 10 T1-VALUE PIC 9(05). *> Test data for Input 2 (BSS System B CDRs, sorted ascending) 01 TEST2-DATA. 05 FILLER PIC X(35) VALUE "CDRA00000213600136001 00150". 05 FILLER PIC X(35) VALUE "CDRC00000113500135001 00300". 05 FILLER PIC X(35) VALUE "CDRE00000113400134001 00500". 01 TEST2-REDEF REDEFINES TEST2-DATA. 05 T2-ENTRY OCCURS 3 TIMES. 10 T2-KEY PIC X(10). 10 T2-DATA PIC X(20). 10 T2-VALUE PIC 9(05). *> Test data for Input 3 (BSS System C CDRs, sorted ascending) 01 TEST3-DATA. 05 FILLER PIC X(35) VALUE "CDRA00000313300133001 00175". 05 FILLER PIC X(35) VALUE "CDRB00000213200132001 00250". 05 FILLER PIC X(35) VALUE "CDRF00000113100131001 00600". 01 TEST3-REDEF REDEFINES TEST3-DATA. 05 T3-ENTRY OCCURS 3 TIMES. 10 T3-KEY PIC X(10). 10 T3-DATA PIC X(20). 10 T3-VALUE PIC 9(05). 01 IDX PIC 9(02). *> ============================================================ *> New WS fields for enhanced merge processing *> ============================================================ *> FILE STATUS fields 01 FS-IN1 PIC X(02). 88 FS-IN1-OK VALUE "00". 88 FS-IN1-EOF VALUE "10". 01 FS-IN2 PIC X(02). 88 FS-IN2-OK VALUE "00". 01 FS-IN3 PIC X(02). 88 FS-IN3-OK VALUE "00". 01 FS-OUT PIC X(02). 88 FS-OUT-OK VALUE "00". 01 FS-WORK PIC X(02). 01 FS-REPORT PIC X(02). 88 FS-REPORT-OK VALUE "00". 01 FS-AUDIT PIC X(02). 88 FS-AUDIT-OK VALUE "00". 01 FS-STATS PIC X(02). 88 FS-STATS-OK VALUE "00". 01 FS-IN4 PIC X(02). 88 FS-IN4-OK VALUE "00". 01 FS-IN5 PIC X(02). 88 FS-IN5-OK VALUE "00". 01 FS-IN6 PIC X(02). 88 FS-IN6-OK VALUE "00". 01 FS-WORK2 PIC X(02). *> Current timestamp 01 WS-CURRENT-DATE-TIME. 05 WS-CDT-DATE PIC 9(08). 05 WS-CDT-TIME PIC 9(06). 05 WS-CDT-MS PIC 9(02). 05 WS-CDT-OFFSET PIC 9(04). 05 WS-CDT-SIGN PIC X(01). *> Audit message buffer 01 WS-AUDIT-MESSAGE PIC X(55). *> Audit entry 01 WS-AUDIT-LINE. 05 FILLER PIC X(01) VALUE SPACE. 05 WS-AL-DATE PIC 9(08). 05 FILLER PIC X(01) VALUE SPACE. 05 WS-AL-TIME PIC 9(06). 05 FILLER PIC X(01) VALUE SPACE. 05 WS-AL-SEVERITY PIC X(01). 05 FILLER PIC X(02) VALUE SPACE. 05 WS-AL-MESSAGE PIC X(55). 01 WS-ERROR-SEVERITY PIC X(01). 88 WS-ERR-INFO VALUE "I". 88 WS-ERR-WARN VALUE "W". 88 WS-ERR-ERROR VALUE "E". 88 WS-ERR-FATAL VALUE "F". *> Merge statistics 01 WS-MERGE-STATS. 05 WS-MS-SRC1-COUNT PIC 9(09) VALUE 0. 05 WS-MS-SRC2-COUNT PIC 9(09) VALUE 0. 05 WS-MS-SRC3-COUNT PIC 9(09) VALUE 0. 05 WS-MS-SRC4-COUNT PIC 9(09) VALUE 0. 05 WS-MS-SRC5-COUNT PIC 9(09) VALUE 0. 05 WS-MS-SRC6-COUNT PIC 9(09) VALUE 0. 05 WS-MS-TOTAL-MERGED PIC 9(09) VALUE 0. 05 WS-MS-DUP-REMOVED PIC 9(09) VALUE 0. 05 WS-MS-INVALID-COUNT PIC 9(09) VALUE 0. 05 WS-MS-HASH-TOTAL PIC 9(15) VALUE 0. *> Detail line for enhanced merge output 01 WS-ENH-DETAIL-LINE. 05 FILLER PIC X(02) VALUE SPACE. 05 EDL-KEY PIC X(10). 05 FILLER PIC X(01) VALUE SPACE. 05 EDL-DATA PIC X(20). 05 FILLER PIC X(01) VALUE SPACE. 05 EDL-VALUE PIC Z(9)9. 05 FILLER PIC X(02) VALUE SPACE. 05 EDL-SOURCE PIC X(05). 05 FILLER PIC X(02) VALUE SPACE. 05 EDL-TIMESTAMP PIC 9(08). *> Dedup tracking 01 WS-PREV-MERGE-KEY PIC X(10). 01 WS-PREV-MERGE-SOURCE PIC X(05). 01 WS-PREV-MERGE-TS PIC 9(08). *> Source priority table 01 WS-SOURCE-PRIORITY. 05 WS-SP-ENTRY OCCURS 6 TIMES. 10 WS-SP-NAME PIC X(05). 10 WS-SP-RANK PIC 9(01). *> Source names for stats 01 WS-SOURCE-NAMES. 05 FILLER PIC X(35) VALUE "BSS-A BSS-B BSS-C BSS-D BSS-E BSS-F". 01 WS-SOURCE-NAMES-REDEF REDEFINES WS-SOURCE-NAMES. 05 WS-SN-ENTRY OCCURS 6 TIMES. 10 WS-SN-NAME PIC X(05). *> Enhanced test data for source-tagged inputs *> Format: key(10) + data(20) + value(5) + source(5) + timestamp(8) = 48 01 ENH4-DATA. 05 FILLER PIC X(48) VALUE "CDRA00000113800138001 00100BSS-A 20260601". 05 FILLER PIC X(48) VALUE "CDRB00000113900139001 00200BSS-A 20260601". 05 FILLER PIC X(48) VALUE "CDRC00000113700137001 00300BSS-A 20260601". 01 ENH4-REDEF REDEFINES ENH4-DATA. 05 E4-ENTRY OCCURS 3 TIMES. 10 E4-KEY PIC X(10). 10 E4-DATA PIC X(20). 10 E4-VALUE PIC 9(05). 10 E4-SOURCE PIC X(05). 10 E4-TIMESTAMP PIC 9(08). 01 ENH5-DATA. 05 FILLER PIC X(48) VALUE "CDRA00000113800138001 00150BSS-B 20260602". 05 FILLER PIC X(48) VALUE "CDRB00000213600136001 00250BSS-B 20260602". 05 FILLER PIC X(48) VALUE "CDRD00000113500135001 00400BSS-B 20260602". 01 ENH5-REDEF REDEFINES ENH5-DATA. 05 E5-ENTRY OCCURS 3 TIMES. 10 E5-KEY PIC X(10). 10 E5-DATA PIC X(20). 10 E5-VALUE PIC 9(05). 10 E5-SOURCE PIC X(05). 10 E5-TIMESTAMP PIC 9(08). 01 ENH6-DATA. 05 FILLER PIC X(48) VALUE "CDRA00000113800138001 00175BSS-C 20260603". 05 FILLER PIC X(48) VALUE "CDRB00000313400134001 00350BSS-C 20260603". 05 FILLER PIC X(48) VALUE "CDRE00000113300133001 00500BSS-C 20260603". 01 ENH6-REDEF REDEFINES ENH6-DATA. 05 E6-ENTRY OCCURS 3 TIMES. 10 E6-KEY PIC X(10). 10 E6-DATA PIC X(20). 10 E6-VALUE PIC 9(05). 10 E6-SOURCE PIC X(05). 10 E6-TIMESTAMP PIC 9(08). 01 ENH-IDX PIC 9(02). *> Report header templates 01 WS-RPT-HEADER1. 05 FILLER PIC X(30) VALUE "MERGE REPORT - RUN AT ". 05 RPT1-DATE PIC 9(08). 05 FILLER PIC X(01) VALUE SPACE. 05 RPT1-TIME PIC 9(06). 01 WS-RPT-HEADER2. 05 FILLER PIC X(80) VALUE ALL "=". PROCEDURE DIVISION. MAIN-PROCEDURE. OPEN OUTPUT FILE-REPORT. *> ======================================== *> MR-N001: 2-file MERGE *> ======================================== DISPLAY "=== MR-N001: 2-file MERGE ===". MOVE "MR-N001: 2-file MERGE" TO REPORT-REC. WRITE REPORT-REC. PERFORM WRITE-HEADER. PERFORM INIT-FILE1. PERFORM INIT-FILE2. MERGE FILE-WORK ON ASCENDING KEY WR-KEY USING FILE-IN1, FILE-IN2 GIVING FILE-OUT. PERFORM DISPLAY-MERGE-OUTPUT. *> ======================================== *> MR-N002: 3-file MERGE *> ======================================== DISPLAY "=== MR-N002: 3-file MERGE ===". MOVE "MR-N002: 3-file MERGE" TO REPORT-REC. WRITE REPORT-REC. PERFORM WRITE-HEADER. PERFORM INIT-FILE1. PERFORM INIT-FILE2. PERFORM INIT-FILE3. MERGE FILE-WORK ON ASCENDING KEY WR-KEY USING FILE-IN1, FILE-IN2, FILE-IN3 GIVING FILE-OUT. PERFORM DISPLAY-MERGE-OUTPUT. *> ======================================== *> MR-N003: Duplicate key MERGE *> ======================================== DISPLAY "=== MR-N003: Duplicate key MERGE ===". MOVE "MR-N003: Duplicate key MERGE" TO REPORT-REC. WRITE REPORT-REC. PERFORM WRITE-HEADER. *> Create input files with overlapping keys PERFORM INIT-DUP-FILE1. PERFORM INIT-DUP-FILE2. MERGE FILE-WORK ON ASCENDING KEY WR-KEY USING FILE-IN1, FILE-IN2 GIVING FILE-OUT. PERFORM DISPLAY-MERGE-OUTPUT. *> ======================================== *> MR-N004: MERGE with OUTPUT PROCEDURE *> ======================================== DISPLAY "=== MR-N004: MERGE with OUTPUT PROCEDURE ===". MOVE "MR-N004: MERGE OUTPUT PROCEDURE" TO REPORT-REC. WRITE REPORT-REC. PERFORM WRITE-HEADER. PERFORM INIT-FILE1. PERFORM INIT-FILE2. MERGE FILE-WORK ON ASCENDING KEY WR-KEY USING FILE-IN1, FILE-IN2 OUTPUT PROCEDURE IS MERGE-OUTPUT-PROC. PERFORM DISPLAY-MERGE-OUTPUT. *> ======================================== *> MR-A001: Unsorted input (expected anomaly) *> ======================================== DISPLAY "=== MR-A001: Unsorted input (anomaly) ===". MOVE "MR-A001: Unsorted input" TO REPORT-REC. WRITE REPORT-REC. OPEN OUTPUT FILE-IN1. MOVE "CDR-Z-0001PHONE-13800138001 00100" TO IN1-REC. WRITE IN1-REC. MOVE "CDR-A-0001PHONE-13900139001 00200" TO IN1-REC. WRITE IN1-REC. CLOSE FILE-IN1. OPEN OUTPUT FILE-IN2. MOVE "CDR-G-0001PHONE-13700137001 00300" TO IN2-REC. WRITE IN2-REC. MOVE "CDR-B-0001PHONE-13600136001 00400" TO IN2-REC. WRITE IN2-REC. CLOSE FILE-IN2. MERGE FILE-WORK ON ASCENDING KEY WR-KEY USING FILE-IN1, FILE-IN2 GIVING FILE-OUT. DISPLAY " (Note: MERGE with unsorted input may produce" DISPLAY " unpredictable results. This is expected." PERFORM DISPLAY-MERGE-OUTPUT. *> ================================================================ *> MR-N005: 3-file enhanced MERGE with source tagging *> Uses FILE-WORK2 and source-tagged inputs *> ================================================================ DISPLAY "=== MR-N005: 3-file source-tagged MERGE ===". PERFORM 1000-INIT. PERFORM INIT-FILE4. PERFORM INIT-FILE5. PERFORM INIT-FILE6. MERGE FILE-WORK2 ON ASCENDING KEY W2R-KEY USING FILE-IN4, FILE-IN5, FILE-IN6 GIVING FILE-OUT. PERFORM DISPLAY-ENH-MERGE-OUTPUT. DISPLAY " MR-N005: Source-tagged merge complete". *> ================================================================ *> MR-N006: MERGE with OUTPUT PROCEDURE and source identification *> ================================================================ DISPLAY "=== MR-N006: MERGE OUTPUT PROCEDURE with source ===". PERFORM 1000-INIT. PERFORM INIT-FILE4. PERFORM INIT-FILE5. PERFORM INIT-FILE6. MERGE FILE-WORK2 ON ASCENDING KEY W2R-KEY USING FILE-IN4, FILE-IN5, FILE-IN6 OUTPUT PROCEDURE IS ENH-MERGE-OUTPUT-PROC. DISPLAY " MR-N006: Source-identified merge complete". MOVE "MR-N006: Source-identified merge complete" TO WS-AUDIT-MESSAGE. MOVE "I" TO WS-ERROR-SEVERITY. PERFORM 5000-AUDIT. *> ================================================================ *> MR-N007: Dedup merge - same key from different sources *> Keep newest record (highest timestamp) *> ================================================================ DISPLAY "=== MR-N007: Dedup merge (keep newest) ===". PERFORM 1000-INIT. *> Create files with overlapping keys at different timestamps PERFORM INIT-DUP-FILE4. PERFORM INIT-DUP-FILE5. PERFORM INIT-DUP-FILE6. MERGE FILE-WORK2 ON ASCENDING KEY W2R-KEY DESCENDING KEY W2R-TIMESTAMP USING FILE-IN4, FILE-IN5, FILE-IN6 OUTPUT PROCEDURE IS DEDUP-MERGE-OUTPUT. PERFORM WRITE-MERGE-STATS. DISPLAY " MR-N007: Dedup merge complete". MOVE "MR-N007: Dedup merge (keep newest) complete" TO WS-AUDIT-MESSAGE. MOVE "I" TO WS-ERROR-SEVERITY. PERFORM 5000-AUDIT. *> ================================================================ *> MR-N008: Source file validation before merge *> ================================================================ DISPLAY "=== MR-N008: Source file validation ===". PERFORM 1000-INIT. PERFORM INIT-FILE4. PERFORM INIT-FILE5. PERFORM INIT-FILE6. PERFORM VALIDATE-SOURCE-FILES. IF WS-ERROR-SEVERITY NOT = "F" MERGE FILE-WORK2 ON ASCENDING KEY W2R-KEY USING FILE-IN4, FILE-IN5, FILE-IN6 OUTPUT PROCEDURE IS ENH-MERGE-OUTPUT-PROC DISPLAY " MR-N008: Merge after validation complete" ELSE DISPLAY " MR-N008: Skipped due to validation failure" END-IF. MOVE "MR-N008: Source validation completed" TO WS-AUDIT-MESSAGE. MOVE "I" TO WS-ERROR-SEVERITY. PERFORM 5000-AUDIT. *> ================================================================ *> MR-N009: Conflict resolution with priority rules *> BSS-A > BSS-B > BSS-C for conflicts *> ================================================================ DISPLAY "=== MR-N009: Conflict resolution by priority ===". PERFORM 1000-INIT. PERFORM INIT-CONFLICT-FILES. MERGE FILE-WORK2 ON ASCENDING KEY W2R-KEY USING FILE-IN4, FILE-IN5, FILE-IN6 OUTPUT PROCEDURE IS CONFLICT-RESOLVE-OUTPUT. PERFORM WRITE-MERGE-STATS. DISPLAY " MR-N009: Conflict resolution complete". MOVE "MR-N009: Conflict resolution by priority complete" TO WS-AUDIT-MESSAGE. MOVE "I" TO WS-ERROR-SEVERITY. PERFORM 5000-AUDIT. *> Close all files and finish CLOSE FILE-REPORT. CLOSE FILE-AUDIT. CLOSE FILE-STATS. DISPLAY "=== All MR-N001..N009 + A001 complete ===". STOP RUN. *> ================================================================ *> Existing paragraphs (preserved exactly) *> ================================================================ WRITE-HEADER. MOVE WS-HEADER-LINE TO REPORT-REC. WRITE REPORT-REC. MOVE SPACES TO REPORT-REC. WRITE REPORT-REC. INIT-FILE1. OPEN OUTPUT FILE-IN1. PERFORM VARYING IDX FROM 1 BY 1 UNTIL IDX > 3 MOVE T1-KEY(IDX) TO IN1-KEY MOVE T1-DATA(IDX) TO IN1-DATA MOVE T1-VALUE(IDX) TO IN1-VALUE WRITE IN1-REC END-PERFORM. CLOSE FILE-IN1. INIT-FILE2. OPEN OUTPUT FILE-IN2. PERFORM VARYING IDX FROM 1 BY 1 UNTIL IDX > 3 MOVE T2-KEY(IDX) TO IN2-KEY MOVE T2-DATA(IDX) TO IN2-DATA MOVE T2-VALUE(IDX) TO IN2-VALUE WRITE IN2-REC END-PERFORM. CLOSE FILE-IN2. INIT-FILE3. OPEN OUTPUT FILE-IN3. PERFORM VARYING IDX FROM 1 BY 1 UNTIL IDX > 3 MOVE T3-KEY(IDX) TO IN3-KEY MOVE T3-DATA(IDX) TO IN3-DATA MOVE T3-VALUE(IDX) TO IN3-VALUE WRITE IN3-REC END-PERFORM. CLOSE FILE-IN3. INIT-DUP-FILE1. OPEN OUTPUT FILE-IN1. MOVE "CDR-D00001" TO IN1-KEY. MOVE "DUP-FILE1-CALL-001 " TO IN1-DATA. MOVE 00100 TO IN1-VALUE. WRITE IN1-REC. MOVE "CDR-D00002" TO IN1-KEY. MOVE "DUP-FILE1-CALL-002 " TO IN1-DATA. MOVE 00200 TO IN1-VALUE. WRITE IN1-REC. CLOSE FILE-IN1. INIT-DUP-FILE2. OPEN OUTPUT FILE-IN2. MOVE "CDR-D00001" TO IN2-KEY. MOVE "DUP-FILE2-CALL-001 " TO IN2-DATA. MOVE 00300 TO IN2-VALUE. WRITE IN2-REC. MOVE "CDR-D00003" TO IN2-KEY. MOVE "DUP-FILE2-CALL-003 " TO IN2-DATA. MOVE 00400 TO IN2-VALUE. WRITE IN2-REC. CLOSE FILE-IN2. DISPLAY-MERGE-OUTPUT. OPEN INPUT FILE-OUT. MOVE 0 TO WS-RECORD-COUNT. MOVE 0 TO WS-TOTAL-VALUE. MOVE "N" TO WS-EOF. PERFORM UNTIL WS-EOF-Y READ FILE-OUT INTO OUT-REC AT END MOVE "Y" TO WS-EOF NOT AT END ADD 1 TO WS-RECORD-COUNT ADD OUT-VALUE TO WS-TOTAL-VALUE MOVE OUT-KEY TO DL-KEY MOVE OUT-DATA TO DL-DATA MOVE OUT-VALUE TO DL-VALUE MOVE SPACES TO DL-SOURCE DISPLAY " " WS-DETAIL-LINE MOVE WS-DETAIL-LINE TO REPORT-REC WRITE REPORT-REC END-READ END-PERFORM. CLOSE FILE-OUT. DISPLAY " Total records: " WS-RECORD-COUNT " Total value: " WS-TOTAL-VALUE. MOVE SPACES TO REPORT-REC. WRITE REPORT-REC. STRING " Total records: " WS-RECORD-COUNT " Total value: " WS-TOTAL-VALUE DELIMITED BY SIZE INTO REPORT-REC. WRITE REPORT-REC. MOVE SPACES TO REPORT-REC. WRITE REPORT-REC. MERGE-OUTPUT-PROC SECTION. *> OUTPUT PROCEDURE for MERGE - adds source tagging OPEN OUTPUT FILE-OUT. MOVE "N" TO WS-EOF. PERFORM UNTIL WS-EOF-Y RETURN FILE-WORK INTO WORK-REC AT END MOVE "Y" TO WS-EOF NOT AT END MOVE WORK-REC TO OUT-REC WRITE OUT-REC END-RETURN END-PERFORM. CLOSE FILE-OUT. *> ================================================================ *> New enhanced sections *> ================================================================ *> ---------------------------------------------------------------- *> 1000-INIT: Initialize batch totals, open audit/stats files *> ---------------------------------------------------------------- 1000-INIT SECTION. MOVE FUNCTION CURRENT-DATE TO WS-CURRENT-DATE-TIME. MOVE 0 TO WS-MS-SRC1-COUNT MOVE 0 TO WS-MS-SRC2-COUNT MOVE 0 TO WS-MS-SRC3-COUNT MOVE 0 TO WS-MS-SRC4-COUNT MOVE 0 TO WS-MS-SRC5-COUNT MOVE 0 TO WS-MS-SRC6-COUNT MOVE 0 TO WS-MS-TOTAL-MERGED MOVE 0 TO WS-MS-DUP-REMOVED MOVE 0 TO WS-MS-INVALID-COUNT MOVE 0 TO WS-MS-HASH-TOTAL MOVE SPACES TO WS-PREV-MERGE-KEY MOVE SPACES TO WS-PREV-MERGE-SOURCE MOVE ZEROS TO WS-PREV-MERGE-TS MOVE "I" TO WS-ERROR-SEVERITY. *> Initialize source priority (lower rank = higher priority) MOVE "BSS-A" TO WS-SP-NAME(1) MOVE 1 TO WS-SP-RANK(1) MOVE "BSS-B" TO WS-SP-NAME(2) MOVE 2 TO WS-SP-RANK(2) MOVE "BSS-C" TO WS-SP-NAME(3) MOVE 3 TO WS-SP-RANK(3) MOVE "BSS-D" TO WS-SP-NAME(4) MOVE 4 TO WS-SP-RANK(4) MOVE "BSS-E" TO WS-SP-NAME(5) MOVE 5 TO WS-SP-RANK(5) MOVE "BSS-F" TO WS-SP-NAME(6) MOVE 6 TO WS-SP-RANK(6). DISPLAY " 1000-INIT at " WS-CDT-DATE "/" WS-CDT-TIME. OPEN OUTPUT FILE-AUDIT. IF NOT FS-AUDIT-OK DISPLAY "ERROR: FILE-AUDIT open failed, FS=" FS-AUDIT MOVE "E" TO WS-ERROR-SEVERITY END-IF. OPEN OUTPUT FILE-STATS. IF NOT FS-STATS-OK DISPLAY "ERROR: FILE-STATS open failed, FS=" FS-STATS MOVE "E" TO WS-ERROR-SEVERITY END-IF. MOVE "1000-INIT: Initialization complete" TO WS-AUDIT-MESSAGE. PERFORM 5000-AUDIT. EXIT. *> ---------------------------------------------------------------- *> 2000-OPEN-FILES: Enhanced file open with FILE STATUS *> ---------------------------------------------------------------- 2000-OPEN-FILES SECTION. DISPLAY " 2000-OPEN-FILES: Opening merge files...". OPEN OUTPUT FILE-IN4. IF NOT FS-IN4-OK DISPLAY "ERROR 2000: FILE-IN4 open failed, FS=" FS-IN4 MOVE "E" TO WS-ERROR-SEVERITY PERFORM 6000-ERROR-HANDLE END-IF. OPEN OUTPUT FILE-IN5. IF NOT FS-IN5-OK DISPLAY "ERROR 2000: FILE-IN5 open failed, FS=" FS-IN5 MOVE "E" TO WS-ERROR-SEVERITY PERFORM 6000-ERROR-HANDLE END-IF. OPEN OUTPUT FILE-IN6. IF NOT FS-IN6-OK DISPLAY "ERROR 2000: FILE-IN6 open failed, FS=" FS-IN6 MOVE "E" TO WS-ERROR-SEVERITY PERFORM 6000-ERROR-HANDLE END-IF. MOVE "2000-OPEN-FILES: Enhanced files opened" TO WS-AUDIT-MESSAGE. PERFORM 5000-AUDIT. EXIT. *> ---------------------------------------------------------------- *> 3000-PROCESS: Main merge processing pipeline *> ---------------------------------------------------------------- 3000-PROCESS SECTION. DISPLAY " 3000-PROCESS: Executing merge...". MERGE FILE-WORK2 ON ASCENDING KEY W2R-KEY USING FILE-IN4, FILE-IN5, FILE-IN6 OUTPUT PROCEDURE IS ENH-MERGE-OUTPUT-PROC. MOVE "3000-PROCESS: Merge pipeline complete" TO WS-AUDIT-MESSAGE. PERFORM 5000-AUDIT. EXIT. *> ---------------------------------------------------------------- *> 4000-REPORT: Generate merge summary report *> ---------------------------------------------------------------- 4000-REPORT SECTION. DISPLAY " 4000-REPORT: Generating merge report...". MOVE WS-CDT-DATE TO RPT1-DATE. MOVE WS-CDT-TIME TO RPT1-TIME. MOVE WS-RPT-HEADER1 TO REPORT-REC. WRITE REPORT-REC. MOVE WS-RPT-HEADER2 TO REPORT-REC. WRITE REPORT-REC. MOVE "4000-REPORT: Merge report generated" TO WS-AUDIT-MESSAGE. PERFORM 5000-AUDIT. EXIT. *> ---------------------------------------------------------------- *> 5000-AUDIT: Write audit entry with timestamp/severity *> ---------------------------------------------------------------- 5000-AUDIT SECTION. MOVE FUNCTION CURRENT-DATE TO WS-CURRENT-DATE-TIME. MOVE WS-CDT-DATE TO WS-AL-DATE. MOVE WS-CDT-TIME TO WS-AL-TIME. MOVE WS-ERROR-SEVERITY TO WS-AL-SEVERITY. IF WS-AL-SEVERITY = SPACE MOVE "I" TO WS-AL-SEVERITY END-IF. MOVE WS-AUDIT-MESSAGE TO WS-AL-MESSAGE. MOVE WS-AUDIT-LINE TO AUDIT-REC. WRITE AUDIT-REC. IF NOT FS-AUDIT-OK DISPLAY "AUDIT WRITE FAILED: FS=" FS-AUDIT END-IF. DISPLAY " AUDIT [" WS-AL-SEVERITY "] " WS-AL-DATE "/" WS-AL-TIME " " WS-AL-MESSAGE. EXIT. *> ---------------------------------------------------------------- *> 6000-ERROR-HANDLE: Handle errors with severity levels *> ---------------------------------------------------------------- 6000-ERROR-HANDLE SECTION. EVALUATE WS-ERROR-SEVERITY WHEN "I" DISPLAY " INFO: Recoverable condition" WHEN "W" DISPLAY " WARN: Non-critical issue detected" PERFORM 5000-AUDIT WHEN "E" DISPLAY " ERROR: Processing may be affected" PERFORM 5000-AUDIT WHEN "F" DISPLAY " FATAL: Aborting processing" PERFORM 5000-AUDIT STOP RUN WHEN OTHER DISPLAY " INFO: Unknown severity - continuing" END-EVALUATE. MOVE "I" TO WS-ERROR-SEVERITY. EXIT. *> ---------------------------------------------------------------- *> 9000-EXIT: Clean exit with file closure *> ---------------------------------------------------------------- 9000-EXIT SECTION. DISPLAY " 9000-EXIT: Closing files and exiting...". CLOSE FILE-AUDIT. CLOSE FILE-STATS. CLOSE FILE-REPORT. MOVE "9000-EXIT: Normal termination" TO WS-AUDIT-MESSAGE. MOVE "I" TO WS-ERROR-SEVERITY. PERFORM 5000-AUDIT. DISPLAY " 9000-EXIT: All files closed. Exiting.". EXIT. *> ================================================================ *> INIT-FILE4: Create enhanced input file 4 (BSS-D) *> ================================================================ INIT-FILE4. OPEN OUTPUT FILE-IN4. IF NOT FS-IN4-OK DISPLAY "ERROR INIT-FILE4: open failed, FS=" FS-IN4 MOVE "E" TO WS-ERROR-SEVERITY PERFORM 6000-ERROR-HANDLE END-IF. PERFORM VARYING ENH-IDX FROM 1 BY 1 UNTIL ENH-IDX > 3 MOVE E4-KEY(ENH-IDX) TO IN4-KEY MOVE E4-DATA(ENH-IDX) TO IN4-DATA MOVE E4-VALUE(ENH-IDX) TO IN4-VALUE MOVE E4-SOURCE(ENH-IDX) TO IN4-SOURCE MOVE E4-TIMESTAMP(ENH-IDX) TO IN4-TIMESTAMP WRITE IN4-REC IF NOT FS-IN4-OK DISPLAY "ERROR: FILE-IN4 write failed, FS=" FS-IN4 END-IF END-PERFORM. CLOSE FILE-IN4. DISPLAY " INIT-FILE4: 3 source-tagged records written". EXIT. *> ================================================================ *> INIT-FILE5: Create enhanced input file 5 (BSS-E) *> ================================================================ INIT-FILE5. OPEN OUTPUT FILE-IN5. IF NOT FS-IN5-OK DISPLAY "ERROR INIT-FILE5: open failed, FS=" FS-IN5 MOVE "E" TO WS-ERROR-SEVERITY PERFORM 6000-ERROR-HANDLE END-IF. PERFORM VARYING ENH-IDX FROM 1 BY 1 UNTIL ENH-IDX > 3 MOVE E5-KEY(ENH-IDX) TO IN5-KEY MOVE E5-DATA(ENH-IDX) TO IN5-DATA MOVE E5-VALUE(ENH-IDX) TO IN5-VALUE MOVE E5-SOURCE(ENH-IDX) TO IN5-SOURCE MOVE E5-TIMESTAMP(ENH-IDX) TO IN5-TIMESTAMP WRITE IN5-REC IF NOT FS-IN5-OK DISPLAY "ERROR: FILE-IN5 write failed, FS=" FS-IN5 END-IF END-PERFORM. CLOSE FILE-IN5. DISPLAY " INIT-FILE5: 3 source-tagged records written". EXIT. *> ================================================================ *> INIT-FILE6: Create enhanced input file 6 (BSS-F) *> ================================================================ INIT-FILE6. OPEN OUTPUT FILE-IN6. IF NOT FS-IN6-OK DISPLAY "ERROR INIT-FILE6: open failed, FS=" FS-IN6 MOVE "E" TO WS-ERROR-SEVERITY PERFORM 6000-ERROR-HANDLE END-IF. PERFORM VARYING ENH-IDX FROM 1 BY 1 UNTIL ENH-IDX > 3 MOVE E6-KEY(ENH-IDX) TO IN6-KEY MOVE E6-DATA(ENH-IDX) TO IN6-DATA MOVE E6-VALUE(ENH-IDX) TO IN6-VALUE MOVE E6-SOURCE(ENH-IDX) TO IN6-SOURCE MOVE E6-TIMESTAMP(ENH-IDX) TO IN6-TIMESTAMP WRITE IN6-REC IF NOT FS-IN6-OK DISPLAY "ERROR: FILE-IN6 write failed, FS=" FS-IN6 END-IF END-PERFORM. CLOSE FILE-IN6. DISPLAY " INIT-FILE6: 3 source-tagged records written". EXIT. *> ================================================================ *> INIT-DUP-FILE4/DUP-FILE5/DUP-FILE6: Duplicate key files *> ================================================================ INIT-DUP-FILE4. OPEN OUTPUT FILE-IN4. IF NOT FS-IN4-OK DISPLAY "ERROR INIT-DUP4: open failed, FS=" FS-IN4 END-IF. MOVE "CDR-CONF01" TO IN4-KEY. MOVE "CONFLICT-CDR-001-A " TO IN4-DATA. MOVE 00100 TO IN4-VALUE. MOVE "BSS-D" TO IN4-SOURCE. MOVE 20260601 TO IN4-TIMESTAMP. WRITE IN4-REC. MOVE "CDR-CONF02" TO IN4-KEY. MOVE "CONFLICT-CDR-002-A " TO IN4-DATA. MOVE 00200 TO IN4-VALUE. MOVE "BSS-D" TO IN4-SOURCE. MOVE 20260601 TO IN4-TIMESTAMP. WRITE IN4-REC. CLOSE FILE-IN4. DISPLAY " INIT-DUP-FILE4: 2 records (1 conflict)". EXIT. INIT-DUP-FILE5. OPEN OUTPUT FILE-IN5. IF NOT FS-IN5-OK DISPLAY "ERROR INIT-DUP5: open failed, FS=" FS-IN5 END-IF. MOVE "CDR-CONF01" TO IN5-KEY. MOVE "CONFLICT-CDR-001-B " TO IN5-DATA. MOVE 00150 TO IN5-VALUE. MOVE "BSS-E" TO IN5-SOURCE. MOVE 20260602 TO IN5-TIMESTAMP. WRITE IN5-REC. MOVE "CDR-CONF03" TO IN5-KEY. MOVE "CONFLICT-CDR-003-B " TO IN5-DATA. MOVE 00300 TO IN5-VALUE. MOVE "BSS-E" TO IN5-SOURCE. MOVE 20260602 TO IN5-TIMESTAMP. WRITE IN5-REC. CLOSE FILE-IN5. DISPLAY " INIT-DUP-FILE5: 2 records (1 conflict)". EXIT. INIT-DUP-FILE6. OPEN OUTPUT FILE-IN6. IF NOT FS-IN6-OK DISPLAY "ERROR INIT-DUP6: open failed, FS=" FS-IN6 END-IF. MOVE "CDR-CONF01" TO IN6-KEY. MOVE "CONFLICT-CDR-001-C " TO IN6-DATA. MOVE 00175 TO IN6-VALUE. MOVE "BSS-F" TO IN6-SOURCE. MOVE 20260603 TO IN6-TIMESTAMP. WRITE IN6-REC. MOVE "CDR-CONF04" TO IN6-KEY. MOVE "CONFLICT-CDR-004-C " TO IN6-DATA. MOVE 00400 TO IN6-VALUE. MOVE "BSS-F" TO IN6-SOURCE. MOVE 20260603 TO IN6-TIMESTAMP. WRITE IN6-REC. CLOSE FILE-IN6. DISPLAY " INIT-DUP-FILE6: 2 records (1 conflict)". EXIT. *> ================================================================ *> INIT-CONFLICT-FILES: Create files for conflict resolution test *> ================================================================ INIT-CONFLICT-FILES. *> FILE-IN4 (BSS-D - highest priority) OPEN OUTPUT FILE-IN4. MOVE "CDR-CONF01" TO IN4-KEY. MOVE "PRIORITY-A-VERSION " TO IN4-DATA. MOVE 00100 TO IN4-VALUE. MOVE "BSS-D" TO IN4-SOURCE. MOVE 20260601 TO IN4-TIMESTAMP. WRITE IN4-REC. MOVE "CDR-UNIQU1" TO IN4-KEY. MOVE "UNIQUE-A-RECORD " TO IN4-DATA. MOVE 00200 TO IN4-VALUE. MOVE "BSS-D" TO IN4-SOURCE. MOVE 20260601 TO IN4-TIMESTAMP. WRITE IN4-REC. CLOSE FILE-IN4. *> FILE-IN5 (BSS-E - medium priority) OPEN OUTPUT FILE-IN5. MOVE "CDR-CONF01" TO IN5-KEY. MOVE "PRIORITY-B-VERSION " TO IN5-DATA. MOVE 00150 TO IN5-VALUE. MOVE "BSS-E" TO IN5-SOURCE. MOVE 20260602 TO IN5-TIMESTAMP. WRITE IN5-REC. MOVE "CDR-CONF02" TO IN5-KEY. MOVE "CONFLICT-TWO-B " TO IN5-DATA. MOVE 00300 TO IN5-VALUE. MOVE "BSS-E" TO IN5-SOURCE. MOVE 20260602 TO IN5-TIMESTAMP. WRITE IN5-REC. CLOSE FILE-IN5. *> FILE-IN6 (BSS-F - lowest priority) OPEN OUTPUT FILE-IN6. MOVE "CDR-CONF01" TO IN6-KEY. MOVE "PRIORITY-C-VERSION " TO IN6-DATA. MOVE 00175 TO IN6-VALUE. MOVE "BSS-F" TO IN6-SOURCE. MOVE 20260603 TO IN6-TIMESTAMP. WRITE IN6-REC. MOVE "CDR-CONF02" TO IN6-KEY. MOVE "CONFLICT-TWO-C " TO IN6-DATA. MOVE 00350 TO IN6-VALUE. MOVE "BSS-F" TO IN6-SOURCE. MOVE 20260603 TO IN6-TIMESTAMP. WRITE IN6-REC. CLOSE FILE-IN6. DISPLAY " INIT-CONFLICT-FILES: 3 files with conflicts". EXIT. *> ================================================================ *> DISPLAY-ENH-MERGE-OUTPUT: Display enhanced merge output *> ================================================================ DISPLAY-ENH-MERGE-OUTPUT. OPEN INPUT FILE-OUT. IF NOT FS-OUT-OK DISPLAY "ERROR: FILE-OUT open failed, FS=" FS-OUT EXIT END-IF. MOVE 0 TO WS-RECORD-COUNT. MOVE 0 TO WS-TOTAL-VALUE. MOVE "N" TO WS-EOF. PERFORM UNTIL WS-EOF-Y READ FILE-OUT INTO OUT-REC AT END MOVE "Y" TO WS-EOF NOT AT END ADD 1 TO WS-RECORD-COUNT ADD OUT-VALUE TO WS-TOTAL-VALUE MOVE OUT-KEY TO DL-KEY MOVE OUT-DATA TO DL-DATA MOVE OUT-VALUE TO DL-VALUE MOVE "ENH" TO DL-SOURCE DISPLAY " " WS-DETAIL-LINE END-READ END-PERFORM. CLOSE FILE-OUT. DISPLAY " Enhanced merged: " WS-RECORD-COUNT " records, value=" WS-TOTAL-VALUE. EXIT. *> ================================================================ *> ENH-MERGE-OUTPUT-PROC: OUTPUT PROCEDURE with source ID *> ================================================================ ENH-MERGE-OUTPUT-PROC SECTION. DISPLAY " ENH-MERGE-OUTPUT-PROC: Source-identified output". OPEN OUTPUT FILE-OUT. IF NOT FS-OUT-OK DISPLAY "ERROR: FILE-OUT open in OUTPUT PROC, FS=" FS-OUT MOVE "E" TO WS-ERROR-SEVERITY PERFORM 6000-ERROR-HANDLE EXIT END-IF. MOVE 0 TO WS-MS-TOTAL-MERGED. MOVE "N" TO WS-EOF. PERFORM UNTIL WS-EOF-Y RETURN FILE-WORK2 INTO WORK2-REC AT END MOVE "Y" TO WS-EOF NOT AT END ADD 1 TO WS-MS-TOTAL-MERGED ADD W2R-VALUE TO WS-MS-HASH-TOTAL *> Count by source EVALUATE W2R-SOURCE WHEN "BSS-A" ADD 1 TO WS-MS-SRC1-COUNT WHEN "BSS-B" ADD 1 TO WS-MS-SRC2-COUNT WHEN "BSS-C" ADD 1 TO WS-MS-SRC3-COUNT WHEN "BSS-D" ADD 1 TO WS-MS-SRC4-COUNT WHEN "BSS-E" ADD 1 TO WS-MS-SRC5-COUNT WHEN "BSS-F" ADD 1 TO WS-MS-SRC6-COUNT WHEN OTHER ADD 1 TO WS-MS-INVALID-COUNT END-EVALUATE *> Map work record to output with source visible in data field MOVE W2R-KEY TO OUT-KEY MOVE W2R-DATA TO OUT-DATA(1:20) MOVE W2R-VALUE TO OUT-VALUE WRITE OUT-REC IF NOT FS-OUT-OK DISPLAY "ERROR: write failed, FS=" FS-OUT END-IF *> Display with source info MOVE W2R-KEY TO EDL-KEY MOVE W2R-DATA TO EDL-DATA MOVE W2R-VALUE TO EDL-VALUE MOVE W2R-SOURCE TO EDL-SOURCE MOVE W2R-TIMESTAMP TO EDL-TIMESTAMP DISPLAY WS-ENH-DETAIL-LINE END-RETURN END-PERFORM. DISPLAY " ENH-MERGE-OUTPUT-PROC: total=" WS-MS-TOTAL-MERGED. CLOSE FILE-OUT. EXIT. *> ================================================================ *> DEDUP-MERGE-OUTPUT: Dedup by key, keep newest (highest timestamp) *> ================================================================ DEDUP-MERGE-OUTPUT SECTION. DISPLAY " DEDUP-MERGE-OUTPUT: Deduplicating by key...". OPEN OUTPUT FILE-OUT. IF NOT FS-OUT-OK DISPLAY "ERROR: FILE-OUT open in DEDUP, FS=" FS-OUT MOVE "E" TO WS-ERROR-SEVERITY PERFORM 6000-ERROR-HANDLE EXIT END-IF. MOVE SPACES TO WS-PREV-MERGE-KEY. MOVE 0 TO WS-MS-TOTAL-MERGED. MOVE 0 TO WS-MS-DUP-REMOVED. MOVE "N" TO WS-EOF. *> Since MERGE sorts by KEY ASC and TIMESTAMP DESC, *> the first occurrence of each key has the highest timestamp PERFORM UNTIL WS-EOF-Y RETURN FILE-WORK2 INTO WORK2-REC AT END MOVE "Y" TO WS-EOF NOT AT END IF W2R-KEY = WS-PREV-MERGE-KEY *> Duplicate key - skip (already have newest) ADD 1 TO WS-MS-DUP-REMOVED DISPLAY " DEDUP removed: " W2R-KEY " from " W2R-SOURCE " timestamp=" W2R-TIMESTAMP ELSE *> New key - accept MOVE W2R-KEY TO WS-PREV-MERGE-KEY MOVE W2R-KEY TO OUT-KEY MOVE W2R-DATA TO OUT-DATA(1:20) MOVE W2R-VALUE TO OUT-VALUE WRITE OUT-REC ADD 1 TO WS-MS-TOTAL-MERGED ADD W2R-VALUE TO WS-MS-HASH-TOTAL DISPLAY " DEDUP kept: " W2R-KEY " from " W2R-SOURCE END-IF END-RETURN END-PERFORM. DISPLAY " DEDUP-MERGE-OUTPUT: kept=" WS-MS-TOTAL-MERGED " removed=" WS-MS-DUP-REMOVED. CLOSE FILE-OUT. EXIT. *> ================================================================ *> VALIDATE-SOURCE-FILES: Check format of each source file *> ================================================================ VALIDATE-SOURCE-FILES. DISPLAY " VALIDATE-SOURCE-FILES: Checking formats...". OPEN INPUT FILE-IN4. IF NOT FS-IN4-OK DISPLAY " VALIDATE: FILE-IN4 missing, FS=" FS-IN4 MOVE "E" TO WS-ERROR-SEVERITY MOVE "VALIDATE: FILE-IN4 format check failed" TO WS-AUDIT-MESSAGE PERFORM 5000-AUDIT ELSE DISPLAY " VALIDATE: FILE-IN4 format OK" CLOSE FILE-IN4 END-IF. OPEN INPUT FILE-IN5. IF NOT FS-IN5-OK DISPLAY " VALIDATE: FILE-IN5 missing, FS=" FS-IN5 MOVE "E" TO WS-ERROR-SEVERITY MOVE "VALIDATE: FILE-IN5 format check failed" TO WS-AUDIT-MESSAGE PERFORM 5000-AUDIT ELSE DISPLAY " VALIDATE: FILE-IN5 format OK" CLOSE FILE-IN5 END-IF. OPEN INPUT FILE-IN6. IF NOT FS-IN6-OK DISPLAY " VALIDATE: FILE-IN6 missing, FS=" FS-IN6 MOVE "E" TO WS-ERROR-SEVERITY MOVE "VALIDATE: FILE-IN6 format check failed" TO WS-AUDIT-MESSAGE PERFORM 5000-AUDIT ELSE DISPLAY " VALIDATE: FILE-IN6 format OK" CLOSE FILE-IN6 END-IF. MOVE "VALIDATE: All source files validated" TO WS-AUDIT-MESSAGE. MOVE "I" TO WS-ERROR-SEVERITY. PERFORM 5000-AUDIT. EXIT. *> ================================================================ *> CONFLICT-RESOLVE-OUTPUT: Resolve conflicts by source priority *> ================================================================ CONFLICT-RESOLVE-OUTPUT SECTION. DISPLAY " CONFLICT-RESOLVE-OUTPUT: Resolving conflicts...". OPEN OUTPUT FILE-OUT. IF NOT FS-OUT-OK DISPLAY "ERROR: FILE-OUT open, FS=" FS-OUT EXIT END-IF. MOVE SPACES TO WS-PREV-MERGE-KEY. MOVE 0 TO WS-MS-TOTAL-MERGED. MOVE 0 TO WS-MS-DUP-REMOVED. MOVE "N" TO WS-EOF. *> Since MERGE sorts by KEY, and we resolve by source priority: *> For each key, keep the record from the highest priority source *> MERGE produces interleaved output, so we process sequentially PERFORM UNTIL WS-EOF-Y RETURN FILE-WORK2 INTO WORK2-REC AT END MOVE "Y" TO WS-EOF NOT AT END IF W2R-KEY NOT = WS-PREV-MERGE-KEY *> New key - accept and set as current IF WS-PREV-MERGE-KEY NOT = SPACES PERFORM WRITE-RESOLVED-RECORD END-IF MOVE W2R-KEY TO WS-PREV-MERGE-KEY MOVE W2R-SOURCE TO WS-PREV-MERGE-SOURCE MOVE W2R-TIMESTAMP TO WS-PREV-MERGE-TS MOVE WORK2-REC TO OUT-REC ELSE *> Same key - conflict resolution ADD 1 TO WS-MS-DUP-REMOVED *> Check if this source has higher priority (lower rank) PERFORM VARYING ENH-IDX FROM 1 BY 1 UNTIL ENH-IDX > 6 IF WS-PREV-MERGE-SOURCE = WS-SP-NAME(ENH-IDX) MOVE ENH-IDX TO IDX END-IF END-PERFORM PERFORM VARYING ENH-IDX FROM 1 BY 1 UNTIL ENH-IDX > 6 IF W2R-SOURCE = WS-SP-NAME(ENH-IDX) *> If current source has lower rank (higher priority), *> replace the output record IF ENH-IDX < IDX MOVE W2R-SOURCE TO WS-PREV-MERGE-SOURCE MOVE W2R-TIMESTAMP TO WS-PREV-MERGE-TS MOVE WORK2-REC TO OUT-REC DISPLAY " CONFLICT: " W2R-KEY " " W2R-SOURCE " wins over " WS-PREV-MERGE-SOURCE ELSE DISPLAY " CONFLICT: " W2R-KEY " " WS-PREV-MERGE-SOURCE " keeps over " W2R-SOURCE END-IF END-IF END-PERFORM END-IF END-RETURN END-PERFORM. *> Write last record IF WS-PREV-MERGE-KEY NOT = SPACES PERFORM WRITE-RESOLVED-RECORD END-IF. DISPLAY " CONFLICT-RESOLVE: total=" WS-MS-TOTAL-MERGED " conflicts-resolved=" WS-MS-DUP-REMOVED. CLOSE FILE-OUT. EXIT. *> ================================================================ *> WRITE-RESOLVED-RECORD: Write a resolved merge record *> ================================================================ WRITE-RESOLVED-RECORD. WRITE OUT-REC. IF NOT FS-OUT-OK DISPLAY "ERROR: write failed, FS=" FS-OUT ELSE ADD 1 TO WS-MS-TOTAL-MERGED ADD OUT-VALUE TO WS-MS-HASH-TOTAL MOVE OUT-KEY TO EDL-KEY MOVE OUT-DATA TO EDL-DATA MOVE OUT-VALUE TO EDL-VALUE MOVE WS-PREV-MERGE-SOURCE TO EDL-SOURCE MOVE WS-PREV-MERGE-TS TO EDL-TIMESTAMP DISPLAY " RESOLVED: " WS-ENH-DETAIL-LINE END-IF. EXIT. *> ================================================================ *> WRITE-MERGE-STATS: Write merge statistics *> ================================================================ WRITE-MERGE-STATS. DISPLAY " WRITE-MERGE-STATS: Writing merge statistics...". MOVE SPACES TO STATS-REC. STRING "=== MERGE STATISTICS ===" DELIMITED BY SIZE INTO STATS-REC. WRITE STATS-REC. MOVE SPACES TO STATS-REC. STRING "Source A (BSS-D) = " WS-MS-SRC1-COUNT DELIMITED BY SIZE INTO STATS-REC. WRITE STATS-REC. MOVE SPACES TO STATS-REC. STRING "Source B (BSS-E) = " WS-MS-SRC2-COUNT DELIMITED BY SIZE INTO STATS-REC. WRITE STATS-REC. MOVE SPACES TO STATS-REC. STRING "Source C (BSS-F) = " WS-MS-SRC3-COUNT DELIMITED BY SIZE INTO STATS-REC. WRITE STATS-REC. MOVE SPACES TO STATS-REC. STRING "Source D (BSS-D) = " WS-MS-SRC4-COUNT DELIMITED BY SIZE INTO STATS-REC. WRITE STATS-REC. MOVE SPACES TO STATS-REC. STRING "Source E (BSS-E) = " WS-MS-SRC5-COUNT DELIMITED BY SIZE INTO STATS-REC. WRITE STATS-REC. MOVE SPACES TO STATS-REC. STRING "Source F (BSS-F) = " WS-MS-SRC6-COUNT DELIMITED BY SIZE INTO STATS-REC. WRITE STATS-REC. MOVE SPACES TO STATS-REC. STRING "Total merged = " WS-MS-TOTAL-MERGED DELIMITED BY SIZE INTO STATS-REC. WRITE STATS-REC. MOVE SPACES TO STATS-REC. STRING "Duplicates removed = " WS-MS-DUP-REMOVED DELIMITED BY SIZE INTO STATS-REC. WRITE STATS-REC. MOVE SPACES TO STATS-REC. STRING "Invalid records = " WS-MS-INVALID-COUNT DELIMITED BY SIZE INTO STATS-REC. WRITE STATS-REC. MOVE SPACES TO STATS-REC. STRING "Hash total (value) = " WS-MS-HASH-TOTAL DELIMITED BY SIZE INTO STATS-REC. WRITE STATS-REC. DISPLAY " STATS: src1=" WS-MS-SRC1-COUNT " src2=" WS-MS-SRC2-COUNT " src3=" WS-MS-SRC3-COUNT " total=" WS-MS-TOTAL-MERGED " dup-removed=" WS-MS-DUP-REMOVED. EXIT.