Challenge: monthly sales report
Time to put the whole module together in the kind of report you'll be asked to change in your first month on a mainframe team: a two-level control-break report with page overflow, page numbers, signed money and a region-per-page layout.
The job
The month-end batch stream runs three steps:
- Extract every sale from the order system.
- Sort the extract by region, rep and date (a DFSORT step, or a COBOL SORT like the ones in the previous module).
- Report: your program. It reads the sorted file once, from top to bottom, and writes a report dataset that is archived and printed for the board pack.
What makes it tricky
Every technique from this module has to cooperate:
- Two control levels (rep within region), tested major first, broken bottom-up, with totals rolled upward at each break.
- Page overflow in the middle of a region, where the new page must repeat the headings with the same region.
- Forced page breaks when the region changes, so each region starts on a fresh page. The neat trick: set the line count to its "full" value and let the normal overflow check do the rest.
- Every body line goes through one paragraph that does the page check, including rep and region totals. Otherwise a total can land below the bottom of the page.
- Signed amounts. Returns are negative. The input carries the sign as a
separate leading character (
SIGN IS LEADING SEPARATE, common in files exchanged with other systems), and the edited fields end in-. - Edge cases: a region that exactly fills a page, a total that is the only line on its page, a rep whose sales net to zero, and a month with no sales at all.
Plan before you code
Sketch the paragraphs first: READ-SALE, PRINT-DETAIL, REP-BREAK,
REGION-BREAK (which performs REP-BREAK first), PRINT-LINE and
PRINT-HEADINGS. Decide which paragraph owns each counter and total, and
where each "previous key" is updated. Then write the main loop, which
should be only a few lines long.
Test with the visible case, then read the task again for the rules the hidden tests check.
On the job
Report changes are usually small ("add a column", "new page per branch"), but they touch this whole structure. Before you change one, run the old version and keep its output, then diff old and new reports line by line. Any difference you didn't intend is a bug.
Your task
Monthly sales report. The sales director wants the month's sales by region and sales rep, one region per page, ready for the board pack. The SORT step before yours has already put the file in region, rep, date order.
DD SALESIN — line sequential, 33 bytes:
| Field | PIC | Notes |
|---|---|---|
SR-REGION |
X(5) |
major control field |
SR-REP |
X(12) |
minor control field |
SR-DATE |
9(8) |
YYYYMMDD |
SR-AMOUNT |
S9(5)V99 SIGN LEADING SEPARATE |
e.g. +0125000; returns are negative |
DD RPTOUT — the report. The starter contains every print layout.
Pages are 12 lines. Each page begins with three heading lines: the
title with page number, REGION: plus the region being printed, and the
column headings. Detail, rep total and region total lines go through the
page-full check; if a page fills up in the middle of a region, continue on
a new page under the same region.
Breaks:
- rep changes → rep total line (
*) - region changes → rep total, region total (
**), and the next region starts on a new page - end of file → final rep and region totals, then the grand total
(
***) on a page of its own whose region line readsREGION: ALL. An empty file produces just that page.
MONTHLY SALES REPORT PAGE 1
REGION: NORTH
REP DATE AMOUNT
BYRNE 2026/09/01 1,250.00
BYRNE 2026/09/05 375.50
BYRNE 2026/09/20 2,100.00
TOTAL BYRNE 3,725.50 *
KELLY 2026/09/02 999.99
KELLY 2026/09/03 15,000.00
KELLY 2026/09/10 250.00-
KELLY 2026/09/11 450.25
KELLY 2026/09/15 80.00
MONTHLY SALES REPORT PAGE 2
REGION: NORTH
REP DATE AMOUNT
KELLY 2026/09/29 3,100.50
TOTAL KELLY 19,380.74 *
...
REGION NORTH TOTAL 30,357.24 **
MONTHLY SALES REPORT PAGE 3
REGION: SOUTH
...