MODULE 13 · MAINFRAME INTERNALS AND CAPSTONE · 9/10

Capstone: claims end-of-day batch

60 min100 XPExercise

This is the kind of program you'll maintain in your first mainframe job. An insurer receives claims all day. Every night a batch job sorts them, checks each one against the policy master, works out what to pay, writes a report for the claims managers and a reject file for the data-quality team, and sets a return code the scheduler can act on.

You'll write CLMPROC, the program at the centre of that job. It uses nearly everything in the course:

Skill Where it came from
Copybooks for record layouts subprograms module
Reading and writing sequential datasets, DD names sequential files
Loading a table and SEARCH ALL tables
NUMERIC checks before arithmetic this module (S0C7)
Edited money pictures, print lines reports
Control break on a sorted key reports
PARM, return codes, multi-step JCL with COND JCL

How the job fits together

CLAIMS.DAILY.INPUT ──SORT──> &&SORTED ──CLMPROC──> CLAIMS.EOD.REPORT ──IEBGENER──> SYSOUT
                                  CLAIMS.POLICY.TABLE ─┘     └──> CLAIMS.EOD.REJECTS

Your program never sorts anything. It trusts that SORTCLM delivered the claims in region order, which is what makes a one-pass control break possible. The last step prints the report only when CLMPROC ended with RC 4 or less (COND=(4,LT)), so a bad run date (RC 16) stops the job before a wrong report reaches anyone.

Looking up the policy

Load the policy file into a table once, then look up every claim in memory. SEARCH ALL does a binary search, and when it finds a match it leaves the index pointing at the entry, so you can keep using it:

       IDENTIFICATION DIVISION.
       PROGRAM-ID. POLFIND.
       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01  WS-POLICY-DATA       PIC X(27)
           VALUE "P0000101AP0000103LP0000106A".
       01  WS-POLICY-TABLE      REDEFINES WS-POLICY-DATA.
           05  WS-POLICY OCCURS 3 TIMES
                   ASCENDING KEY IS TBL-POL-NO
                   INDEXED BY POL-IX.
               10  TBL-POL-NO       PIC X(8).
               10  TBL-POL-STATUS   PIC X.
       01  WS-WANTED            PIC X(8).
       PROCEDURE DIVISION.
           MOVE "P0000103" TO WS-WANTED
           PERFORM FIND-POLICY
           MOVE "P0000104" TO WS-WANTED
           PERFORM FIND-POLICY
           STOP RUN.
       FIND-POLICY.
           SEARCH ALL WS-POLICY
               AT END
                   DISPLAY WS-WANTED " NOT FOUND"
               WHEN TBL-POL-NO (POL-IX) = WS-WANTED
                   DISPLAY WS-WANTED " STATUS "
                       TBL-POL-STATUS (POL-IX)
           END-SEARCH.
P0000103 STATUS L
P0000104 NOT FOUND

In the capstone the table is OCCURS 1 TO 50 DEPENDING ON WS-POLICY-COUNT, so the search only covers the entries you loaded.

Things that trip people up

  • Validate first, calculate second. On z/OS a claim with letters in its amount would abend the whole night's run with S0C7. Nothing touches CLM-AMOUNT arithmetically until it has passed NUMERIC.
  • Break on accepted claims only. Rejected claims never reach the report, so a region whose claims were all rejected must not produce a total line. Do the break check inside the paragraph that accepts a claim, not straight after the READ.
  • Clear output records. A record area in the FILE SECTION isn't initialised. The starter does MOVE SPACES TO REJECT-LINE before filling it; without that GnuCOBOL refuses to write the stray bytes (status 71), and on z/OS they would go into the file.
  • The last group. The final region's total is written after the read loop ends. The starter's main line already does this.

Build it a piece at a time and submit often: the visible tests show your report and reject file next to the expected ones, and the job log shows each step's return code.

On the job

When you talk about this project in an interview, describe it the way an operations team would: "a three-step batch job: DFSORT, a COBOL validation and pricing program with a table lookup and control-break report, and a print step conditioned on the return code. Bad input goes to a reject file with reason codes; RC 4 flags rejects, RC 16 stops the job." That sentence shows you understand batch, not just syntax.

Your task

Write CLMPROC, the heart of the insurer's claims end-of-day job. Operations run it with this JCL (see the JCL tab):

  1. SORTCLM sorts the day's claims by region, then claim id, into &&SORTED.
  2. PROCESS runs your program with PARM='20261024', the run date.
  3. PRTRPT prints the report, unless PROCESS ended worse than RC 4.

DD names (all line sequential; record layouts are the copybooks CLAIMREC and POLREC, see the Copybooks tab):

DD Contents
CLAIMS sorted claims, COPY CLAIMREC (40 bytes)
POLICIES policy table, ascending POL-NO, at most 50 records, COPY POLREC
CLMRPT the report, 80-byte lines
REJECTS rejected claims: claim id, space, reason

Run date. Read PARM with ACCEPT WS-PARM FROM COMMAND-LINE. If it is not numeric, display CLMPROC INVALID RUN DATE: and the PARM, and stop with return code 16 before opening anything.

Validation. Load the policy table first. Then check each claim in this order; the first failure is the reason:

Check Reason
CLM-AMOUNT not numeric INVALID AMOUNT
CLM-TYPE not A, H or T INVALID TYPE
CLM-DATE not numeric, or after the run date INVALID DATE
CLM-POLICY not in the table POLICY NOT FOUND
policy status not A POLICY LAPSED

Pricing. Payable = claimed amount minus the policy's POL-EXCESS, but never below 0 and never above POL-LIMIT.

Report. The starter already writes the title, headings, detail lines and grand total. Add a control break on region: after the last accepted claim of each region, write the region total line (RPT-REGION-TOTAL) followed by one blank line. Regions with no accepted claims get no total line.

CLAIMS END-OF-DAY REPORT          RUN DATE 2026-10-24
REGION CLAIM ID POLICY   TYPE        CLAIMED      PAYABLE
CRK    C0000002 P0000102 HOME      12,000.00    11,500.00
  TOTAL REGION CRK   CLAIMS   1    12,000.00    11,500.00

DUB    C0000001 P0000101 AUTO       1,250.00     1,000.00
...

Return code: 4 if any claim was rejected, otherwise 0.

fixed format
Run your program to see its output here. The first visible test's input and datasets are used.
Submit to grade your program against every test.