MODULE 12 · JCL AND BATCH JOBS · 9/9

Challenge: the nightly stock run

30 min60 XPExercise

Almost every batch system has a job shaped like this one. Once you can write it, you can read most of the nightly schedule at a bank, an insurer or a retailer:

  1. Sort the day's transactions into master-file order, dropping the ones that shouldn't be processed.
  2. Update: a COBOL program matches the sorted transactions against yesterday's master and writes today's master plus a report. This is the match-merge you wrote in the sequential files module.
  3. Report: the report goes somewhere people will read it.
  4. Clean up, but only if everything worked, so a bad night can be rerun from the top.

The work in between is carried by temporary datasets. Whether each step runs is decided by return codes and COND. Each DD's disposition is chosen with the rerun in mind.

//SORTMOVE EXEC PGM=SORT
//SORTOUT  DD DSN=&&MOVES,DISP=(NEW,PASS)
  ...
//UPDATE   EXEC PGM=STKUPD
//MOVESIN  DD DSN=&&MOVES,DISP=(OLD,DELETE)
  ...
//CLEANUP  EXEC PGM=IEFBR14,COND=(4,LT)

Plan it on paper first: list each step, its program, every DD with its dataset and DISP, and the RCs for which the step must run. Then write the JCL, and read the job log after every run, including the ones that pass.

How this looks in production

  • The master file would be a GDG (generation data group): DSN=STOCK.MASTER(0) is the current generation, and DSN=STOCK.MASTER(+1),DISP=(NEW,CATLG,DELETE) creates the next. The catalog keeps the last n generations, so yesterday's master is always available for a rerun and no job has to rename anything.
  • The steps would probably live in a catalogued procedure (//NIGHTLY EXEC STKPROC), with symbolic parameters such as &DATE, so test and production run identical JCL with different dataset prefixes.
  • The job would be submitted by the scheduler once the warehouse feed has arrived, and a failed run would page the on-call developer, who opens the job log you have learned to read.

On the job

When you change a job like this, test the failure paths too: feed it an empty file, an unknown item and an out-of-sequence file in a test region, and check which steps run and which datasets survive. Most batch production incidents are in the paths that "never happen".

Your task

Module challenge. Write the warehouse's nightly stock job, STKNIGHT, from the outline in the starter. Four steps, in this order:

1. SORTMOVE (SORT). Read today's movements, STOCK.MOVES.DAILY (keep it; step 4 deals with it). Omit voided movements and sort the rest by item code, then by time, both ascending. Pass the result to step 2 as the temporary dataset &&MOVES.

Field Positions Format
Item code 1–6 CH
Type (R receipt, I issue) 7 CH
Quantity 8–12 ZD
Time (HHMM) 13–16 CH
Void flag (V = voided) 17 CH

2. UPDATE runs the update program STKUPD (already written):

DD Dataset Notes
MASTIN STOCK.MASTER Yesterday's master, read-only
MOVESIN &&MOVES Sorted movements; delete after this step
MASTOUT STOCK.MASTER.NEW Today's master: new, cataloged, deleted on abend
RPTOUT &&STKRPT The stock report, passed to step 3
SYSOUT spool

STKUPD ends with RC 0 if all went well, RC 4 if some movements were for unknown items, RC 8 if an item's stock would go negative, and RC 12 if its input isn't sorted or still contains voids.

3. PRINT (IEBGENER) copies the report &&STKRPT to a new cataloged dataset STOCK.REPORT.DAILY, where the report distribution system picks it up. It runs when UPDATE ended with RC 8 or less: the warehouse needs the report most when there's a problem.

4. CLEANUP (IEFBR14) deletes STOCK.MOVES.DAILY, but only when every earlier step ended with RC 4 or less. After a worse night the movements must be kept so the job can be rerun.

In production the master would be a GDG (STOCK.MASTER(0) in, STOCK.MASTER(+1) out), but here the two generations are simply STOCK.MASTER and STOCK.MASTER.NEW.

JCL
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.